// // modifiers.cs: Modifier handling. // using System; using System.Reflection; namespace Mono.CSharp { [Flags] public enum Modifiers { // // The ordering of the following 4 constants // has been carefully done. // PROTECTED = 0x0001, PUBLIC = 0x0002, PRIVATE = 0x0004, INTERNAL = 0x0008, NEW = 0x0010, ABSTRACT = 0x0020, SEALED = 0x0040, STATIC = 0x0080, READONLY = 0x0100, VIRTUAL = 0x0200, OVERRIDE = 0x0400, EXTERN = 0x0800, VOLATILE = 0x1000, UNSAFE = 0x2000, TOP = 0x4000, // // Compiler specific flags // PROPERTY_CUSTOM = 0x4000, PARTIAL = 0x20000, DEFAULT_ACCESS_MODIFER = 0x40000, METHOD_EXTENSION = 0x80000, COMPILER_GENERATED = 0x100000, BACKING_FIELD = 0x200000, DEBUGGER_HIDDEN = 0x400000, AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE, AllowedExplicitImplFlags = UNSAFE | EXTERN, } static class ModifiersExtensions { static public string Name (Modifiers i) { string s = ""; switch (i) { case Modifiers.NEW: s = "new"; break; case Modifiers.PUBLIC: s = "public"; break; case Modifiers.PROTECTED: s = "protected"; break; case Modifiers.INTERNAL: s = "internal"; break; case Modifiers.PRIVATE: s = "private"; break; case Modifiers.ABSTRACT: s = "abstract"; break; case Modifiers.SEALED: s = "sealed"; break; case Modifiers.STATIC: s = "static"; break; case Modifiers.READONLY: s = "readonly"; break; case Modifiers.VIRTUAL: s = "virtual"; break; case Modifiers.OVERRIDE: s = "override"; break; case Modifiers.EXTERN: s = "extern"; break; case Modifiers.VOLATILE: s = "volatile"; break; case Modifiers.UNSAFE: s = "unsafe"; break; } return s; } public static string GetDescription (MethodAttributes ma) { ma &= MethodAttributes.MemberAccessMask; if (ma == MethodAttributes.Assembly) return "internal"; if (ma == MethodAttributes.Family) return "protected"; if (ma == MethodAttributes.Public) return "public"; if (ma == MethodAttributes.FamORAssem) return "protected internal"; if (ma == MethodAttributes.Private) return "private"; throw new NotImplementedException (ma.ToString ()); } public static TypeAttributes TypeAttr (Modifiers mod_flags, bool is_toplevel) { TypeAttributes t = 0; if (is_toplevel){ if ((mod_flags & Modifiers.PUBLIC) != 0) t = TypeAttributes.Public; else if ((mod_flags & Modifiers.PRIVATE) != 0) t = TypeAttributes.NotPublic; } else { if ((mod_flags & Modifiers.PUBLIC) != 0) t = TypeAttributes.NestedPublic; else if ((mod_flags & Modifiers.PRIVATE) != 0) t = TypeAttributes.NestedPrivate; else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) t = TypeAttributes.NestedFamORAssem; else if ((mod_flags & Modifiers.PROTECTED) != 0) t = TypeAttributes.NestedFamily; else if ((mod_flags & Modifiers.INTERNAL) != 0) t = TypeAttributes.NestedAssembly; } if ((mod_flags & Modifiers.SEALED) != 0) t |= TypeAttributes.Sealed; if ((mod_flags & Modifiers.ABSTRACT) != 0) t |= TypeAttributes.Abstract; return t; } public static FieldAttributes FieldAttr (Modifiers mod_flags) { FieldAttributes fa = 0; if ((mod_flags & Modifiers.PUBLIC) != 0) fa |= FieldAttributes.Public; if ((mod_flags & Modifiers.PRIVATE) != 0) fa |= FieldAttributes.Private; if ((mod_flags & Modifiers.PROTECTED) != 0) { if ((mod_flags & Modifiers.INTERNAL) != 0) fa |= FieldAttributes.FamORAssem; else fa |= FieldAttributes.Family; } else { if ((mod_flags & Modifiers.INTERNAL) != 0) fa |= FieldAttributes.Assembly; } if ((mod_flags & Modifiers.STATIC) != 0) fa |= FieldAttributes.Static; if ((mod_flags & Modifiers.READONLY) != 0) fa |= FieldAttributes.InitOnly; return fa; } public static MethodAttributes MethodAttr (Modifiers mod_flags) { MethodAttributes ma = MethodAttributes.HideBySig; if ((mod_flags & Modifiers.PUBLIC) != 0) ma |= MethodAttributes.Public; else if ((mod_flags & Modifiers.PRIVATE) != 0) ma |= MethodAttributes.Private; else if ((mod_flags & Modifiers.PROTECTED) != 0) { if ((mod_flags & Modifiers.INTERNAL) != 0) ma |= MethodAttributes.FamORAssem; else ma |= MethodAttributes.Family; } else { if ((mod_flags & Modifiers.INTERNAL) != 0) ma |= MethodAttributes.Assembly; } if ((mod_flags & Modifiers.STATIC) != 0) ma |= MethodAttributes.Static; if ((mod_flags & Modifiers.ABSTRACT) != 0) { ma |= MethodAttributes.Abstract | MethodAttributes.Virtual; } if ((mod_flags & Modifiers.SEALED) != 0) ma |= MethodAttributes.Final; if ((mod_flags & Modifiers.VIRTUAL) != 0) ma |= MethodAttributes.Virtual; if ((mod_flags & Modifiers.OVERRIDE) != 0) ma |= MethodAttributes.Virtual; else { if ((ma & MethodAttributes.Virtual) != 0) ma |= MethodAttributes.NewSlot; } return ma; } // // Checks the object @mod modifiers to be in @allowed. // Returns the new mask. Side effect: reports any // incorrect attributes. // public static Modifiers Check (Modifiers allowed, Modifiers mod, Modifiers def_access, Location l, Report Report) { int invalid_flags = (~(int) allowed) & ((int) mod & ((int) Modifiers.TOP - 1)); int i; if (invalid_flags == 0){ if ((mod & Modifiers.UNSAFE) != 0){ RootContext.CheckUnsafeOption (l, Report); } // // If no accessibility bits provided // then provide the defaults. // if ((mod & Modifiers.AccessibilityMask) == 0) { mod |= def_access; if (def_access != 0) mod |= Modifiers.DEFAULT_ACCESS_MODIFER; return mod; } // // Make sure that no conflicting accessibility // bits have been set. Protected+Internal is // allowed, that is why they are placed on bits // 1 and 4 (so the shift 3 basically merges them) // int a = (int) mod; a &= 15; a |= (a >> 3); a = ((a & 2) >> 1) + (a & 5); a = ((a & 4) >> 2) + (a & 3); if (a > 1) Report.Error (107, l, "More than one protection modifier specified", Report); return mod; } for (i = 1; i <= (int) Modifiers.TOP; i <<= 1) { if ((i & invalid_flags) == 0) continue; Error_InvalidModifier (l, Name ((Modifiers) i), Report); } return allowed & mod; } public static void Error_InvalidModifier (Location l, string name, Report Report) { Report.Error (106, l, "The modifier `" + name + "' is not valid for this item", Report); } } }