Add more checks for async modifier
[mono.git] / mcs / mcs / modifiers.cs
1 //
2 // modifiers.cs: Modifiers handling
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Marek Safar (marek.safar@gmail.com)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2004-2010 Novell, Inc
11 //
12
13 using System;
14
15 #if STATIC
16 using IKVM.Reflection;
17 #else
18 using System.Reflection;
19 #endif
20
21 namespace Mono.CSharp
22 {
23         [Flags]
24         public enum Modifiers
25         {
26                 PROTECTED = 0x0001,
27                 PUBLIC    = 0x0002,
28                 PRIVATE   = 0x0004,
29                 INTERNAL  = 0x0008,
30                 NEW       = 0x0010,
31                 ABSTRACT  = 0x0020,
32                 SEALED    = 0x0040,
33                 STATIC    = 0x0080,
34                 READONLY  = 0x0100,
35                 VIRTUAL   = 0x0200,
36                 OVERRIDE  = 0x0400,
37                 EXTERN    = 0x0800,
38                 VOLATILE  = 0x1000,
39                 UNSAFE    = 0x2000,
40                 ASYNC     = 0x4000,
41                 TOP       = 0x8000,
42
43                 //
44                 // Compiler specific flags
45                 //
46                 PROPERTY_CUSTOM                 = 0x10000,
47
48                 PARTIAL                                 = 0x20000,
49                 DEFAULT_ACCESS_MODIFER  = 0x40000,
50                 METHOD_EXTENSION                = 0x80000,
51                 COMPILER_GENERATED              = 0x100000,
52                 BACKING_FIELD                   = 0x200000,
53                 DEBUGGER_HIDDEN                 = 0x400000,
54
55                 AccessibilityMask = PUBLIC | PROTECTED | INTERNAL | PRIVATE,
56                 AllowedExplicitImplFlags = UNSAFE | EXTERN,
57         }
58
59         static class ModifiersExtensions
60         {
61                 public static string AccessibilityName (Modifiers mod)
62                 {
63                         switch (mod & Modifiers.AccessibilityMask) {
64                         case Modifiers.PUBLIC:
65                                 return "public";
66                         case Modifiers.PROTECTED:
67                                 return "protected";
68                         case Modifiers.PROTECTED | Modifiers.INTERNAL:
69                                 return "protected internal";
70                         case Modifiers.INTERNAL:
71                                 return "internal";
72                         case Modifiers.PRIVATE:
73                                 return "private";
74                         default:
75                                 throw new NotImplementedException (mod.ToString ());
76                         }
77                 }
78
79                 static public string Name (Modifiers i)
80                 {
81                         string s = "";
82                         
83                         switch (i) {
84                         case Modifiers.NEW:
85                                 s = "new"; break;
86                         case Modifiers.PUBLIC:
87                                 s = "public"; break;
88                         case Modifiers.PROTECTED:
89                                 s = "protected"; break;
90                         case Modifiers.INTERNAL:
91                                 s = "internal"; break;
92                         case Modifiers.PRIVATE:
93                                 s = "private"; break;
94                         case Modifiers.ABSTRACT:
95                                 s = "abstract"; break;
96                         case Modifiers.SEALED:
97                                 s = "sealed"; break;
98                         case Modifiers.STATIC:
99                                 s = "static"; break;
100                         case Modifiers.READONLY:
101                                 s = "readonly"; break;
102                         case Modifiers.VIRTUAL:
103                                 s = "virtual"; break;
104                         case Modifiers.OVERRIDE:
105                                 s = "override"; break;
106                         case Modifiers.EXTERN:
107                                 s = "extern"; break;
108                         case Modifiers.VOLATILE:
109                                 s = "volatile"; break;
110                         case Modifiers.UNSAFE:
111                                 s = "unsafe"; break;
112                         case Modifiers.ASYNC:
113                                 s = "async"; break;
114                         }
115
116                         return s;
117                 }
118
119                 //
120                 // Used by custom property accessors to check whether @modA is more restrictive than @modB
121                 //
122                 public static bool IsRestrictedModifier (Modifiers modA, Modifiers modB)
123                 {
124                         Modifiers flags = 0;
125
126                         if ((modB & Modifiers.PUBLIC) != 0) {
127                                 flags = Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
128                         } else if ((modB & Modifiers.PROTECTED) != 0) {
129                                 if ((modB & Modifiers.INTERNAL) != 0)
130                                         flags = Modifiers.PROTECTED | Modifiers.INTERNAL;
131
132                                 flags |= Modifiers.PRIVATE;
133                         } else if ((modB & Modifiers.INTERNAL) != 0)
134                                 flags = Modifiers.PRIVATE;
135
136                         return modB != modA && (modA & (~flags)) == 0;
137                 }
138
139                 public static TypeAttributes TypeAttr (Modifiers mod_flags, bool is_toplevel)
140                 {
141                         TypeAttributes t = 0;
142
143                         if (is_toplevel){
144                                 if ((mod_flags & Modifiers.PUBLIC) != 0)
145                                         t = TypeAttributes.Public;
146                                 else if ((mod_flags & Modifiers.PRIVATE) != 0)
147                                         t = TypeAttributes.NotPublic;
148                         } else {
149                                 if ((mod_flags & Modifiers.PUBLIC) != 0)
150                                         t = TypeAttributes.NestedPublic;
151                                 else if ((mod_flags & Modifiers.PRIVATE) != 0)
152                                         t = TypeAttributes.NestedPrivate;
153                                 else if ((mod_flags & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL))
154                                         t = TypeAttributes.NestedFamORAssem;
155                                 else if ((mod_flags & Modifiers.PROTECTED) != 0)
156                                         t = TypeAttributes.NestedFamily;
157                                 else if ((mod_flags & Modifiers.INTERNAL) != 0)
158                                         t = TypeAttributes.NestedAssembly;
159                         }
160
161                         if ((mod_flags & Modifiers.SEALED) != 0)
162                                 t |= TypeAttributes.Sealed;
163                         if ((mod_flags & Modifiers.ABSTRACT) != 0)
164                                 t |= TypeAttributes.Abstract;
165
166                         return t;
167                 }
168
169                 public static FieldAttributes FieldAttr (Modifiers mod_flags)
170                 {
171                         FieldAttributes fa = 0;
172
173                         if ((mod_flags & Modifiers.PUBLIC) != 0)
174                                 fa |= FieldAttributes.Public;
175                         if ((mod_flags & Modifiers.PRIVATE) != 0)
176                                 fa |= FieldAttributes.Private;
177                         if ((mod_flags & Modifiers.PROTECTED) != 0) {
178                                 if ((mod_flags & Modifiers.INTERNAL) != 0)
179                                         fa |= FieldAttributes.FamORAssem;
180                                 else 
181                                         fa |= FieldAttributes.Family;
182                         } else {
183                                 if ((mod_flags & Modifiers.INTERNAL) != 0)
184                                         fa |= FieldAttributes.Assembly;
185                         }
186
187                         if ((mod_flags & Modifiers.STATIC) != 0)
188                                 fa |= FieldAttributes.Static;
189                         if ((mod_flags & Modifiers.READONLY) != 0)
190                                 fa |= FieldAttributes.InitOnly;
191
192                         return fa;
193                 }
194
195                 public static MethodAttributes MethodAttr (Modifiers mod_flags)
196                 {
197                         MethodAttributes ma = MethodAttributes.HideBySig;
198
199                         switch (mod_flags & Modifiers.AccessibilityMask) {
200                         case Modifiers.PUBLIC:
201                                 ma |= MethodAttributes.Public;
202                                 break;
203                         case Modifiers.PRIVATE:
204                                 ma |= MethodAttributes.Private;
205                                 break;
206                         case Modifiers.PROTECTED | Modifiers.INTERNAL:
207                                 ma |= MethodAttributes.FamORAssem;
208                                 break;
209                         case Modifiers.PROTECTED:
210                                 ma |= MethodAttributes.Family;
211                                 break;
212                         case Modifiers.INTERNAL:
213                                 ma |= MethodAttributes.Assembly;
214                                 break;
215                         default:
216                                 throw new NotImplementedException (mod_flags.ToString ());
217                         }
218
219                         if ((mod_flags & Modifiers.STATIC) != 0)
220                                 ma |= MethodAttributes.Static;
221                         if ((mod_flags & Modifiers.ABSTRACT) != 0) {
222                                 ma |= MethodAttributes.Abstract | MethodAttributes.Virtual;
223                         }
224                         if ((mod_flags & Modifiers.SEALED) != 0)
225                                 ma |= MethodAttributes.Final;
226
227                         if ((mod_flags & Modifiers.VIRTUAL) != 0)
228                                 ma |= MethodAttributes.Virtual;
229
230                         if ((mod_flags & Modifiers.OVERRIDE) != 0) {
231                                 ma |= MethodAttributes.Virtual;
232                         } else {
233                                 if ((ma & MethodAttributes.Virtual) != 0)
234                                         ma |= MethodAttributes.NewSlot;
235                         }
236                         
237                         return ma;
238                 }
239
240                 // <summary>
241                 //   Checks the object @mod modifiers to be in @allowed.
242                 //   Returns the new mask.  Side effect: reports any
243                 //   incorrect attributes. 
244                 // </summary>
245                 public static Modifiers Check (Modifiers allowed, Modifiers mod, Modifiers def_access, Location l, Report Report)
246                 {
247                         int invalid_flags = (~(int) allowed) & ((int) mod & ((int) Modifiers.TOP - 1));
248                         int i;
249
250                         if (invalid_flags == 0){
251                                 //
252                                 // If no accessibility bits provided
253                                 // then provide the defaults.
254                                 //
255                                 if ((mod & Modifiers.AccessibilityMask) == 0) {
256                                         mod |= def_access;
257                                         if (def_access != 0)
258                                                 mod |= Modifiers.DEFAULT_ACCESS_MODIFER;
259                                         return mod;
260                                 }
261
262                                 return mod;
263                         }
264
265                         for (i = 1; i <= (int) Modifiers.TOP; i <<= 1) {
266                                 if ((i & invalid_flags) == 0)
267                                         continue;
268
269                                 Error_InvalidModifier ((Modifiers)i, l, Report);
270                         }
271
272                         return allowed & mod;
273                 }
274
275                 static void Error_InvalidModifier (Modifiers mod, Location l, Report Report)
276                 {
277                         Report.Error (106, l, "The modifier `{0}' is not valid for this item",
278                                 Name (mod));
279                 }
280         }
281 }