Merge pull request #4710 from Unity-Technologies/additional-config-checks
[mono.git] / mcs / mcs / modifiers.cs
index 961a0912d6fc31e09f0e75a20f1db03b0eb283e5..bfae5985a0345f1d5058e6e6586618d0fd185ba1 100644 (file)
@@ -1,51 +1,84 @@
 //
-// modifiers.cs: Modifier handling.
-// 
+// modifiers.cs: Modifiers handling
+//
+// Authors: Miguel de Icaza (miguel@gnu.org)
+//          Marek Safar (marek.safar@gmail.com)
+//
+// Dual licensed under the terms of the MIT X11 or GNU GPL
+//
+// Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
+// Copyright 2004-2010 Novell, Inc
+//
+
 using System;
+
+#if STATIC
+using IKVM.Reflection;
+#else
 using System.Reflection;
+#endif
 
-namespace Mono.CSharp {
-       public class Modifiers {
+namespace Mono.CSharp
+{
+       [Flags]
+       public enum Modifiers
+       {
+               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,
+               ASYNC     = 0x4000,
+               TOP       = 0x8000,
 
                //
-               // The ordering of the following 4 constants
-               // has been carefully done.
+               // Compiler specific flags
                //
-               public const int PROTECTED = 0x0001;
-               public const int PUBLIC    = 0x0002;
-               public const int PRIVATE   = 0x0004;
-               public const int INTERNAL  = 0x0008;
-               public const int NEW       = 0x0010;
-               public const int ABSTRACT  = 0x0020;
-               public const int SEALED    = 0x0040;
-               public const int STATIC    = 0x0080;
-               public const int READONLY  = 0x0100;
-               public const int VIRTUAL   = 0x0200;
-               public const int OVERRIDE  = 0x0400;
-               public const int EXTERN    = 0x0800;
-               public const int VOLATILE  = 0x1000;
-               public const int UNSAFE    = 0x2000;
-               private const int TOP      = 0x2000;
-
-               public const int PROPERTY_CUSTOM = 0x4000; // Custom property modifier
+               PROPERTY_CUSTOM                 = 0x10000,
 
-               //
-               // We use this internally to flag that the method contains an iterator
-               //
-               public const int METHOD_YIELDS                  = 0x8000;
-               public const int METHOD_GENERIC                 = 0x10000;
-               public const int PARTIAL                                = 0x20000;
-               public const int DEFAULT_ACCESS_MODIFER = 0x40000;
-               public const int METHOD_EXTENSION               = 0x80000;
-               public const int COMPILER_GENERATED             = 0x100000;
-               public const int BACKING_FIELD                  = 0x200000 | COMPILER_GENERATED;
-
-               public const int Accessibility =
-                       PUBLIC | PROTECTED | INTERNAL | PRIVATE;
-               public const int AllowedExplicitImplFlags =
-                       UNSAFE | EXTERN;
-               
-               static public string Name (int i)
+               PARTIAL                                 = 0x20000,
+               DEFAULT_ACCESS_MODIFIER = 0x40000,
+               METHOD_EXTENSION                = 0x80000,
+               COMPILER_GENERATED              = 0x100000,
+               BACKING_FIELD                   = 0x200000,
+               DEBUGGER_HIDDEN                 = 0x400000,
+               DEBUGGER_STEP_THROUGH   = 0x800000,
+               AutoProperty                    = 0x1000000,
+
+               AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE,
+               AllowedExplicitImplFlags = UNSAFE | EXTERN,
+       }
+
+       static class ModifiersExtensions
+       {
+               public static string AccessibilityName (Modifiers mod)
+               {
+                       switch (mod & Modifiers.AccessibilityMask) {
+                       case Modifiers.PUBLIC:
+                               return "public";
+                       case Modifiers.PROTECTED:
+                               return "protected";
+                       case Modifiers.PROTECTED | Modifiers.INTERNAL:
+                               return "protected internal";
+                       case Modifiers.INTERNAL:
+                               return "internal";
+                       case Modifiers.PRIVATE:
+                               return "private";
+                       default:
+                               throw new NotImplementedException (mod.ToString ());
+                       }
+               }
+
+               static public string Name (Modifiers i)
                {
                        string s = "";
                        
@@ -78,121 +111,127 @@ namespace Mono.CSharp {
                                s = "volatile"; break;
                        case Modifiers.UNSAFE:
                                s = "unsafe"; break;
+                       case Modifiers.ASYNC:
+                               s = "async"; break;
                        }
 
                        return s;
                }
 
-               public static string GetDescription (MethodAttributes ma)
+               //
+               // Used by custom property accessors to check whether @modA is more restrictive than @modB
+               //
+               public static bool IsRestrictedModifier (Modifiers modA, Modifiers modB)
                {
-                       ma &= MethodAttributes.MemberAccessMask;
+                       Modifiers flags = 0;
 
-                       if (ma == MethodAttributes.Assembly)
-                               return "internal";
-
-                       if (ma == MethodAttributes.Family)
-                               return "protected";
+                       if ((modB & Modifiers.PUBLIC) != 0) {
+                               flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
+                       } else if ((modB & Modifiers.PROTECTED) != 0) {
+                               if ((modB & Modifiers.INTERNAL) != 0)
+                                       flags = Modifiers.PROTECTED | Modifiers.INTERNAL;
 
-                       if (ma == MethodAttributes.Public)
-                               return "public";
+                               flags |= Modifiers.PRIVATE;
+                       } else if ((modB & Modifiers.INTERNAL) != 0)
+                               flags = Modifiers.PRIVATE;
 
-                       if (ma == MethodAttributes.FamANDAssem)
-                               return "protected internal";
-
-                       if (ma == MethodAttributes.Private)
-                               return "private";
-
-                       throw new NotImplementedException (ma.ToString ());
+                       return modB != modA && (modA & (~flags)) == 0;
                }
 
-               public static TypeAttributes TypeAttr (int mod_flags, bool is_toplevel)
+               public static TypeAttributes TypeAttr (Modifiers mod_flags, bool is_toplevel)
                {
                        TypeAttributes t = 0;
 
                        if (is_toplevel){
-                               if ((mod_flags & PUBLIC) != 0)
-                                       t |= TypeAttributes.Public;
-                               if ((mod_flags & PRIVATE) != 0)
-                                       t |= TypeAttributes.NotPublic;
+                               if ((mod_flags & Modifiers.PUBLIC) != 0)
+                                       t = TypeAttributes.Public;
+                               else if ((mod_flags & Modifiers.PRIVATE) != 0)
+                                       t = TypeAttributes.NotPublic;
                        } else {
-                               if ((mod_flags & PUBLIC) != 0)
-                                       t |= TypeAttributes.NestedPublic;
-                               if ((mod_flags & PRIVATE) != 0)
-                                       t |= TypeAttributes.NestedPrivate;
-                               if ((mod_flags & PROTECTED) != 0 && (mod_flags & INTERNAL) != 0)
-                                       t |= TypeAttributes.NestedFamORAssem;
-                               if ((mod_flags & PROTECTED) != 0)
-                                       t |= TypeAttributes.NestedFamily;
-                               if ((mod_flags & INTERNAL) != 0)
-                                       t |= TypeAttributes.NestedAssembly;
+                               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 & SEALED) != 0)
+
+                       if ((mod_flags & Modifiers.SEALED) != 0)
                                t |= TypeAttributes.Sealed;
-                       if ((mod_flags & ABSTRACT) != 0)
+                       if ((mod_flags & Modifiers.ABSTRACT) != 0)
                                t |= TypeAttributes.Abstract;
 
                        return t;
                }
 
-               public static FieldAttributes FieldAttr (int mod_flags)
+               public static FieldAttributes FieldAttr (Modifiers mod_flags)
                {
                        FieldAttributes fa = 0;
 
-                       if ((mod_flags & PUBLIC) != 0)
+                       if ((mod_flags & Modifiers.PUBLIC) != 0)
                                fa |= FieldAttributes.Public;
-                       if ((mod_flags & PRIVATE) != 0)
+                       if ((mod_flags & Modifiers.PRIVATE) != 0)
                                fa |= FieldAttributes.Private;
-                       if ((mod_flags & PROTECTED) != 0){
-                               if ((mod_flags & INTERNAL) != 0)
+                       if ((mod_flags & Modifiers.PROTECTED) != 0) {
+                               if ((mod_flags & Modifiers.INTERNAL) != 0)
                                        fa |= FieldAttributes.FamORAssem;
                                else 
                                        fa |= FieldAttributes.Family;
                        } else {
-                               if ((mod_flags & INTERNAL) != 0)
+                               if ((mod_flags & Modifiers.INTERNAL) != 0)
                                        fa |= FieldAttributes.Assembly;
                        }
-                       
-                       if ((mod_flags & STATIC) != 0)
+
+                       if ((mod_flags & Modifiers.STATIC) != 0)
                                fa |= FieldAttributes.Static;
-                       if ((mod_flags & READONLY) != 0)
+                       if ((mod_flags & Modifiers.READONLY) != 0)
                                fa |= FieldAttributes.InitOnly;
 
                        return fa;
                }
 
-               public static MethodAttributes MethodAttr (int mod_flags)
+               public static MethodAttributes MethodAttr (Modifiers mod_flags)
                {
                        MethodAttributes ma = MethodAttributes.HideBySig;
 
-                       if ((mod_flags & PUBLIC) != 0)
+                       switch (mod_flags & Modifiers.AccessibilityMask) {
+                       case Modifiers.PUBLIC:
                                ma |= MethodAttributes.Public;
-                       else if ((mod_flags & PRIVATE) != 0)
+                               break;
+                       case Modifiers.PRIVATE:
                                ma |= MethodAttributes.Private;
-                       else if ((mod_flags & PROTECTED) != 0){
-                               if ((mod_flags & INTERNAL) != 0)
-                                       ma |= MethodAttributes.FamORAssem;
-                               else 
-                                       ma |= MethodAttributes.Family;
-                       } else {
-                               if ((mod_flags & INTERNAL) != 0)
-                                       ma |= MethodAttributes.Assembly;
+                               break;
+                       case Modifiers.PROTECTED | Modifiers.INTERNAL:
+                               ma |= MethodAttributes.FamORAssem;
+                               break;
+                       case Modifiers.PROTECTED:
+                               ma |= MethodAttributes.Family;
+                               break;
+                       case Modifiers.INTERNAL:
+                               ma |= MethodAttributes.Assembly;
+                               break;
+                       default:
+                               throw new NotImplementedException (mod_flags.ToString ());
                        }
 
-                       if ((mod_flags & STATIC) != 0)
+                       if ((mod_flags & Modifiers.STATIC) != 0)
                                ma |= MethodAttributes.Static;
-                       if ((mod_flags & ABSTRACT) != 0){
+                       if ((mod_flags & Modifiers.ABSTRACT) != 0) {
                                ma |= MethodAttributes.Abstract | MethodAttributes.Virtual;
                        }
-                       if ((mod_flags & SEALED) != 0)
+                       if ((mod_flags & Modifiers.SEALED) != 0)
                                ma |= MethodAttributes.Final;
 
-                       if ((mod_flags & VIRTUAL) != 0)
+                       if ((mod_flags & Modifiers.VIRTUAL) != 0)
                                ma |= MethodAttributes.Virtual;
 
-                       if ((mod_flags & OVERRIDE) != 0)
+                       if ((mod_flags & Modifiers.OVERRIDE) != 0) {
                                ma |= MethodAttributes.Virtual;
-                       else {
+                       else {
                                if ((ma & MethodAttributes.Virtual) != 0)
                                        ma |= MethodAttributes.NewSlot;
                        }
@@ -205,58 +244,40 @@ namespace Mono.CSharp {
                //   Returns the new mask.  Side effect: reports any
                //   incorrect attributes. 
                // </summary>
-               public static int Check (int allowed, int mod, int def_access, Location l)
+               public static Modifiers Check (Modifiers allowed, Modifiers mod, Modifiers def_access, Location l, Report Report)
                {
-                       int invalid_flags  = (~allowed) & (mod & (Modifiers.TOP - 1));
+                       int invalid_flags = (~(int) allowed) & ((int) mod & ((int) Modifiers.TOP - 1));
                        int i;
 
                        if (invalid_flags == 0){
-                               int a = mod;
-
-                               if ((mod & Modifiers.UNSAFE) != 0){
-                                       RootContext.CheckUnsafeOption (l);
-                               }
-                               
                                //
                                // If no accessibility bits provided
                                // then provide the defaults.
                                //
-                               if ((mod & Accessibility) == 0){
+                               if ((mod & Modifiers.AccessibilityMask) == 0) {
                                        mod |= def_access;
                                        if (def_access != 0)
-                                               mod |= DEFAULT_ACCESS_MODIFER;
+                                               mod |= Modifiers.DEFAULT_ACCESS_MODIFIER;
                                        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)
-                               //
-                               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");
-                               
                                return mod;
                        }
-                       
-                       for (i = 1; i <= TOP; i <<= 1){
+
+                       for (i = 1; i < (int) Modifiers.TOP; i <<= 1) {
                                if ((i & invalid_flags) == 0)
                                        continue;
 
-                               Error_InvalidModifier (l, Name (i));
+                               Error_InvalidModifier ((Modifiers)i, l, Report);
                        }
 
                        return allowed & mod;
                }
 
-               public static void Error_InvalidModifier (Location l, string name)
+               static void Error_InvalidModifier (Modifiers mod, Location l, Report Report)
                {
-                       Report.Error (106, l, "The modifier `" + name + "' is not valid for this item");
+                       Report.Error (106, l, "The modifier `{0}' is not valid for this item",
+                               Name (mod));
                }
        }
 }