* codegen.cs (IResolveContent.GenericDeclContainer): Copy from gmcs.
[mono.git] / mcs / gmcs / codegen.cs
1 //
2 // codegen.cs: The code generator
3 //
4 // Author:
5 //   Miguel de Icaza (miguel@ximian.com)
6 //
7 // (C) 2001, 2002, 2003 Ximian, Inc.
8 // (C) 2004 Novell, Inc.
9 //
10
11 #if !DEBUG
12         #define PRODUCTION
13 #endif
14
15 using System;
16 using System.IO;
17 using System.Collections;
18 using System.Collections.Specialized;
19 using System.Reflection;
20 using System.Reflection.Emit;
21 using System.Runtime.InteropServices;
22 using System.Security;
23 using System.Security.Cryptography;
24 using System.Security.Permissions;
25
26 using Mono.Security.Cryptography;
27
28 namespace Mono.CSharp {
29
30         /// <summary>
31         ///    Code generator class.
32         /// </summary>
33         public class CodeGen {
34                 static AppDomain current_domain;
35                 static public SymbolWriter SymbolWriter;
36
37                 public static AssemblyClass Assembly;
38                 public static ModuleClass Module;
39
40                 static CodeGen ()
41                 {
42                         Reset ();
43                 }
44
45                 public static void Reset ()
46                 {
47                         Assembly = new AssemblyClass ();
48                         Module = new ModuleClass (RootContext.Unsafe);
49                 }
50
51                 public static string Basename (string name)
52                 {
53                         int pos = name.LastIndexOf ('/');
54
55                         if (pos != -1)
56                                 return name.Substring (pos + 1);
57
58                         pos = name.LastIndexOf ('\\');
59                         if (pos != -1)
60                                 return name.Substring (pos + 1);
61
62                         return name;
63                 }
64
65                 public static string Dirname (string name)
66                 {
67                         int pos = name.LastIndexOf ('/');
68
69                         if (pos != -1)
70                                 return name.Substring (0, pos);
71
72                         pos = name.LastIndexOf ('\\');
73                         if (pos != -1)
74                                 return name.Substring (0, pos);
75
76                         return ".";
77                 }
78
79                 static public string FileName;
80
81                 //
82                 // Initializes the symbol writer
83                 //
84                 static void InitializeSymbolWriter (string filename)
85                 {
86                         SymbolWriter = SymbolWriter.GetSymbolWriter (Module.Builder, filename);
87
88                         //
89                         // If we got an ISymbolWriter instance, initialize it.
90                         //
91                         if (SymbolWriter == null) {
92                                 Report.Warning (
93                                         -18, 1, "Could not find the symbol writer assembly (Mono.CompilerServices.SymbolWriter.dll). This is normally an installation problem. Please make sure to compile and install the mcs/class/Mono.CompilerServices.SymbolWriter directory.");
94                                 return;
95                         }
96                 }
97
98                 //
99                 // Initializes the code generator variables
100                 //
101                 static public bool Init (string name, string output, bool want_debugging_support)
102                 {
103                         FileName = output;
104                         AssemblyName an = Assembly.GetAssemblyName (name, output);
105                         if (an == null)
106                                 return false;
107
108                         if (an.KeyPair != null) {
109                                 // If we are going to strong name our assembly make
110                                 // sure all its refs are strong named
111                                 foreach (Assembly a in RootNamespace.Global.Assemblies) {
112                                         AssemblyName ref_name = a.GetName ();
113                                         byte [] b = ref_name.GetPublicKeyToken ();
114                                         if (b == null || b.Length == 0) {
115                                                 Report.Error (1577, "Assembly generation failed " +
116                                                                 "-- Referenced assembly '" +
117                                                                 ref_name.Name +
118                                                                 "' does not have a strong name.");
119                                                 //Environment.Exit (1);
120                                         }
121                                 }
122                         }
123                         
124                         current_domain = AppDomain.CurrentDomain;
125
126                         try {
127                                 Assembly.Builder = current_domain.DefineDynamicAssembly (an,
128                                         AssemblyBuilderAccess.Save, Dirname (name));
129                         }
130                         catch (ArgumentException) {
131                                 // specified key may not be exportable outside it's container
132                                 if (RootContext.StrongNameKeyContainer != null) {
133                                         Report.Error (1548, "Could not access the key inside the container `" +
134                                                 RootContext.StrongNameKeyContainer + "'.");
135                                         Environment.Exit (1);
136                                 }
137                                 return false;
138                         }
139                         catch (CryptographicException) {
140                                 if ((RootContext.StrongNameKeyContainer != null) || (RootContext.StrongNameKeyFile != null)) {
141                                         Report.Error (1548, "Could not use the specified key to strongname the assembly.");
142                                         Environment.Exit (1);
143                                 }
144                                 return false;
145                         }
146
147                         // Get the complete AssemblyName from the builder
148                         // (We need to get the public key and token)
149                         Assembly.Name = Assembly.Builder.GetName ();
150                         
151                         //
152                         // Pass a path-less name to DefineDynamicModule.  Wonder how
153                         // this copes with output in different directories then.
154                         // FIXME: figure out how this copes with --output /tmp/blah
155                         //
156                         // If the third argument is true, the ModuleBuilder will dynamically
157                         // load the default symbol writer.
158                         //
159                         Module.Builder = Assembly.Builder.DefineDynamicModule (
160                                 Basename (name), Basename (output), false);
161
162                         if (want_debugging_support)
163                                 InitializeSymbolWriter (output);
164
165                         return true;
166                 }
167
168                 static public void Save (string name)
169                 {
170                         try {
171                                 Assembly.Builder.Save (Basename (name));
172
173                                 if (SymbolWriter != null)
174                                         SymbolWriter.WriteSymbolFile ();
175                         }
176                         catch (COMException) {
177                                 if ((RootContext.StrongNameKeyFile == null) || (!RootContext.StrongNameDelaySign))
178                                         throw;
179
180                                 // FIXME: it seems Microsoft AssemblyBuilder doesn't like to delay sign assemblies 
181                                 Report.Error (1548, "Couldn't delay-sign the assembly with the '" +
182                                         RootContext.StrongNameKeyFile +
183                                         "', Use MCS with the Mono runtime or CSC to compile this assembly.");
184                         }
185                         catch (System.IO.IOException io) {
186                                 Report.Error (16, "Could not write to file `"+name+"', cause: " + io.Message);
187                         }
188                         catch (System.UnauthorizedAccessException ua) {
189                                 Report.Error (16, "Could not write to file `"+name+"', cause: " + ua.Message);
190                         }
191                 }
192         }
193
194
195         public interface IResolveContext
196         {
197                 DeclSpace DeclContainer { get; }
198                 bool IsInObsoleteScope { get; }
199                 bool IsInUnsafeScope { get; }
200
201                 // the declcontainer to lookup for type-parameters.  Should only use LookupGeneric on it.
202                 //
203                 // FIXME: This is somewhat of a hack.  We don't need a full DeclSpace for this.  We just need the
204                 //        current type parameters in scope. IUIC, that will require us to rewrite GenericMethod.
205                 //        Maybe we can replace this with a 'LookupGeneric (string)' instead, but we'll have to 
206                 //        handle generic method overrides differently
207                 DeclSpace GenericDeclContainer { get; }
208         }
209
210         /// <summary>
211         ///   An Emit Context is created for each body of code (from methods,
212         ///   properties bodies, indexer bodies or constructor bodies)
213         /// </summary>
214         public class EmitContext : IResolveContext {
215
216                 DeclSpace declSpace;
217                 public DeclSpace TypeContainer;
218                 public ILGenerator   ig;
219
220                 [Flags]
221                 public enum Flags : byte {
222                         /// <summary>
223                         ///   This flag tracks the `checked' state of the compilation,
224                         ///   it controls whether we should generate code that does overflow
225                         ///   checking, or if we generate code that ignores overflows.
226                         ///
227                         ///   The default setting comes from the command line option to generate
228                         ///   checked or unchecked code plus any source code changes using the
229                         ///   checked/unchecked statements or expressions.   Contrast this with
230                         ///   the ConstantCheckState flag.
231                         /// </summary>
232                         CheckState = 1 << 0,
233
234                         /// <summary>
235                         ///   The constant check state is always set to `true' and cant be changed
236                         ///   from the command line.  The source code can change this setting with
237                         ///   the `checked' and `unchecked' statements and expressions. 
238                         /// </summary>
239                         ConstantCheckState = 1 << 1,
240
241                         AllCheckStateFlags = CheckState | ConstantCheckState,
242
243                         /// <summary>
244                         ///  Whether we are inside an unsafe block
245                         /// </summary>
246                         InUnsafe = 1 << 2,
247
248                         InCatch = 1 << 3,
249                         InFinally = 1 << 4,
250
251                         /// <summary>
252                         ///   Whether control flow analysis is enabled
253                         /// </summary>
254                         DoFlowAnalysis = 1 << 5,
255
256                         /// <summary>
257                         ///   Whether control flow analysis is disabled on structs
258                         ///   (only meaningful when DoFlowAnalysis is set)
259                         /// </summary>
260                         OmitStructFlowAnalysis = 1 << 6
261                 }
262
263                 Flags flags;
264
265                 /// <summary>
266                 ///   Whether we are emitting code inside a static or instance method
267                 /// </summary>
268                 public bool IsStatic;
269
270                 /// <summary>
271                 ///   Whether the actual created method is static or instance method.
272                 ///   Althoug the method might be declared as `static', if an anonymous
273                 ///   method is involved, we might turn this into an instance method.
274                 ///
275                 ///   So this reflects the low-level staticness of the method, while
276                 ///   IsStatic represents the semantic, high-level staticness.
277                 /// </summary>
278                 public bool MethodIsStatic;
279
280                 /// <summary>
281                 ///   Whether we are emitting a field initializer
282                 /// </summary>
283                 public bool IsFieldInitializer;
284
285                 /// <summary>
286                 ///   The value that is allowed to be returned or NULL if there is no
287                 ///   return type.
288                 /// </summary>
289                 public Type ReturnType;
290
291                 /// <summary>
292                 ///   Points to the Type (extracted from the TypeContainer) that
293                 ///   declares this body of code
294                 /// </summary>
295                 public Type ContainerType;
296                 
297                 /// <summary>
298                 ///   Whether this is generating code for a constructor
299                 /// </summary>
300                 public bool IsConstructor;
301
302                 /// <summary>
303                 ///   Keeps track of the Type to LocalBuilder temporary storage created
304                 ///   to store structures (used to compute the address of the structure
305                 ///   value on structure method invocations)
306                 /// </summary>
307                 public Hashtable temporary_storage;
308
309                 public Block CurrentBlock;
310
311                 public int CurrentFile;
312
313                 /// <summary>
314                 ///   The location where we store the return value.
315                 /// </summary>
316                 LocalBuilder return_value;
317
318                 /// <summary>
319                 ///   The location where return has to jump to return the
320                 ///   value
321                 /// </summary>
322                 public Label ReturnLabel;
323
324                 /// <summary>
325                 ///   If we already defined the ReturnLabel
326                 /// </summary>
327                 public bool HasReturnLabel;
328
329                 /// <summary>
330                 ///   Whether we are inside an iterator block.
331                 /// </summary>
332                 public bool InIterator;
333
334                 public bool IsLastStatement;
335
336                 /// <summary>
337                 ///  Whether we are in a `fixed' initialization
338                 /// </summary>
339                 public bool InFixedInitializer;
340
341                 /// <summary>
342                 ///  Whether we are inside an anonymous method.
343                 /// </summary>
344                 public AnonymousContainer CurrentAnonymousMethod;
345                 
346                 /// <summary>
347                 ///   Location for this EmitContext
348                 /// </summary>
349                 public Location loc;
350
351                 /// <summary>
352                 ///   Inside an enum definition, we do not resolve enumeration values
353                 ///   to their enumerations, but rather to the underlying type/value
354                 ///   This is so EnumVal + EnumValB can be evaluated.
355                 ///
356                 ///   There is no "E operator + (E x, E y)", so during an enum evaluation
357                 ///   we relax the rules
358                 /// </summary>
359                 public bool InEnumContext;
360
361                 /// <summary>
362                 ///   Anonymous methods can capture local variables and fields,
363                 ///   this object tracks it.  It is copied from the TopLevelBlock
364                 ///   field.
365                 /// </summary>
366                 public CaptureContext capture_context;
367
368                 public readonly IResolveContext ResolveContext;
369
370                 /// <summary>
371                 ///    The current iterator
372                 /// </summary>
373                 public Iterator CurrentIterator {
374                         get {
375                                 if (CurrentAnonymousMethod != null)
376                                         return CurrentAnonymousMethod.Iterator;
377                                 else
378                                         return null;
379                         }
380                 }
381
382                 /// <summary>
383                 ///    Whether we are in the resolving stage or not
384                 /// </summary>
385                 enum Phase {
386                         Created,
387                         Resolving,
388                         Emitting
389                 }
390
391                 bool isAnonymousMethodAllowed = true;
392
393                 Phase current_phase;
394                 FlowBranching current_flow_branching;
395
396                 static int next_id = 0;
397                 int id = ++next_id;
398
399                 public override string ToString ()
400                 {
401                         return String.Format ("EmitContext ({0}:{1}:{2})", id,
402                                               CurrentIterator, capture_context, loc);
403                 }
404                 
405                 public EmitContext (IResolveContext rc, DeclSpace parent, DeclSpace ds, Location l, ILGenerator ig,
406                                     Type return_type, int code_flags, bool is_constructor)
407                 {
408                         this.ResolveContext = rc;
409                         this.ig = ig;
410
411                         TypeContainer = parent;
412                         this.declSpace = ds;
413                         if (RootContext.Checked)
414                                 flags |= Flags.CheckState;
415                         flags |= Flags.ConstantCheckState;
416
417                         if ((return_type is TypeBuilder) && return_type.IsGenericTypeDefinition)
418                                 throw new InternalErrorException ();
419                         
420                         IsStatic = (code_flags & Modifiers.STATIC) != 0;
421                         MethodIsStatic = IsStatic;
422                         InIterator = (code_flags & Modifiers.METHOD_YIELDS) != 0;
423                         ReturnType = return_type;
424                         IsConstructor = is_constructor;
425                         CurrentBlock = null;
426                         CurrentFile = 0;
427                         current_phase = Phase.Created;
428
429                         if (parent != null){
430                                 // Can only be null for the ResolveType contexts.
431                                 ContainerType = parent.TypeBuilder;
432                                 if (rc.IsInUnsafeScope)
433                                         flags |= Flags.InUnsafe;
434                         }
435                         loc = l;
436
437                         if (ReturnType == TypeManager.void_type)
438                                 ReturnType = null;
439                 }
440
441                 public EmitContext (IResolveContext rc, DeclSpace ds, Location l, ILGenerator ig,
442                                     Type return_type, int code_flags, bool is_constructor)
443                         : this (rc, ds, ds, l, ig, return_type, code_flags, is_constructor)
444                 {
445                 }
446
447                 public EmitContext (IResolveContext rc, DeclSpace ds, Location l, ILGenerator ig,
448                                     Type return_type, int code_flags)
449                         : this (rc, ds, ds, l, ig, return_type, code_flags, false)
450                 {
451                 }
452
453                 public DeclSpace DeclContainer { 
454                         get { return declSpace; }
455                         set { declSpace = value; }
456                 }
457
458                 public DeclSpace GenericDeclContainer {
459                         get { return DeclContainer; }
460                 }
461
462                 public bool CheckState {
463                         get { return (flags & Flags.CheckState) != 0; }
464                 }
465
466                 public bool ConstantCheckState {
467                         get { return (flags & Flags.ConstantCheckState) != 0; }
468                 }
469
470                 public bool InUnsafe {
471                         get { return (flags & Flags.InUnsafe) != 0; }
472                 }
473
474                 public bool InCatch {
475                         get { return (flags & Flags.InCatch) != 0; }
476                 }
477
478                 public bool InFinally {
479                         get { return (flags & Flags.InFinally) != 0; }
480                 }
481
482                 public bool DoFlowAnalysis {
483                         get { return (flags & Flags.DoFlowAnalysis) != 0; }
484                 }
485
486                 public bool OmitStructFlowAnalysis {
487                         get { return (flags & Flags.OmitStructFlowAnalysis) != 0; }
488                 }
489
490                 // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements
491                 // it's public so that we can use a struct at the callsite
492                 public struct FlagsHandle : IDisposable
493                 {
494                         EmitContext ec;
495                         Flags invmask, oldval;
496                         internal FlagsHandle (EmitContext ec, Flags mask, Flags val)
497                         {
498                                 this.ec = ec;
499                                 invmask = ~mask;
500                                 oldval = ec.flags & mask;
501                                 ec.flags = (ec.flags & invmask) | (val & mask);
502                         }
503                         public void Dispose ()
504                         {
505                                 ec.flags = (ec.flags & invmask) | oldval;
506                         }
507                 }
508
509                 // Temporarily set all the given flags to the given value.  Should be used in an 'using' statement
510                 public FlagsHandle With (Flags bits, bool enable)
511                 {
512                         return new FlagsHandle (this, bits, enable ? bits : 0);
513                 }
514
515                 public FlagsHandle WithFlowAnalysis (bool do_flow_analysis, bool omit_struct_analysis)
516                 {
517                         Flags newflags = 
518                                 (do_flow_analysis ? Flags.DoFlowAnalysis : 0) |
519                                 (omit_struct_analysis ? Flags.OmitStructFlowAnalysis : 0);
520                         return new FlagsHandle (this, Flags.DoFlowAnalysis | Flags.OmitStructFlowAnalysis, newflags);
521                 }
522
523                 public bool IsInObsoleteScope {
524                         get { return ResolveContext.IsInObsoleteScope; }
525                 }
526
527                 public bool IsInUnsafeScope {
528                         get { return InUnsafe || ResolveContext.IsInUnsafeScope; }
529                 }
530
531                 public bool IsAnonymousMethodAllowed {
532                         get { return isAnonymousMethodAllowed; }
533                         set { isAnonymousMethodAllowed = value; }
534                 }
535
536                 public FlowBranching CurrentBranching {
537                         get { return current_flow_branching; }
538                 }
539
540                 public bool HaveCaptureInfo {
541                         get { return capture_context != null; }
542                 }
543
544                 public void EmitScopeInitFromBlock (Block b)
545                 {
546                         if (capture_context != null)
547                                 capture_context.EmitScopeInitFromBlock (this, b);
548                 }
549
550                 // <summary>
551                 //   Starts a new code branching.  This inherits the state of all local
552                 //   variables and parameters from the current branching.
553                 // </summary>
554                 public FlowBranching StartFlowBranching (FlowBranching.BranchingType type, Location loc)
555                 {
556                         current_flow_branching = FlowBranching.CreateBranching (CurrentBranching, type, null, loc);
557                         return current_flow_branching;
558                 }
559
560                 // <summary>
561                 //   Starts a new code branching for block `block'.
562                 // </summary>
563                 public FlowBranching StartFlowBranching (Block block)
564                 {
565                         FlowBranching.BranchingType type;
566
567                         if ((CurrentBranching != null) &&
568                             (CurrentBranching.Type == FlowBranching.BranchingType.Switch))
569                                 type = FlowBranching.BranchingType.SwitchSection;
570                         else
571                                 type = FlowBranching.BranchingType.Block;
572
573                         flags |= Flags.DoFlowAnalysis;
574
575                         current_flow_branching = FlowBranching.CreateBranching (
576                                 CurrentBranching, type, block, block.StartLocation);
577                         return current_flow_branching;
578                 }
579
580                 public FlowBranchingException StartFlowBranching (ExceptionStatement stmt)
581                 {
582                         FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt);
583                         current_flow_branching = branching;
584                         return branching;
585                 }
586
587                 public FlowBranchingLabeled StartFlowBranching (LabeledStatement stmt)
588                 {
589                         FlowBranchingLabeled branching = new FlowBranchingLabeled (CurrentBranching, stmt);
590                         current_flow_branching = branching;
591                         return branching;
592                 }
593
594                 public FlowBranchingToplevel StartFlowBranching (ToplevelBlock stmt)
595                 {
596                         FlowBranchingToplevel branching = new FlowBranchingToplevel (CurrentBranching, stmt);
597                         current_flow_branching = branching;
598                         return branching;
599                 }
600
601                 // <summary>
602                 //   Ends a code branching.  Merges the state of locals and parameters
603                 //   from all the children of the ending branching.
604                 // </summary>
605                 public FlowBranching.UsageVector DoEndFlowBranching ()
606                 {
607                         FlowBranching old = current_flow_branching;
608                         current_flow_branching = current_flow_branching.Parent;
609
610                         return current_flow_branching.MergeChild (old);
611                 }
612
613                 // <summary>
614                 //   Ends a code branching.  Merges the state of locals and parameters
615                 //   from all the children of the ending branching.
616                 // </summary>
617                 public FlowBranching.Reachability EndFlowBranching ()
618                 {
619                         FlowBranching.UsageVector vector = DoEndFlowBranching ();
620
621                         return vector.Reachability;
622                 }
623
624                 // <summary>
625                 //   Kills the current code branching.  This throws away any changed state
626                 //   information and should only be used in case of an error.
627                 // </summary>
628                 public void KillFlowBranching ()
629                 {
630                         current_flow_branching = current_flow_branching.Parent;
631                 }
632
633                 public void CaptureVariable (LocalInfo li)
634                 {
635                         capture_context.AddLocal (CurrentAnonymousMethod, li);
636                         li.IsCaptured = true;
637                 }
638
639                 public void CaptureParameter (string name, Type t, int idx)
640                 {
641                         capture_context.AddParameter (this, CurrentAnonymousMethod, name, t, idx);
642                 }
643
644                 public void CaptureThis ()
645                 {
646                         capture_context.CaptureThis (CurrentAnonymousMethod);
647                 }
648                 
649                 
650                 //
651                 // Use to register a field as captured
652                 //
653                 public void CaptureField (FieldExpr fe)
654                 {
655                         capture_context.AddField (this, CurrentAnonymousMethod, fe);
656                 }
657
658                 //
659                 // Whether anonymous methods have captured variables
660                 //
661                 public bool HaveCapturedVariables ()
662                 {
663                         if (capture_context != null)
664                                 return capture_context.HaveCapturedVariables;
665                         return false;
666                 }
667
668                 //
669                 // Whether anonymous methods have captured fields or this.
670                 //
671                 public bool HaveCapturedFields ()
672                 {
673                         if (capture_context != null)
674                                 return capture_context.HaveCapturedFields;
675                         return false;
676                 }
677
678                 //
679                 // Emits the instance pointer for the host method
680                 //
681                 public void EmitMethodHostInstance (EmitContext target, AnonymousMethod am)
682                 {
683                         if (capture_context != null)
684                                 capture_context.EmitMethodHostInstance (target, am);
685                         else if (IsStatic)
686                                 target.ig.Emit (OpCodes.Ldnull);
687                         else
688                                 target.ig.Emit (OpCodes.Ldarg_0);
689                 }
690
691                 //
692                 // Returns whether the `local' variable has been captured by an anonymous
693                 // method
694                 //
695                 public bool IsCaptured (LocalInfo local)
696                 {
697                         return capture_context.IsCaptured (local);
698                 }
699
700                 public bool IsParameterCaptured (string name)
701                 {
702                         if (capture_context != null)
703                                 return capture_context.IsParameterCaptured (name);
704                         return false;
705                 }
706                 
707                 public void EmitMeta (ToplevelBlock b)
708                 {
709                         if (capture_context != null)
710                                 capture_context.EmitAnonymousHelperClasses (this);
711                         b.EmitMeta (this);
712
713                         if (HasReturnLabel)
714                                 ReturnLabel = ig.DefineLabel ();
715                 }
716
717                 //
718                 // Here until we can fix the problem with Mono.CSharp.Switch, which
719                 // currently can not cope with ig == null during resolve (which must
720                 // be fixed for switch statements to work on anonymous methods).
721                 //
722                 public void EmitTopBlock (IMethodData md, ToplevelBlock block)
723                 {
724                         if (block == null)
725                                 return;
726                         
727                         bool unreachable;
728                         
729                         if (ResolveTopBlock (null, block, md.ParameterInfo, md, out unreachable)){
730                                 EmitMeta (block);
731
732                                 current_phase = Phase.Emitting;
733                                 EmitResolvedTopBlock (block, unreachable);
734                         }
735                 }
736
737                 bool resolved;
738
739                 public bool ResolveTopBlock (EmitContext anonymous_method_host, ToplevelBlock block,
740                                              Parameters ip, IMethodData md, out bool unreachable)
741                 {
742                         current_phase = Phase.Resolving;
743                         
744                         unreachable = false;
745
746                         if (resolved)
747                                 return true;
748
749                         capture_context = block.CaptureContext;
750
751                         if (!loc.IsNull)
752                                 CurrentFile = loc.File;
753
754 #if PRODUCTION
755                         try {
756 #endif
757                                 if (!block.ResolveMeta (this, ip))
758                                         return false;
759
760                                 using (this.With (EmitContext.Flags.DoFlowAnalysis, true)) {
761                                         FlowBranchingToplevel top_level;
762                                         if (anonymous_method_host != null)
763                                                 top_level = new FlowBranchingToplevel (anonymous_method_host.CurrentBranching, block);
764                                         else 
765                                                 top_level = block.TopLevelBranching;
766
767                                         current_flow_branching = top_level;
768                                         bool ok = block.Resolve (this);
769                                         current_flow_branching = null;
770
771                                         if (!ok)
772                                                 return false;
773
774                                         FlowBranching.Reachability reachability = top_level.End ();
775                                         if (reachability.IsUnreachable)
776                                                 unreachable = true;
777                                 }
778 #if PRODUCTION
779                         } catch (Exception e) {
780                                 Console.WriteLine ("Exception caught by the compiler while compiling:");
781                                 Console.WriteLine ("   Block that caused the problem begin at: " + loc);
782
783                                 if (CurrentBlock != null){
784                                         Console.WriteLine ("                     Block being compiled: [{0},{1}]",
785                                                            CurrentBlock.StartLocation, CurrentBlock.EndLocation);
786                                 }
787                                 Console.WriteLine (e.GetType ().FullName + ": " + e.Message);
788                                 throw;
789                         }
790 #endif
791
792                         if (ReturnType != null && !unreachable) {
793                                 if (CurrentAnonymousMethod == null) {
794                                         Report.Error (161, md.Location, "`{0}': not all code paths return a value", md.GetSignatureForError ());
795                                         return false;
796                                 } else if (!CurrentAnonymousMethod.IsIterator) {
797                                         Report.Error (1643, CurrentAnonymousMethod.Location, "Not all code paths return a value in anonymous method of type `{0}'",
798                                                 CurrentAnonymousMethod.GetSignatureForError ());
799                                         return false;
800                                 }
801                         }
802
803                         block.CompleteContexts ();
804                         resolved = true;
805                         return true;
806                 }
807
808                 public void EmitResolvedTopBlock (ToplevelBlock block, bool unreachable)
809                 {
810                         if (block != null)
811                                 block.Emit (this);
812
813                         if (HasReturnLabel)
814                                 ig.MarkLabel (ReturnLabel);
815
816                         if (return_value != null){
817                                 ig.Emit (OpCodes.Ldloc, return_value);
818                                 ig.Emit (OpCodes.Ret);
819                         } else {
820                                 //
821                                 // If `HasReturnLabel' is set, then we already emitted a
822                                 // jump to the end of the method, so we must emit a `ret'
823                                 // there.
824                                 //
825                                 // Unfortunately, System.Reflection.Emit automatically emits
826                                 // a leave to the end of a finally block.  This is a problem
827                                 // if no code is following the try/finally block since we may
828                                 // jump to a point after the end of the method.
829                                 // As a workaround, we're always creating a return label in
830                                 // this case.
831                                 //
832
833                                 bool in_iterator = (CurrentAnonymousMethod != null) &&
834                                         CurrentAnonymousMethod.IsIterator && InIterator;
835
836                                 if ((block != null) && block.IsDestructor) {
837                                         // Nothing to do; S.R.E automatically emits a leave.
838                                 } else if (HasReturnLabel || (!unreachable && !in_iterator)) {
839                                         if (ReturnType != null)
840                                                 ig.Emit (OpCodes.Ldloc, TemporaryReturn ());
841                                         ig.Emit (OpCodes.Ret);
842                                 }
843                         }
844
845                         //
846                         // Close pending helper classes if we are the toplevel
847                         //
848                         if (capture_context != null && capture_context.ParentToplevel == null)
849                                 capture_context.CloseAnonymousHelperClasses ();
850                 }
851
852                 /// <summary>
853                 ///   This is called immediately before emitting an IL opcode to tell the symbol
854                 ///   writer to which source line this opcode belongs.
855                 /// </summary>
856                 public void Mark (Location loc, bool check_file)
857                 {
858                         if ((CodeGen.SymbolWriter == null) || loc.IsNull)
859                                 return;
860
861                         if (check_file && (CurrentFile != loc.File))
862                                 return;
863
864                         CodeGen.SymbolWriter.MarkSequencePoint (ig, loc.Row, loc.Column);
865                 }
866
867                 public void DefineLocalVariable (string name, LocalBuilder builder)
868                 {
869                         if (CodeGen.SymbolWriter == null)
870                                 return;
871
872                         CodeGen.SymbolWriter.DefineLocalVariable (name, builder);
873                 }
874
875                 public void BeginScope ()
876                 {
877                         ig.BeginScope();
878
879                         if (CodeGen.SymbolWriter != null)
880                                 CodeGen.SymbolWriter.OpenScope(ig);
881                 }
882
883                 public void EndScope ()
884                 {
885                         ig.EndScope();
886
887                         if (CodeGen.SymbolWriter != null)
888                                 CodeGen.SymbolWriter.CloseScope(ig);
889                 }
890
891                 /// <summary>
892                 ///   Returns a temporary storage for a variable of type t as 
893                 ///   a local variable in the current body.
894                 /// </summary>
895                 public LocalBuilder GetTemporaryLocal (Type t)
896                 {
897                         if (temporary_storage != null) {
898                                 object o = temporary_storage [t];
899                                 if (o != null) {
900                                         if (o is Stack) {
901                                                 Stack s = (Stack) o;
902                                                 o = s.Count == 0 ? null : s.Pop ();
903                                         } else {
904                                                 temporary_storage.Remove (t);
905                                         }
906                                 }
907                                 if (o != null)
908                                         return (LocalBuilder) o;
909                         }
910                         return ig.DeclareLocal (t);
911                 }
912
913                 public void FreeTemporaryLocal (LocalBuilder b, Type t)
914                 {
915                         Stack s;
916
917                         if (temporary_storage == null) {
918                                 temporary_storage = new Hashtable ();
919                                 temporary_storage [t] = b;
920                                 return;
921                         }
922                         object o = temporary_storage [t];
923                         if (o == null) {
924                                 temporary_storage [t] = b;
925                                 return;
926                         }
927                         if (o is Stack) {
928                                 s = (Stack) o;
929                         } else {
930                                 s = new Stack ();
931                                 s.Push (o);
932                                 temporary_storage [t] = s;
933                         }
934                         s.Push (b);
935                 }
936
937                 /// <summary>
938                 ///   Current loop begin and end labels.
939                 /// </summary>
940                 public Label LoopBegin, LoopEnd;
941
942                 /// <summary>
943                 ///   Default target in a switch statement.   Only valid if
944                 ///   InSwitch is true
945                 /// </summary>
946                 public Label DefaultTarget;
947
948                 /// <summary>
949                 ///   If this is non-null, points to the current switch statement
950                 /// </summary>
951                 public Switch Switch;
952
953                 /// <summary>
954                 ///   ReturnValue creates on demand the LocalBuilder for the
955                 ///   return value from the function.  By default this is not
956                 ///   used.  This is only required when returns are found inside
957                 ///   Try or Catch statements.
958                 ///
959                 ///   This method is typically invoked from the Emit phase, so
960                 ///   we allow the creation of a return label if it was not
961                 ///   requested during the resolution phase.   Could be cleaned
962                 ///   up, but it would replicate a lot of logic in the Emit phase
963                 ///   of the code that uses it.
964                 /// </summary>
965                 public LocalBuilder TemporaryReturn ()
966                 {
967                         if (return_value == null){
968                                 return_value = ig.DeclareLocal (ReturnType);
969                                 if (!HasReturnLabel){
970                                         ReturnLabel = ig.DefineLabel ();
971                                         HasReturnLabel = true;
972                                 }
973                         }
974
975                         return return_value;
976                 }
977
978                 /// <summary>
979                 ///   This method is used during the Resolution phase to flag the
980                 ///   need to define the ReturnLabel
981                 /// </summary>
982                 public void NeedReturnLabel ()
983                 {
984                         if (current_phase != Phase.Resolving){
985                                 //
986                                 // The reason is that the `ReturnLabel' is declared between
987                                 // resolution and emission
988                                 // 
989                                 throw new Exception ("NeedReturnLabel called from Emit phase, should only be called during Resolve");
990                         }
991                         
992                         if (!InIterator && !HasReturnLabel) 
993                                 HasReturnLabel = true;
994                 }
995
996                 //
997                 // Emits the proper object to address fields on a remapped
998                 // variable/parameter to field in anonymous-method/iterator proxy classes.
999                 //
1000                 public void EmitThis (bool need_address)
1001                 {
1002                         ig.Emit (OpCodes.Ldarg_0);
1003                         if (capture_context != null && CurrentAnonymousMethod != null){
1004                                 ScopeInfo si = CurrentAnonymousMethod.Scope;
1005                                 while (si != null){
1006                                         if (si.ParentLink != null)
1007                                                 ig.Emit (OpCodes.Ldfld, si.ParentLink);
1008                                         if (si.THIS != null){
1009                                                 if (need_address && TypeManager.IsValueType (si.THIS.FieldType))
1010                                                         ig.Emit (OpCodes.Ldflda, si.THIS);
1011                                                 else
1012                                                         ig.Emit (OpCodes.Ldfld, si.THIS);
1013                                                 break;
1014                                         }
1015                                         si = si.ParentScope;
1016                                 }
1017                         } 
1018                 }
1019
1020                 //
1021                 // Emits the code necessary to load the instance required
1022                 // to access the captured LocalInfo
1023                 //
1024                 public void EmitCapturedVariableInstance (LocalInfo li)
1025                 {
1026                         if (capture_context == null)
1027                                 throw new Exception ("Calling EmitCapturedContext when there is no capture_context");
1028                         
1029                         capture_context.EmitCapturedVariableInstance (this, li, CurrentAnonymousMethod);
1030                 }
1031
1032                 public void EmitParameter (string name, bool leave_copy, bool prepared, ref LocalTemporary temp)
1033                 {
1034                         capture_context.EmitParameter (this, name, leave_copy, prepared, ref temp);
1035                 }
1036
1037                 public void EmitAssignParameter (string name, Expression source, bool leave_copy, bool prepare_for_load, ref LocalTemporary  temp)
1038                 {
1039                         capture_context.EmitAssignParameter (this, name, source, leave_copy, prepare_for_load, ref temp);
1040                 }
1041
1042                 public void EmitAddressOfParameter (string name)
1043                 {
1044                         capture_context.EmitAddressOfParameter (this, name);
1045                 }
1046                 
1047                 public Expression GetThis (Location loc)
1048                 {
1049                         This my_this;
1050                         if (CurrentBlock != null)
1051                                 my_this = new This (CurrentBlock, loc);
1052                         else
1053                                 my_this = new This (loc);
1054
1055                         if (!my_this.ResolveBase (this))
1056                                 my_this = null;
1057
1058                         return my_this;
1059                 }
1060         }
1061
1062
1063         public abstract class CommonAssemblyModulClass : Attributable, IResolveContext {
1064
1065                 protected CommonAssemblyModulClass ():
1066                         base (null)
1067                 {
1068                 }
1069
1070                 public void AddAttributes (ArrayList attrs)
1071                 {
1072                         foreach (Attribute a in attrs)
1073                                 a.AttachTo (this);
1074
1075                         if (attributes == null) {
1076                                 attributes = new Attributes (attrs);
1077                                 return;
1078                         }
1079                         attributes.AddAttributes (attrs);
1080                 }
1081
1082                 public virtual void Emit (TypeContainer tc) 
1083                 {
1084                         if (OptAttributes == null)
1085                                 return;
1086
1087                         OptAttributes.Emit ();
1088                 }
1089
1090                 protected Attribute ResolveAttribute (Type a_type)
1091                 {
1092                         if (OptAttributes == null)
1093                                 return null;
1094
1095                         // Ensure that we only have GlobalAttributes, since the Search below isn't safe with other types.
1096                         if (!OptAttributes.CheckTargets ())
1097                                 return null;
1098
1099                         Attribute a = OptAttributes.Search (a_type);
1100                         if (a != null) {
1101                                 a.Resolve ();
1102                         }
1103                         return a;
1104                 }
1105
1106                 public override IResolveContext ResolveContext {
1107                         get { return this; }
1108                 }
1109
1110                 #region IResolveContext Members
1111
1112                 public DeclSpace DeclContainer {
1113                         get { return RootContext.ToplevelTypes; }
1114                 }
1115
1116                 public DeclSpace GenericDeclContainer {
1117                         get { return DeclContainer; }
1118                 }
1119
1120                 public bool IsInObsoleteScope {
1121                         get { return false; }
1122                 }
1123
1124                 public bool IsInUnsafeScope {
1125                         get { return false; }
1126                 }
1127
1128                 #endregion
1129         }
1130                 
1131         public class AssemblyClass : CommonAssemblyModulClass {
1132                 // TODO: make it private and move all builder based methods here
1133                 public AssemblyBuilder Builder;
1134                 public AssemblyName Name;
1135                     
1136                 bool is_cls_compliant;
1137                 bool wrap_non_exception_throws;
1138
1139                 public Attribute ClsCompliantAttribute;
1140
1141                 ListDictionary declarative_security;
1142                 MethodInfo add_type_forwarder;
1143
1144                 // Module is here just because of error messages
1145                 static string[] attribute_targets = new string [] { "assembly", "module" };
1146
1147                 public AssemblyClass (): base ()
1148                 {
1149                         wrap_non_exception_throws = true;
1150                 }
1151
1152                 public bool IsClsCompliant {
1153                         get {
1154                                 return is_cls_compliant;
1155                         }
1156                 }
1157
1158                 public bool WrapNonExceptionThrows {
1159                         get {
1160                                 return wrap_non_exception_throws;
1161                         }
1162                 }
1163
1164                 public override AttributeTargets AttributeTargets {
1165                         get {
1166                                 return AttributeTargets.Assembly;
1167                         }
1168                 }
1169
1170                 public override bool IsClsComplianceRequired ()
1171                 {
1172                         return is_cls_compliant;
1173                 }
1174
1175                 public void Resolve ()
1176                 {
1177                         ClsCompliantAttribute = ResolveAttribute (TypeManager.cls_compliant_attribute_type);
1178                         if (ClsCompliantAttribute != null) {
1179                                 is_cls_compliant = ClsCompliantAttribute.GetClsCompliantAttributeValue ();
1180                         }
1181
1182 #if GMCS_SOURCE
1183                         Attribute a = ResolveAttribute (TypeManager.runtime_compatibility_attr_type);
1184                         if (a != null) {
1185                                 object val = a.GetPropertyValue ("WrapNonExceptionThrows");
1186                                 if (val != null)
1187                                         wrap_non_exception_throws = (bool)val;
1188                         }
1189 #endif
1190                 }
1191
1192                 // fix bug #56621
1193                 private void SetPublicKey (AssemblyName an, byte[] strongNameBlob) 
1194                 {
1195                         try {
1196                                 // check for possible ECMA key
1197                                 if (strongNameBlob.Length == 16) {
1198                                         // will be rejected if not "the" ECMA key
1199                                         an.SetPublicKey (strongNameBlob);
1200                                 }
1201                                 else {
1202                                         // take it, with or without, a private key
1203                                         RSA rsa = CryptoConvert.FromCapiKeyBlob (strongNameBlob);
1204                                         // and make sure we only feed the public part to Sys.Ref
1205                                         byte[] publickey = CryptoConvert.ToCapiPublicKeyBlob (rsa);
1206                                         
1207                                         // AssemblyName.SetPublicKey requires an additional header
1208                                         byte[] publicKeyHeader = new byte [12] { 0x00, 0x24, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00 };
1209
1210                                         byte[] encodedPublicKey = new byte [12 + publickey.Length];
1211                                         Buffer.BlockCopy (publicKeyHeader, 0, encodedPublicKey, 0, 12);
1212                                         Buffer.BlockCopy (publickey, 0, encodedPublicKey, 12, publickey.Length);
1213                                         an.SetPublicKey (encodedPublicKey);
1214                                 }
1215                         }
1216                         catch (Exception) {
1217                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' is incorrectly encoded");
1218                                 Environment.Exit (1);
1219                         }
1220                 }
1221
1222                 // TODO: rewrite this code (to kill N bugs and make it faster) and use standard ApplyAttribute way.
1223                 public AssemblyName GetAssemblyName (string name, string output) 
1224                 {
1225                         if (OptAttributes != null) {
1226                                 foreach (Attribute a in OptAttributes.Attrs) {
1227                                         // cannot rely on any resolve-based members before you call Resolve
1228                                         if (a.ExplicitTarget == null || a.ExplicitTarget != "assembly")
1229                                                 continue;
1230
1231                                         // TODO: This code is buggy: comparing Attribute name without resolving is wrong.
1232                                         //       However, this is invoked by CodeGen.Init, when none of the namespaces
1233                                         //       are loaded yet.
1234                                         // TODO: Does not handle quoted attributes properly
1235                                         switch (a.Name) {
1236                                                 case "AssemblyKeyFile":
1237                                                 case "AssemblyKeyFileAttribute":
1238                                                 case "System.Reflection.AssemblyKeyFileAttribute":
1239                                                         if (RootContext.StrongNameKeyFile != null) {
1240                                                                 Report.SymbolRelatedToPreviousError (a.Location, a.Name);
1241                                                                 Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
1242                                     "keyfile", "System.Reflection.AssemblyKeyFileAttribute");
1243                                                         }
1244                                                         else {
1245                                                                 string value = a.GetString ();
1246                                                                 if (value.Length != 0)
1247                                                                         RootContext.StrongNameKeyFile = value;
1248                                                         }
1249                                                         break;
1250                                                 case "AssemblyKeyName":
1251                                                 case "AssemblyKeyNameAttribute":
1252                                                 case "System.Reflection.AssemblyKeyNameAttribute":
1253                                                         if (RootContext.StrongNameKeyContainer != null) {
1254                                                                 Report.SymbolRelatedToPreviousError (a.Location, a.Name);
1255                                                                 Report.Warning (1616, 1, "Option `{0}' overrides attribute `{1}' given in a source file or added module",
1256                                                                         "keycontainer", "System.Reflection.AssemblyKeyNameAttribute");
1257                                                         }
1258                                                         else {
1259                                                                 string value = a.GetString ();
1260                                                                 if (value.Length != 0)
1261                                                                         RootContext.StrongNameKeyContainer = value;
1262                                                         }
1263                                                         break;
1264                                                 case "AssemblyDelaySign":
1265                                                 case "AssemblyDelaySignAttribute":
1266                                                 case "System.Reflection.AssemblyDelaySignAttribute":
1267                                                         RootContext.StrongNameDelaySign = a.GetBoolean ();
1268                                                         break;
1269                                         }
1270                                 }
1271                         }
1272
1273                         AssemblyName an = new AssemblyName ();
1274                         an.Name = Path.GetFileNameWithoutExtension (name);
1275
1276                         // note: delay doesn't apply when using a key container
1277                         if (RootContext.StrongNameKeyContainer != null) {
1278                                 an.KeyPair = new StrongNameKeyPair (RootContext.StrongNameKeyContainer);
1279                                 return an;
1280                         }
1281
1282                         // strongname is optional
1283                         if (RootContext.StrongNameKeyFile == null)
1284                                 return an;
1285
1286                         string AssemblyDir = Path.GetDirectoryName (output);
1287
1288                         // the StrongName key file may be relative to (a) the compiled
1289                         // file or (b) to the output assembly. See bugzilla #55320
1290                         // http://bugzilla.ximian.com/show_bug.cgi?id=55320
1291
1292                         // (a) relative to the compiled file
1293                         string filename = Path.GetFullPath (RootContext.StrongNameKeyFile);
1294                         bool exist = File.Exists (filename);
1295                         if ((!exist) && (AssemblyDir != null) && (AssemblyDir != String.Empty)) {
1296                                 // (b) relative to the outputed assembly
1297                                 filename = Path.GetFullPath (Path.Combine (AssemblyDir, RootContext.StrongNameKeyFile));
1298                                 exist = File.Exists (filename);
1299                         }
1300
1301                         if (exist) {
1302                                 using (FileStream fs = new FileStream (filename, FileMode.Open, FileAccess.Read)) {
1303                                         byte[] snkeypair = new byte [fs.Length];
1304                                         fs.Read (snkeypair, 0, snkeypair.Length);
1305
1306                                         if (RootContext.StrongNameDelaySign) {
1307                                                 // delayed signing - DO NOT include private key
1308                                                 SetPublicKey (an, snkeypair);
1309                                         }
1310                                         else {
1311                                                 // no delay so we make sure we have the private key
1312                                                 try {
1313                                                         CryptoConvert.FromCapiPrivateKeyBlob (snkeypair);
1314                                                         an.KeyPair = new StrongNameKeyPair (snkeypair);
1315                                                 }
1316                                                 catch (CryptographicException) {
1317                                                         if (snkeypair.Length == 16) {
1318                                                                 // error # is different for ECMA key
1319                                                                 Report.Error (1606, "Could not sign the assembly. " + 
1320                                                                         "ECMA key can only be used to delay-sign assemblies");
1321                                                         }
1322                                                         else {
1323                                                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not have a private key");
1324                                                         }
1325                                                         return null;
1326                                                 }
1327                                         }
1328                                 }
1329                         }
1330                         else {
1331                                 Error_AssemblySigning ("The specified file `" + RootContext.StrongNameKeyFile + "' does not exist");
1332                                 return null;
1333                         }
1334                         return an;
1335                 }
1336
1337                 void Error_AssemblySigning (string text)
1338                 {
1339                         Report.Error (1548, "Error during assembly signing. " + text);
1340                 }
1341
1342                 bool CheckInternalsVisibleAttribute (Attribute a)
1343                 {
1344                         string assembly_name = a.GetString ();
1345                         if (assembly_name.Length == 0)
1346                                 return false;
1347                                 
1348                         AssemblyName aname = null;
1349                         try {
1350                                 aname = new AssemblyName (assembly_name);
1351                         } catch (FileLoadException) {
1352                         } catch (ArgumentException) {
1353                         }
1354                                 
1355                         // Bad assembly name format
1356                         if (aname == null)
1357                                 Report.Warning (1700, 3, a.Location, "Assembly reference `" + assembly_name + "' is invalid and cannot be resolved");
1358                         // Report error if we have defined Version or Culture
1359                         else if (aname.Version != null || aname.CultureInfo != null)
1360                                 throw new Exception ("Friend assembly `" + a.GetString () + 
1361                                                 "' is invalid. InternalsVisibleTo cannot have version or culture specified.");
1362                         else if (aname.GetPublicKey () == null && Name.GetPublicKey () != null) {
1363                                 Report.Error (1726, a.Location, "Friend assembly reference `" + aname.FullName + "' is invalid." +
1364                                                 " Strong named assemblies must specify a public key in their InternalsVisibleTo declarations");
1365                                 return false;
1366                         }
1367
1368                         return true;
1369                 }
1370
1371                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
1372                 {
1373                         if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (true)) {
1374                                 if (declarative_security == null)
1375                                         declarative_security = new ListDictionary ();
1376
1377                                 a.ExtractSecurityPermissionSet (declarative_security);
1378                                 return;
1379                         }
1380
1381                         if (a.Type == TypeManager.assembly_culture_attribute_type) {
1382                                 string value = a.GetString ();
1383                                 if (value == null || value.Length == 0)
1384                                         return;
1385
1386                                 if (RootContext.Target == Target.Exe) {
1387                                         a.Error_AttributeEmitError ("The executables cannot be satelite assemblies, remove the attribute or keep it empty");
1388                                         return;
1389                                 }
1390                         }
1391
1392                         if (a.Type == TypeManager.internals_visible_attr_type && !CheckInternalsVisibleAttribute (a))
1393                                 return;
1394
1395                         if (a.Type == TypeManager.type_forwarder_attr_type) {
1396                                 Type t = a.GetArgumentType ();
1397                                 if (t == null || TypeManager.HasElementType (t)) {
1398                                         Report.Error (735, a.Location, "Invalid type specified as an argument for TypeForwardedTo attribute");
1399                                         return;
1400                                 }
1401
1402                                 if (TypeManager.LookupDeclSpace (t) != null) {
1403                                         Report.SymbolRelatedToPreviousError (t);
1404                                         Report.Error (729, a.Location, "Cannot forward type `{0}' because it is defined in this assembly",
1405                                                 TypeManager.CSharpName (t));
1406                                         return;
1407                                 }
1408
1409                                 if (t.IsNested) {
1410                                         Report.Error (730, a.Location, "Cannot forward type `{0}' because it is a nested type",
1411                                                 TypeManager.CSharpName (t));
1412                                         return;
1413                                 }
1414
1415                                 if (t.IsGenericType) {
1416                                         Report.Error (733, a.Location, "Cannot forward generic type `{0}'", TypeManager.CSharpName (t));
1417                                         return;
1418                                 }
1419
1420                                 if (add_type_forwarder == null) {
1421                                         add_type_forwarder = typeof (AssemblyBuilder).GetMethod ("AddTypeForwarder",
1422                                                 BindingFlags.NonPublic | BindingFlags.Instance);
1423
1424                                         if (add_type_forwarder == null) {
1425                                                 Report.RuntimeMissingSupport (a.Location, "TypeForwardedTo attribute");
1426                                                 return;
1427                                         }
1428                                 }
1429
1430                                 add_type_forwarder.Invoke (Builder, new object[] { t });
1431                                 return;
1432                         }
1433                         
1434                         Builder.SetCustomAttribute (customBuilder);
1435                 }
1436
1437                 public override void Emit (TypeContainer tc)
1438                 {
1439                         base.Emit (tc);
1440
1441                         // FIXME: Does this belong inside SRE.AssemblyBuilder instead?
1442                         if (OptAttributes == null || !OptAttributes.Contains (TypeManager.runtime_compatibility_attr_type)) {
1443                                 ConstructorInfo ci = TypeManager.GetConstructor (
1444                                         TypeManager.runtime_compatibility_attr_type, Type.EmptyTypes);
1445                                 PropertyInfo [] pis = new PropertyInfo [1];
1446                                 pis [0] = TypeManager.GetProperty (
1447                                         TypeManager.runtime_compatibility_attr_type, "WrapNonExceptionThrows");
1448                                 object [] pargs = new object [1];
1449                                 pargs [0] = true;
1450                                 Builder.SetCustomAttribute (new CustomAttributeBuilder (ci, new object [0], pis, pargs));
1451                         }
1452
1453                         if (declarative_security != null) {
1454
1455                                 MethodInfo add_permission = typeof (AssemblyBuilder).GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
1456                                 object builder_instance = Builder;
1457
1458                                 try {
1459                                         // Microsoft runtime hacking
1460                                         if (add_permission == null) {
1461                                                 Type assembly_builder = typeof (AssemblyBuilder).Assembly.GetType ("System.Reflection.Emit.AssemblyBuilderData");
1462                                                 add_permission = assembly_builder.GetMethod ("AddPermissionRequests", BindingFlags.Instance | BindingFlags.NonPublic);
1463
1464                                                 FieldInfo fi = typeof (AssemblyBuilder).GetField ("m_assemblyData", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField);
1465                                                 builder_instance = fi.GetValue (Builder);
1466                                         }
1467
1468                                         object[] args = new object [] { declarative_security [SecurityAction.RequestMinimum],
1469                                                                                                   declarative_security [SecurityAction.RequestOptional],
1470                                                                                                   declarative_security [SecurityAction.RequestRefuse] };
1471                                         add_permission.Invoke (builder_instance, args);
1472                                 }
1473                                 catch {
1474                                         Report.RuntimeMissingSupport (Location.Null, "assembly permission setting");
1475                                 }
1476                         }
1477                 }
1478
1479                 public override string[] ValidAttributeTargets {
1480                         get {
1481                                 return attribute_targets;
1482                         }
1483                 }
1484         }
1485
1486         public class ModuleClass : CommonAssemblyModulClass {
1487                 // TODO: make it private and move all builder based methods here
1488                 public ModuleBuilder Builder;
1489                 bool m_module_is_unsafe;
1490
1491                 public CharSet DefaultCharSet = CharSet.Ansi;
1492                 public TypeAttributes DefaultCharSetType = TypeAttributes.AnsiClass;
1493
1494                 static string[] attribute_targets = new string [] { "module" };
1495
1496                 public ModuleClass (bool is_unsafe)
1497                 {
1498                         m_module_is_unsafe = is_unsafe;
1499                 }
1500
1501                 public override AttributeTargets AttributeTargets {
1502                         get {
1503                                 return AttributeTargets.Module;
1504                         }
1505                 }
1506
1507                 public override bool IsClsComplianceRequired ()
1508                 {
1509                         return CodeGen.Assembly.IsClsCompliant;
1510                 }
1511
1512                 public override void Emit (TypeContainer tc) 
1513                 {
1514                         base.Emit (tc);
1515
1516                         if (!m_module_is_unsafe)
1517                                 return;
1518
1519                         if (TypeManager.unverifiable_code_ctor == null) {
1520                                 Console.WriteLine ("Internal error ! Cannot set unverifiable code attribute.");
1521                                 return;
1522                         }
1523                                 
1524                         Builder.SetCustomAttribute (new CustomAttributeBuilder (TypeManager.unverifiable_code_ctor, new object [0]));
1525                 }
1526                 
1527                 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder customBuilder)
1528                 {
1529                         if (a.Type == TypeManager.cls_compliant_attribute_type) {
1530                                 if (CodeGen.Assembly.ClsCompliantAttribute == null) {
1531                                         Report.Warning (3012, 1, a.Location, "You must specify the CLSCompliant attribute on the assembly, not the module, to enable CLS compliance checking");
1532                                 }
1533                                 else if (CodeGen.Assembly.IsClsCompliant != a.GetBoolean ()) {
1534                                         Report.SymbolRelatedToPreviousError (CodeGen.Assembly.ClsCompliantAttribute.Location, CodeGen.Assembly.ClsCompliantAttribute.GetSignatureForError ());
1535                                         Report.Error (3017, a.Location, "You cannot specify the CLSCompliant attribute on a module that differs from the CLSCompliant attribute on the assembly");
1536                                         return;
1537                                 }
1538                         }
1539
1540                         Builder.SetCustomAttribute (customBuilder);
1541                 }
1542
1543                 /// <summary>
1544                 /// It is called very early therefore can resolve only predefined attributes
1545                 /// </summary>
1546                 public void ResolveAttributes ()
1547                 {
1548 #if GMCS_SOURCE
1549                         Attribute a = ResolveAttribute (TypeManager.default_charset_type);
1550                         if (a != null) {
1551                                 DefaultCharSet = a.GetCharSetValue ();
1552                                 switch (DefaultCharSet) {
1553                                         case CharSet.Ansi:
1554                                         case CharSet.None:
1555                                                 break;
1556                                         case CharSet.Auto:
1557                                                 DefaultCharSetType = TypeAttributes.AutoClass;
1558                                                 break;
1559                                         case CharSet.Unicode:
1560                                                 DefaultCharSetType = TypeAttributes.UnicodeClass;
1561                                                 break;
1562                                         default:
1563                                                 Report.Error (1724, a.Location, "Value specified for the argument to 'System.Runtime.InteropServices.DefaultCharSetAttribute' is not valid");
1564                                                 break;
1565                                 }
1566                         }
1567 #endif
1568                 }
1569
1570                 public override string[] ValidAttributeTargets {
1571                         get {
1572                                 return attribute_targets;
1573                         }
1574                 }
1575         }
1576 }