Fix LinearGradientMode parameter validation to match corefx (#5672)
[mono.git] / mcs / mcs / module.cs
1 //
2 // module.cs: keeps a tree representation of the generated code
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-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
11 // Copyright 2011 Xamarin Inc
12 //
13
14 using System;
15 using System.Collections.Generic;
16 using System.Runtime.InteropServices;
17 using Mono.CompilerServices.SymbolWriter;
18 using System.Linq;
19 using System.IO;
20 using System.Security.Cryptography;
21 using Mono.Security.Cryptography;
22
23 #if STATIC
24 using IKVM.Reflection;
25 using IKVM.Reflection.Emit;
26 #else
27 using System.Reflection;
28 using System.Reflection.Emit;
29 #endif
30
31 namespace Mono.CSharp
32 {
33         //
34         // Module (top-level type) container
35         //
36         public sealed class ModuleContainer : TypeContainer
37         {
38 #if STATIC
39                 //
40                 // Compiler generated container for static data
41                 //
42                 sealed class StaticDataContainer : CompilerGeneratedContainer
43                 {
44                         readonly Dictionary<int, Struct> size_types;
45                         readonly Dictionary<string, FieldSpec> data_hashes;
46
47                         public StaticDataContainer (ModuleContainer module)
48                                 : base (module, new MemberName ("<PrivateImplementationDetails>", Location.Null),
49                                         Modifiers.STATIC | Modifiers.INTERNAL)
50                         {
51                                 size_types = new Dictionary<int, Struct> ();
52                                 data_hashes = new Dictionary<string, FieldSpec> (StringComparer.Ordinal);
53                         }
54
55                         public override void CloseContainer ()
56                         {
57                                 base.CloseContainer ();
58
59                                 foreach (var entry in size_types) {
60                                         entry.Value.CloseContainer ();
61                                 }
62                         }
63
64                         public FieldSpec DefineInitializedData (byte[] data, Location loc)
65                         {
66                                 Struct size_type;
67                                 if (!size_types.TryGetValue (data.Length, out size_type)) {
68                                         //
69                                         // Build common type for this data length. We cannot use
70                                         // DefineInitializedData because it creates public type,
71                                         // and its name is not unique among modules
72                                         //
73                                         size_type = new Struct (this, new MemberName ("$ArrayType=" + data.Length, loc), Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED, null);
74                                         size_type.CreateContainer ();
75                                         size_type.DefineContainer ();
76
77                                         size_types.Add (data.Length, size_type);
78
79                                         // It has to work even if StructLayoutAttribute does not exist
80                                         size_type.TypeBuilder.__SetLayout (1, data.Length);
81                                 }
82
83                                 FieldSpec fs;
84                                 var data_hash = GenerateDataFieldName (data);
85                                 if (!data_hashes.TryGetValue (data_hash, out fs)) {
86                                         var name = "$field-" + data_hash;
87                                         const Modifiers fmod = Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.READONLY;
88                                         var fbuilder = TypeBuilder.DefineField (name, size_type.CurrentType.GetMetaInfo (), ModifiersExtensions.FieldAttr (fmod) | FieldAttributes.HasFieldRVA);
89                                         fbuilder.__SetDataAndRVA (data);
90
91                                         fs = new FieldSpec (CurrentType, null, size_type.CurrentType, fbuilder, fmod);
92                                         data_hashes.Add (data_hash, fs);
93                                 }
94
95                                 return fs;
96                         }
97
98                         static string GenerateDataFieldName (byte[] bytes)
99                         {
100                                 using (var hashProvider = new SHA1CryptoServiceProvider ())
101                                 {
102                                         return CryptoConvert.ToHex (hashProvider.ComputeHash (bytes));
103                                 }
104                         }
105                 }
106
107                 StaticDataContainer static_data;
108
109                 //
110                 // Makes const data field inside internal type container
111                 //
112                 public FieldSpec MakeStaticData (byte[] data, Location loc)
113                 {
114                         if (static_data == null) {
115                                 static_data = new StaticDataContainer (this);
116                                 static_data.CreateContainer ();
117                                 static_data.DefineContainer ();
118
119                                 AddCompilerGeneratedClass (static_data);
120                         }
121
122                         return static_data.DefineInitializedData (data, loc);
123                 }
124 #endif
125
126                 public sealed class PatternMatchingHelper : CompilerGeneratedContainer
127                 {
128                         public PatternMatchingHelper (ModuleContainer module)
129                                 : base (module, new MemberName ("<PatternMatchingHelper>", Location.Null),
130                                         Modifiers.STATIC | Modifiers.INTERNAL | Modifiers.DEBUGGER_HIDDEN)
131                         {
132                         }
133
134                         public Method NumberMatcher { get; private set; }
135
136                         protected override bool DoDefineMembers ()
137                         {
138                                 if (!base.DoDefineMembers ())
139                                         return false;
140
141                                 NumberMatcher = GenerateNumberMatcher ();
142                                 return true;
143                         }
144
145                         Method GenerateNumberMatcher ()
146                         {
147                                 var loc = Location;
148                                 var parameters = ParametersCompiled.CreateFullyResolved (
149                                         new [] {
150                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "obj", 0, null, loc),
151                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Object, loc), "value", 0, null, loc),
152                                                 new Parameter (new TypeExpression (Compiler.BuiltinTypes.Bool, loc), "enumType", 0, null, loc),
153                                         },
154                                         new [] {
155                                                 Compiler.BuiltinTypes.Object,
156                                                 Compiler.BuiltinTypes.Object,
157                                                 Compiler.BuiltinTypes.Bool
158                                         });
159
160                                 var m = new Method (this, new TypeExpression (Compiler.BuiltinTypes.Bool, loc),
161                                         Modifiers.PUBLIC | Modifiers.STATIC | Modifiers.DEBUGGER_HIDDEN, new MemberName ("NumberMatcher", loc),
162                                         parameters, null);
163
164                                 parameters [0].Resolve (m, 0);
165                                 parameters [1].Resolve (m, 1);
166                                 parameters [2].Resolve (m, 2);
167
168                                 ToplevelBlock top_block = new ToplevelBlock (Compiler, parameters, loc);
169                                 m.Block = top_block;
170
171                                 //
172                                 // if (enumType)
173                                 //              return Equals (obj, value);
174                                 //
175                                 var equals_args = new Arguments (2);
176                                 equals_args.Add (new Argument (top_block.GetParameterReference (0, loc)));
177                                 equals_args.Add (new Argument (top_block.GetParameterReference (1, loc)));
178
179                                 var if_type = new If (
180                                                       top_block.GetParameterReference (2, loc),
181                                                       new Return (new Invocation (new SimpleName ("Equals", loc), equals_args), loc),
182                                                       loc);
183
184                                 top_block.AddStatement (if_type);
185
186                                 //
187                                 // if (obj is Enum || obj == null)
188                                 //              return false;
189                                 //
190
191                                 var if_enum = new If (
192                                                       new Binary (Binary.Operator.LogicalOr,
193                                                               new Is (top_block.GetParameterReference (0, loc), new TypeExpression (Compiler.BuiltinTypes.Enum, loc), loc),
194                                                               new Binary (Binary.Operator.Equality, top_block.GetParameterReference (0, loc), new NullLiteral (loc))),
195                                                       new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc),
196                                                       loc);
197
198                                 top_block.AddStatement (if_enum);
199
200
201                                 var system_convert = new MemberAccess (new QualifiedAliasMember ("global", "System", loc), "Convert", loc);
202                                 var expl_block = new ExplicitBlock (top_block, loc, loc);
203
204                                 //
205                                 // var converted = System.Convert.ChangeType (obj, System.Convert.GetTypeCode (value));
206                                 //
207                                 var lv_converted = LocalVariable.CreateCompilerGenerated (Compiler.BuiltinTypes.Object, top_block, loc);
208
209                                 var arguments_gettypecode = new Arguments (1);
210                                 arguments_gettypecode.Add (new Argument (top_block.GetParameterReference (1, loc)));
211
212                                 var gettypecode = new Invocation (new MemberAccess (system_convert, "GetTypeCode", loc), arguments_gettypecode);
213
214                                 var arguments_changetype = new Arguments (1);
215                                 arguments_changetype.Add (new Argument (top_block.GetParameterReference (0, loc)));
216                                 arguments_changetype.Add (new Argument (gettypecode));
217
218                                 var changetype = new Invocation (new MemberAccess (system_convert, "ChangeType", loc), arguments_changetype);
219
220                                 expl_block.AddStatement (new StatementExpression (new SimpleAssign (new LocalVariableReference (lv_converted, loc), changetype, loc)));
221
222
223                                 //
224                                 // return converted.Equals (value)
225                                 //
226                                 var equals_arguments = new Arguments (1);
227                                 equals_arguments.Add (new Argument (top_block.GetParameterReference (1, loc)));
228                                 var equals_invocation = new Invocation (new MemberAccess (new LocalVariableReference (lv_converted, loc), "Equals"), equals_arguments);
229                                 expl_block.AddStatement (new Return (equals_invocation, loc));
230
231                                 var catch_block = new ExplicitBlock (top_block, loc, loc);
232                                 catch_block.AddStatement (new Return (new BoolLiteral (Compiler.BuiltinTypes, false, loc), loc));
233                                 top_block.AddStatement (new TryCatch (expl_block, new List<Catch> () {
234                                         new Catch (catch_block, loc)
235                                 }, loc, false));
236
237                                 m.Define ();
238                                 m.PrepareEmit ();
239                                 AddMember (m);
240
241                                 return m;
242                         }
243                 }
244
245                 PatternMatchingHelper pmh;
246
247                 public PatternMatchingHelper CreatePatterMatchingHelper ()
248                 {
249                         if (pmh == null) {
250                                 pmh = new PatternMatchingHelper (this);
251
252                                 pmh.CreateContainer ();
253                                 pmh.DefineContainer ();
254                                 pmh.Define ();
255                                 AddCompilerGeneratedClass (pmh);
256                         }
257
258                         return pmh;
259                 }
260
261                 public CharSet? DefaultCharSet;
262                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
263
264                 readonly Dictionary<int, List<AnonymousTypeClass>> anonymous_types;
265                 readonly Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> array_types;
266                 readonly Dictionary<TypeSpec, PointerContainer> pointer_types;
267                 readonly Dictionary<TypeSpec, ReferenceContainer> reference_types;
268                 readonly Dictionary<TypeSpec, MethodSpec> attrs_cache;
269                 readonly Dictionary<TypeSpec, AwaiterDefinition> awaiters;
270                 readonly Dictionary<TypeSpec, TypeInfo> type_info_cache;
271
272                 AssemblyDefinition assembly;
273                 readonly CompilerContext context;
274                 readonly RootNamespace global_ns;
275                 readonly Dictionary<string, RootNamespace> alias_ns;
276
277                 ModuleBuilder builder;
278
279                 bool has_extenstion_method;
280
281                 PredefinedAttributes predefined_attributes;
282                 PredefinedTypes predefined_types;
283                 PredefinedMembers predefined_members;
284
285                 public Binary.PredefinedOperator[] OperatorsBinaryEqualityLifted;
286                 public Binary.PredefinedOperator[] OperatorsBinaryLifted;
287
288                 static readonly string[] attribute_targets = new string[] { "assembly", "module" };
289
290                 public ModuleContainer (CompilerContext context)
291                         : base (null, MemberName.Null, null, 0)
292                 {
293                         this.context = context;
294
295                         caching_flags &= ~(Flags.Obsolete_Undetected | Flags.Excluded_Undetected);
296
297                         containers = new List<TypeContainer> ();
298                         anonymous_types = new Dictionary<int, List<AnonymousTypeClass>> ();
299                         global_ns = new GlobalRootNamespace ();
300                         alias_ns = new Dictionary<string, RootNamespace> ();
301                         array_types = new Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ();
302                         pointer_types = new Dictionary<TypeSpec, PointerContainer> ();
303                         reference_types = new Dictionary<TypeSpec, ReferenceContainer> ();
304                         attrs_cache = new Dictionary<TypeSpec, MethodSpec> ();
305                         awaiters = new Dictionary<TypeSpec, AwaiterDefinition> ();
306                         type_info_cache = new Dictionary<TypeSpec, TypeInfo> ();
307                 }
308
309                 #region Properties
310
311                 internal Dictionary<ArrayContainer.TypeRankPair, ArrayContainer> ArrayTypesCache {
312                         get {
313                                 return array_types;
314                         }
315                 }
316
317                 //
318                 // Cache for parameter-less attributes
319                 //
320                 internal Dictionary<TypeSpec, MethodSpec> AttributeConstructorCache {
321                         get {
322                                 return attrs_cache;
323                         }
324                 }
325
326                 public override AttributeTargets AttributeTargets {
327                         get {
328                                 return AttributeTargets.Assembly;
329                         }
330                 }
331
332                 public ModuleBuilder Builder {
333                         get {
334                                 return builder;
335                         }
336                 }
337
338                 public override CompilerContext Compiler {
339                         get {
340                                 return context;
341                         }
342                 }
343
344                 public int CounterAnonymousTypes { get; set; }
345
346                 public AssemblyDefinition DeclaringAssembly {
347                         get {
348                                 return assembly;
349                         }
350                 }
351
352                 internal DocumentationBuilder DocumentationBuilder {
353                         get; set;
354                 }
355
356                 public override string DocCommentHeader {
357                         get {
358                                 throw new NotSupportedException ();
359                         }
360                 }
361
362                 public Evaluator Evaluator {
363                         get; set;
364                 }
365
366                 public bool HasDefaultCharSet {
367                         get {
368                                 return DefaultCharSet.HasValue;
369                         }
370                 }
371
372                 public bool HasExtensionMethod {
373                         get {
374                                 return has_extenstion_method;
375                         }
376                         set {
377                                 has_extenstion_method = value;
378                         }
379                 }
380
381                 public bool HasTypesFullyDefined {
382                         get; set;
383                 }
384
385                 //
386                 // Returns module global:: namespace
387                 //
388                 public RootNamespace GlobalRootNamespace {
389                     get {
390                         return global_ns;
391                     }
392                 }
393
394                 public override ModuleContainer Module {
395                         get {
396                                 return this;
397                         }
398                 }
399
400                 internal Dictionary<TypeSpec, PointerContainer> PointerTypesCache {
401                         get {
402                                 return pointer_types;
403                         }
404                 }
405
406                 internal PredefinedAttributes PredefinedAttributes {
407                         get {
408                                 return predefined_attributes;
409                         }
410                 }
411
412                 internal PredefinedMembers PredefinedMembers {
413                         get {
414                                 return predefined_members;
415                         }
416                 }
417
418                 internal PredefinedTypes PredefinedTypes {
419                         get {
420                                 return predefined_types;
421                         }
422                 }
423
424                 internal Dictionary<TypeSpec, ReferenceContainer> ReferenceTypesCache {
425                         get {
426                                 return reference_types;
427                         }
428                 }
429
430                 internal Dictionary<TypeSpec, TypeInfo> TypeInfoCache {
431                         get {
432                                 return type_info_cache;
433                         }
434                 }
435
436                 public override string[] ValidAttributeTargets {
437                         get {
438                                 return attribute_targets;
439                         }
440                 }
441
442                 public Dictionary<string, string> GetResourceStrings { get; private set; }
443
444                 #endregion
445
446                 public override void Accept (StructuralVisitor visitor)
447                 {
448                         visitor.Visit (this);
449                 }
450
451                 public void AddAnonymousType (AnonymousTypeClass type)
452                 {
453                         List<AnonymousTypeClass> existing;
454                         if (!anonymous_types.TryGetValue (type.Parameters.Count, out existing))
455                         if (existing == null) {
456                                 existing = new List<AnonymousTypeClass> ();
457                                 anonymous_types.Add (type.Parameters.Count, existing);
458                         }
459
460                         existing.Add (type);
461                 }
462
463                 public void AddAttribute (Attribute attr, IMemberContext context)
464                 {
465                         attr.AttachTo (this, context);
466
467                         if (attributes == null) {
468                                 attributes = new Attributes (attr);
469                                 return;
470                         }
471
472                         attributes.AddAttribute (attr);
473                 }
474
475                 public override void AddTypeContainer (TypeContainer tc)
476                 {
477                         AddTypeContainerMember (tc);
478                 }
479
480                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
481                 {
482                         if (a.Target == AttributeTargets.Assembly) {
483                                 assembly.ApplyAttributeBuilder (a, ctor, cdata, pa);
484                                 return;
485                         }
486
487                         if (a.Type == pa.DefaultCharset) {
488                                 switch (a.GetCharSetValue ()) {
489                                 case CharSet.Ansi:
490                                 case CharSet.None:
491                                         break;
492                                 case CharSet.Auto:
493                                         DefaultCharSet = CharSet.Auto;
494                                         DefaultCharSetType = TypeAttributes.AutoClass;
495                                         break;
496                                 case CharSet.Unicode:
497                                         DefaultCharSet = CharSet.Unicode;
498                                         DefaultCharSetType = TypeAttributes.UnicodeClass;
499                                         break;
500                                 default:
501                                         Report.Error (1724, a.Location, "Value specified for the argument to `{0}' is not valid",
502                                                 a.GetSignatureForError ());
503                                         break;
504                                 }
505                         } else if (a.Type == pa.CLSCompliant) {
506                                 Attribute cls = DeclaringAssembly.CLSCompliantAttribute;
507                                 if (cls == null) {
508                                         Report.Warning (3012, 1, a.Location,
509                                                 "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
510                                 } else if (DeclaringAssembly.IsCLSCompliant != a.GetBoolean ()) {
511                                         Report.SymbolRelatedToPreviousError (cls.Location, cls.GetSignatureForError ());
512                                         Report.Warning (3017, 1, a.Location,
513                                                 "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
514                                         return;
515                                 }
516                         }
517
518                         builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
519                 }
520
521                 public override void CloseContainer ()
522                 {
523                         if (anonymous_types != null) {
524                                 foreach (var atypes in anonymous_types)
525                                         foreach (var at in atypes.Value)
526                                                 at.CloseContainer ();
527                         }
528
529                         base.CloseContainer ();
530                 }
531
532                 public TypeBuilder CreateBuilder (string name, TypeAttributes attr, int typeSize)
533                 {
534                         return builder.DefineType (name, attr, null, typeSize);
535                 }
536
537                 //
538                 // Creates alias global namespace
539                 //
540                 public RootNamespace CreateRootNamespace (string alias)
541                 {
542                         if (alias == global_ns.Alias) {
543                                 RootNamespace.Error_GlobalNamespaceRedefined (Report, Location.Null);
544                                 return global_ns;
545                         }
546
547                         RootNamespace rn;
548                         if (!alias_ns.TryGetValue (alias, out rn)) {
549                                 rn = new RootNamespace (alias);
550                                 alias_ns.Add (alias, rn);
551                         }
552
553                         return rn;
554                 }
555
556                 public void Create (AssemblyDefinition assembly, ModuleBuilder moduleBuilder)
557                 {
558                         this.assembly = assembly;
559                         builder = moduleBuilder;
560                 }
561
562                 public override bool Define ()
563                 {
564                         DefineContainer ();
565
566                         ExpandBaseInterfaces ();
567
568                         base.Define ();
569
570                         HasTypesFullyDefined = true;
571
572                         return true;
573                 }
574
575                 public override bool DefineContainer ()
576                 {
577                         DefineNamespace ();
578
579                         return base.DefineContainer ();
580                 }
581
582                 public void EnableRedefinition ()
583                 {
584                         is_defined = false;
585                 }
586
587                 public override void EmitContainer ()
588                 {
589                         if (OptAttributes != null)
590                                 OptAttributes.Emit ();
591
592                         if (Compiler.Settings.Unsafe && !assembly.IsSatelliteAssembly) {
593                                 var pa = PredefinedAttributes.UnverifiableCode;
594                                 if (pa.IsDefined)
595                                         pa.EmitAttribute (builder);
596                         }
597
598                         foreach (var tc in containers) {
599                                 tc.PrepareEmit ();
600                         }
601
602                         base.EmitContainer ();
603
604                         if (Compiler.Report.Errors == 0 && !Compiler.Settings.WriteMetadataOnly)
605                                 VerifyMembers ();
606
607                         if (anonymous_types != null) {
608                                 foreach (var atypes in anonymous_types)
609                                         foreach (var at in atypes.Value)
610                                                 at.EmitContainer ();
611                         }
612                 }
613
614                 internal override void GenerateDocComment (DocumentationBuilder builder)
615                 {
616                         foreach (var tc in containers)
617                                 tc.GenerateDocComment (builder);
618                 }
619
620                 public AnonymousTypeClass GetAnonymousType (IList<AnonymousTypeParameter> parameters)
621                 {
622                         List<AnonymousTypeClass> candidates;
623                         if (!anonymous_types.TryGetValue (parameters.Count, out candidates))
624                                 return null;
625
626                         int i;
627                         foreach (AnonymousTypeClass at in candidates) {
628                                 for (i = 0; i < parameters.Count; ++i) {
629                                         if (!parameters [i].Equals (at.Parameters [i]))
630                                                 break;
631                                 }
632
633                                 if (i == parameters.Count)
634                                         return at;
635                         }
636
637                         return null;
638                 }
639
640                 //
641                 // Return container with awaiter definition. It never returns null
642                 // but all container member can be null for easier error reporting
643                 //
644                 public AwaiterDefinition GetAwaiter (TypeSpec type)
645                 {
646                         AwaiterDefinition awaiter;
647                         if (awaiters.TryGetValue (type, out awaiter))
648                                 return awaiter;
649
650                         awaiter = new AwaiterDefinition ();
651
652                         //
653                         // Predefined: bool IsCompleted { get; } 
654                         //
655                         awaiter.IsCompleted = MemberCache.FindMember (type, MemberFilter.Property ("IsCompleted", Compiler.BuiltinTypes.Bool),
656                                 BindingRestriction.InstanceOnly) as PropertySpec;
657
658                         //
659                         // Predefined: GetResult ()
660                         //
661                         // The method return type is also result type of await expression
662                         //
663                         awaiter.GetResult = MemberCache.FindMember (type, MemberFilter.Method ("GetResult", 0,
664                                 ParametersCompiled.EmptyReadOnlyParameters, null),
665                                 BindingRestriction.InstanceOnly) as MethodSpec;
666
667                         //
668                         // Predefined: INotifyCompletion.OnCompleted (System.Action)
669                         //
670                         var nc = PredefinedTypes.INotifyCompletion;
671                         awaiter.INotifyCompletion = !nc.Define () || type.ImplementsInterface (nc.TypeSpec, false);
672
673                         awaiters.Add (type, awaiter);
674                         return awaiter;
675                 }
676
677                 public override void GetCompletionStartingWith (string prefix, List<string> results)
678                 {
679                         var names = Evaluator.GetVarNames ();
680                         results.AddRange (names.Where (l => l.StartsWith (prefix)));
681                 }
682
683                 public RootNamespace GetRootNamespace (string name)
684                 {
685                         RootNamespace rn;
686                         alias_ns.TryGetValue (name, out rn);
687                         return rn;
688                 }
689
690                 public override string GetSignatureForError ()
691                 {
692                         return "<module>";
693                 }
694
695                 public Binary.PredefinedOperator[] GetPredefinedEnumAritmeticOperators (TypeSpec enumType, bool nullable)
696                 {
697                         TypeSpec underlying;
698                         Binary.Operator mask = 0;
699
700                         if (nullable) {
701                                 underlying = Nullable.NullableInfo.GetEnumUnderlyingType (this, enumType);
702                                 mask = Binary.Operator.NullableMask;
703                         } else {
704                                 underlying = EnumSpec.GetUnderlyingType (enumType);
705                         }
706
707                         var operators = new[] {
708                                 new Binary.PredefinedOperator (enumType, underlying,
709                                         mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
710                                 new Binary.PredefinedOperator (underlying, enumType,
711                                         mask | Binary.Operator.AdditionMask | Binary.Operator.SubtractionMask | Binary.Operator.DecomposedMask, enumType),
712                                 new Binary.PredefinedOperator (enumType, mask | Binary.Operator.SubtractionMask, underlying)
713                         };
714
715                         return operators;
716                 }
717
718                 public void InitializePredefinedTypes ()
719                 {
720                         predefined_attributes = new PredefinedAttributes (this);
721                         predefined_types = new PredefinedTypes (this);
722                         predefined_members = new PredefinedMembers (this);
723
724                         OperatorsBinaryEqualityLifted = Binary.CreateEqualityLiftedOperatorsTable (this);
725                         OperatorsBinaryLifted = Binary.CreateStandardLiftedOperatorsTable (this);
726                 }
727
728                 public override bool IsClsComplianceRequired ()
729                 {
730                         return DeclaringAssembly.IsCLSCompliant;
731                 }
732
733                 public Attribute ResolveAssemblyAttribute (PredefinedAttribute a_type)
734                 {
735                         Attribute a = OptAttributes.Search ("assembly", a_type);
736                         if (a != null) {
737                                 a.Resolve ();
738                         }
739                         return a;
740                 }
741
742                 public void SetDeclaringAssembly (AssemblyDefinition assembly)
743                 {
744                         // TODO: This setter is quite ugly but I have not found a way around it yet
745                         this.assembly = assembly;
746                 }
747
748                 public void LoadGetResourceStrings (List<string> fileNames)
749                 {
750                         foreach (var fileName in fileNames) {
751                                 if (!File.Exists (fileName)) {
752                                         Report.Error (1566, "Error reading resource file `{0}'", fileName);
753                                         return;
754                                 }
755
756                                 foreach (var l in File.ReadLines (fileName)) {
757                                         if (GetResourceStrings == null)
758                                                 GetResourceStrings = new Dictionary<string, string> ();
759
760                                         var line = l.Trim ();
761                                         if (line.Length == 0 || line [0] == '#' || line [0] == ';')
762                                                 continue;
763                                 
764                                         var epos = line.IndexOf ('=');
765                                         if (epos < 0)
766                                                 continue;
767
768                                         var key = line.Substring (0, epos).Trim ();
769                                         var value = line.Substring (epos + 1).Trim ();
770
771                                         GetResourceStrings [key] = value;
772                                 }
773                         }
774                 }
775         }
776 }