Fix Buildin typo
[mono.git] / mcs / mcs / method.cs
1 //
2 // method.cs: Method based declarations
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 //          Martin Baulig (martin@ximian.com)
6 //          Marek Safar (marek.safar@gmail.com)
7 //
8 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 //
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
12 //
13
14 using System;
15 using System.Collections.Generic;
16 using System.Security;
17 using System.Security.Permissions;
18 using System.Text;
19 using System.Linq;
20
21 #if NET_2_1
22 using XmlElement = System.Object;
23 #else
24 using System.Xml;
25 #endif
26
27 #if STATIC
28 using MetaType = IKVM.Reflection.Type;
29 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
30 using IKVM.Reflection;
31 using IKVM.Reflection.Emit;
32 #else
33 using MetaType = System.Type;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
37 #endif
38
39 using Mono.CompilerServices.SymbolWriter;
40
41 namespace Mono.CSharp {
42
43         public abstract class MethodCore : InterfaceMemberBase, IParametersMember
44         {
45                 protected ParametersCompiled parameters;
46                 protected ToplevelBlock block;
47                 protected MethodSpec spec;
48
49                 public MethodCore (DeclSpace parent, GenericMethod generic,
50                         FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
51                         MemberName name, Attributes attrs, ParametersCompiled parameters)
52                         : base (parent, generic, type, mod, allowed_mod, name, attrs)
53                 {
54                         this.parameters = parameters;
55                 }
56
57                 //
58                 //  Returns the System.Type array for the parameters of this method
59                 //
60                 public TypeSpec [] ParameterTypes {
61                         get {
62                                 return parameters.Types;
63                         }
64                 }
65
66                 public ParametersCompiled ParameterInfo {
67                         get {
68                                 return parameters;
69                         }
70                 }
71
72                 AParametersCollection IParametersMember.Parameters {
73                         get { return parameters; }
74                 }
75                 
76                 public ToplevelBlock Block {
77                         get {
78                                 return block;
79                         }
80
81                         set {
82                                 block = value;
83                         }
84                 }
85
86                 public CallingConventions CallingConventions {
87                         get {
88                                 CallingConventions cc = parameters.CallingConvention;
89                                 if (!IsInterface)
90                                         if ((ModFlags & Modifiers.STATIC) == 0)
91                                                 cc |= CallingConventions.HasThis;
92
93                                 // FIXME: How is `ExplicitThis' used in C#?
94                         
95                                 return cc;
96                         }
97                 }
98
99                 protected override bool CheckOverrideAgainstBase (MemberSpec base_member)
100                 {
101                         bool res = base.CheckOverrideAgainstBase (base_member);
102
103                         //
104                         // Check that the permissions are not being changed
105                         //
106                         if (!CheckAccessModifiers (this, base_member)) {
107                                 Error_CannotChangeAccessModifiers (this, base_member);
108                                 res = false;
109                         }
110
111                         return res;
112                 }
113
114                 protected override bool CheckBase ()
115                 {
116                         // Check whether arguments were correct.
117                         if (!DefineParameters (parameters))
118                                 return false;
119
120                         return base.CheckBase ();
121                 }
122
123                 //
124                 // Returns a string that represents the signature for this 
125                 // member which should be used in XML documentation.
126                 //
127                 public override string GetDocCommentName (DeclSpace ds)
128                 {
129                         return DocUtil.GetMethodDocCommentName (this, parameters, ds);
130                 }
131
132                 //
133                 // Raised (and passed an XmlElement that contains the comment)
134                 // when GenerateDocComment is writing documentation expectedly.
135                 //
136                 // FIXME: with a few effort, it could be done with XmlReader,
137                 // that means removal of DOM use.
138                 //
139                 internal override void OnGenerateDocComment (XmlElement el)
140                 {
141                         DocUtil.OnMethodGenerateDocComment (this, el, Report);
142                 }
143
144                 //
145                 //   Represents header string for documentation comment.
146                 //
147                 public override string DocCommentHeader 
148                 {
149                         get { return "M:"; }
150                 }
151
152                 public override bool EnableOverloadChecks (MemberCore overload)
153                 {
154                         if (overload is MethodCore) {
155                                 caching_flags |= Flags.MethodOverloadsExist;
156                                 return true;
157                         }
158
159                         if (overload is AbstractPropertyEventMethod)
160                                 return true;
161
162                         return base.EnableOverloadChecks (overload);
163                 }
164
165                 public MethodSpec Spec {
166                         get { return spec; }
167                 }
168
169                 protected override bool VerifyClsCompliance ()
170                 {
171                         if (!base.VerifyClsCompliance ())
172                                 return false;
173
174                         if (parameters.HasArglist) {
175                                 Report.Warning (3000, 1, Location, "Methods with variable arguments are not CLS-compliant");
176                         }
177
178                         if (member_type != null && !member_type.IsCLSCompliant ()) {
179                                 Report.Warning (3002, 1, Location, "Return type of `{0}' is not CLS-compliant",
180                                         GetSignatureForError ());
181                         }
182
183                         parameters.VerifyClsCompliance (this);
184                         return true;
185                 }
186         }
187
188         public interface IGenericMethodDefinition : IMemberDefinition
189         {
190                 TypeParameterSpec[] TypeParameters { get; }
191                 int TypeParametersCount { get; }
192
193 //              MethodInfo MakeGenericMethod (TypeSpec[] targs);
194         }
195
196         public sealed class MethodSpec : MemberSpec, IParametersMember
197         {
198                 MethodBase metaInfo, inflatedMetaInfo;
199                 AParametersCollection parameters;
200                 TypeSpec returnType;
201
202                 TypeSpec[] targs;
203                 TypeParameterSpec[] constraints;
204
205                 public MethodSpec (MemberKind kind, TypeSpec declaringType, IMemberDefinition details, TypeSpec returnType,
206                         MethodBase info, AParametersCollection parameters, Modifiers modifiers)
207                         : base (kind, declaringType, details, modifiers)
208                 {
209                         this.metaInfo = info;
210                         this.parameters = parameters;
211                         this.returnType = returnType;
212                 }
213
214                 #region Properties
215
216                 public override int Arity {
217                         get {
218                                 return IsGeneric ? GenericDefinition.TypeParametersCount : 0;
219                         }
220                 }
221
222                 public TypeParameterSpec[] Constraints {
223                         get {
224                                 if (constraints == null && IsGeneric)
225                                         constraints = GenericDefinition.TypeParameters;
226
227                                 return constraints;
228                         }
229                 }
230
231                 public bool IsConstructor {
232                         get {
233                                 return Kind == MemberKind.Constructor;
234                         }
235                 }
236
237                 public IGenericMethodDefinition GenericDefinition {
238                         get {
239                                 return (IGenericMethodDefinition) definition;
240                         }
241                 }
242
243                 public bool IsExtensionMethod {
244                         get {
245                                 return IsStatic && parameters.HasExtensionMethodType;
246                         }
247                 }
248
249                 public bool IsSealed {
250                         get {
251                                 return (Modifiers & Modifiers.SEALED) != 0;
252                         }
253                 }
254
255                 // When is virtual or abstract
256                 public bool IsVirtual {
257                         get {
258                                 return (Modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) != 0;
259                         }
260                 }
261
262                 public bool IsReservedMethod {
263                         get {
264                                 return Kind == MemberKind.Operator || IsAccessor;
265                         }
266                 }
267
268                 TypeSpec IInterfaceMemberSpec.MemberType {
269                         get {
270                                 return returnType;
271                         }
272                 }
273
274                 public AParametersCollection Parameters {
275                         get { 
276                                 return parameters;
277                         }
278                 }
279
280                 public TypeSpec ReturnType {
281                         get {
282                                 return returnType;
283                         }
284                 }
285
286                 public TypeSpec[] TypeArguments {
287                         get {
288                                 return targs;
289                         }
290                 }
291
292                 #endregion
293
294                 public MethodSpec GetGenericMethodDefinition ()
295                 {
296                         if (!IsGeneric && !DeclaringType.IsGeneric)
297                                 return this;
298
299                         return MemberCache.GetMember (declaringType, this);
300                 }
301
302                 public MethodBase GetMetaInfo ()
303                 {
304                         //
305                         // inflatedMetaInfo is extra field needed for cases where we
306                         // inflate method but another nested type can later inflate
307                         // again (the cache would be build with inflated metaInfo) and
308                         // TypeBuilder can work with method definitions only
309                         //
310                         if (inflatedMetaInfo == null) {
311                                 if ((state & StateFlags.PendingMetaInflate) != 0) {
312                                         var dt_meta = DeclaringType.GetMetaInfo ();
313
314                                         if (DeclaringType.IsTypeBuilder) {
315                                                 if (IsConstructor)
316                                                         inflatedMetaInfo = TypeBuilder.GetConstructor (dt_meta, (ConstructorInfo) metaInfo);
317                                                 else
318                                                         inflatedMetaInfo = TypeBuilder.GetMethod (dt_meta, (MethodInfo) metaInfo);
319                                         } else {
320 #if STATIC
321                                                 // it should not be reached
322                                                 throw new NotImplementedException ();
323 #else
324                                                 inflatedMetaInfo = MethodInfo.GetMethodFromHandle (metaInfo.MethodHandle, dt_meta.TypeHandle);
325 #endif
326                                         }
327
328                                         state &= ~StateFlags.PendingMetaInflate;
329                                 } else {
330                                         inflatedMetaInfo = metaInfo;
331                                 }
332                         }
333
334                         if ((state & StateFlags.PendingMakeMethod) != 0) {
335                                 var sre_targs = new MetaType[targs.Length];
336                                 for (int i = 0; i < sre_targs.Length; ++i)
337                                         sre_targs[i] = targs[i].GetMetaInfo ();
338
339                                 inflatedMetaInfo = ((MethodInfo) inflatedMetaInfo).MakeGenericMethod (sre_targs);
340                                 state &= ~StateFlags.PendingMakeMethod;
341                         }
342
343                         return inflatedMetaInfo;
344                 }
345
346                 public override string GetSignatureForError ()
347                 {
348                         string name;
349                         if (IsConstructor) {
350                                 name = DeclaringType.GetSignatureForError () + "." + DeclaringType.Name;
351                         } else if (Kind == MemberKind.Operator) {
352                                 var op = Operator.GetType (Name).Value;
353                                 if (op == Operator.OpType.Implicit || op == Operator.OpType.Explicit) {
354                                         name = DeclaringType.GetSignatureForError () + "." + Operator.GetName (op) + " operator " + returnType.GetSignatureForError ();
355                                 } else {
356                                         name = DeclaringType.GetSignatureForError () + ".operator " + Operator.GetName (op);
357                                 }
358                         } else if (IsAccessor) {
359                                 int split = Name.IndexOf ('_');
360                                 name = Name.Substring (split + 1);
361                                 var postfix = Name.Substring (0, split);
362                                 if (split == 3) {
363                                         var pc = parameters.Count;
364                                         if (pc > 0 && postfix == "get") {
365                                                 name = "this" + parameters.GetSignatureForError ("[", "]", pc);
366                                         } else if (pc > 1 && postfix == "set") {
367                                                 name = "this" + parameters.GetSignatureForError ("[", "]", pc - 1);
368                                         }
369                                 }
370
371                                 return DeclaringType.GetSignatureForError () + "." + name + "." + postfix;
372                         } else {
373                                 name = base.GetSignatureForError ();
374                                 if (targs != null)
375                                         name += "<" + TypeManager.CSharpName (targs) + ">";
376                                 else if (IsGeneric)
377                                         name += "<" + TypeManager.CSharpName (GenericDefinition.TypeParameters) + ">";
378                         }
379
380                         return name + parameters.GetSignatureForError ();
381                 }
382
383                 public override MemberSpec InflateMember (TypeParameterInflator inflator)
384                 {
385                         var ms = (MethodSpec) base.InflateMember (inflator);
386                         ms.inflatedMetaInfo = null;
387                         ms.returnType = inflator.Inflate (returnType);
388                         ms.parameters = parameters.Inflate (inflator);
389                         if (IsGeneric)
390                                 ms.constraints = TypeParameterSpec.InflateConstraints (inflator, Constraints);
391
392                         return ms;
393                 }
394
395                 public MethodSpec MakeGenericMethod (IMemberContext context, params TypeSpec[] targs)
396                 {
397                         if (targs == null)
398                                 throw new ArgumentNullException ();
399 // TODO MemberCache
400 //                      if (generic_intances != null && generic_intances.TryGetValue (targs, out ginstance))
401 //                              return ginstance;
402
403                         //if (generic_intances == null)
404                         //    generic_intances = new Dictionary<TypeSpec[], Method> (TypeSpecArrayComparer.Default);
405
406                         var inflator = new TypeParameterInflator (context, DeclaringType, GenericDefinition.TypeParameters, targs);
407
408                         var inflated = (MethodSpec) MemberwiseClone ();
409                         inflated.declaringType = inflator.TypeInstance;
410                         inflated.returnType = inflator.Inflate (returnType);
411                         inflated.parameters = parameters.Inflate (inflator);
412                         inflated.targs = targs;
413                         inflated.constraints = TypeParameterSpec.InflateConstraints (inflator, constraints ?? GenericDefinition.TypeParameters);
414                         inflated.state |= StateFlags.PendingMakeMethod;
415
416                         //                      if (inflated.parent == null)
417                         //                              inflated.parent = parent;
418
419                         //generic_intances.Add (targs, inflated);
420                         return inflated;
421                 }
422
423                 public MethodSpec Mutate (TypeParameterMutator mutator)
424                 {
425                         var targs = TypeArguments;
426                         if (targs != null)
427                                 targs = mutator.Mutate (targs);
428
429                         var decl = DeclaringType;
430                         if (DeclaringType.IsGenericOrParentIsGeneric) {
431                                 decl = mutator.Mutate (decl);
432                         }
433
434                         if (targs == TypeArguments && decl == DeclaringType)
435                                 return this;
436
437                         var ms = (MethodSpec) MemberwiseClone ();
438                         if (decl != DeclaringType) {
439                                 ms.inflatedMetaInfo = null;
440                                 ms.declaringType = decl;
441                                 ms.state |= StateFlags.PendingMetaInflate;
442                         }
443
444                         if (targs != null) {
445                                 ms.targs = targs;
446                                 ms.state |= StateFlags.PendingMakeMethod;
447                         }
448
449                         return ms;
450                 }
451
452                 public override List<TypeSpec> ResolveMissingDependencies ()
453                 {
454                         var missing = returnType.ResolveMissingDependencies ();
455                         foreach (var pt in parameters.Types) {
456                                 var m = pt.GetMissingDependencies ();
457                                 if (m == null)
458                                         continue;
459
460                                 if (missing == null)
461                                         missing = new List<TypeSpec> ();
462
463                                 missing.AddRange (m);
464                         }
465
466                         return missing;                 
467                 }
468
469                 public void SetMetaInfo (MethodInfo info)
470                 {
471                         if (this.metaInfo != null)
472                                 throw new InternalErrorException ("MetaInfo reset");
473
474                         this.metaInfo = info;
475                 }
476         }
477
478         public abstract class MethodOrOperator : MethodCore, IMethodData
479         {
480                 public MethodBuilder MethodBuilder;
481                 ReturnParameter return_attributes;
482                 SecurityType declarative_security;
483                 protected MethodData MethodData;
484
485                 static readonly string[] attribute_targets = new string [] { "method", "return" };
486
487                 protected MethodOrOperator (DeclSpace parent, GenericMethod generic, FullNamedExpression type, Modifiers mod,
488                                 Modifiers allowed_mod, MemberName name,
489                                 Attributes attrs, ParametersCompiled parameters)
490                         : base (parent, generic, type, mod, allowed_mod, name,
491                                         attrs, parameters)
492                 {
493                 }
494
495                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
496                 {
497                         if (a.Target == AttributeTargets.ReturnValue) {
498                                 if (return_attributes == null)
499                                         return_attributes = new ReturnParameter (this, MethodBuilder, Location);
500
501                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
502                                 return;
503                         }
504
505                         if (a.Type == pa.MethodImpl) {
506                                 is_external_implementation = a.IsInternalCall ();
507                         }
508
509                         if (a.Type == pa.DllImport) {
510                                 const Modifiers extern_static = Modifiers.EXTERN | Modifiers.STATIC;
511                                 if ((ModFlags & extern_static) != extern_static) {
512                                         Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
513                                 }
514                                 is_external_implementation = true;
515                         }
516
517                         if (a.IsValidSecurityAttribute ()) {
518                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
519                                 return;
520                         }
521
522                         if (MethodBuilder != null)
523                                 MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
524                 }
525
526                 public override AttributeTargets AttributeTargets {
527                         get {
528                                 return AttributeTargets.Method; 
529                         }
530                 }
531
532                 protected override bool CheckForDuplications ()
533                 {
534                         return Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
535                 }
536
537                 public virtual EmitContext CreateEmitContext (ILGenerator ig)
538                 {
539                         return new EmitContext (this, ig, MemberType);
540                 }
541
542                 public override bool Define ()
543                 {
544                         if (!base.Define ())
545                                 return false;
546
547                         if (!CheckBase ())
548                                 return false;
549
550                         MemberKind kind;
551                         if (this is Operator)
552                                 kind = MemberKind.Operator;
553                         else if (this is Destructor)
554                                 kind = MemberKind.Destructor;
555                         else
556                                 kind = MemberKind.Method;
557
558                         if (IsPartialDefinition) {
559                                 caching_flags &= ~Flags.Excluded_Undetected;
560                                 caching_flags |= Flags.Excluded;
561
562                                 // Add to member cache only when a partial method implementation has not been found yet
563                                 if ((caching_flags & Flags.PartialDefinitionExists) == 0) {
564 //                                      MethodBase mb = new PartialMethodDefinitionInfo (this);
565
566                                         spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, null, parameters, ModFlags);
567                                         Parent.MemberCache.AddMember (spec);
568                                 }
569
570                                 return true;
571                         }
572
573                         MethodData = new MethodData (
574                                 this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method);
575
576                         if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report))
577                                 return false;
578                                         
579                         MethodBuilder = MethodData.MethodBuilder;
580
581                         spec = new MethodSpec (kind, Parent.Definition, this, ReturnType, MethodBuilder, parameters, ModFlags);
582                         if (MemberName.Arity > 0)
583                                 spec.IsGeneric = true;
584                         
585                         Parent.MemberCache.AddMember (this, MethodBuilder.Name, spec);
586
587                         return true;
588                 }
589
590                 protected override void DoMemberTypeIndependentChecks ()
591                 {
592                         base.DoMemberTypeIndependentChecks ();
593
594                         CheckAbstractAndExtern (block != null);
595
596                         if ((ModFlags & Modifiers.PARTIAL) != 0) {
597                                 for (int i = 0; i < parameters.Count; ++i) {
598                                         IParameterData p = parameters.FixedParameters [i];
599                                         if (p.ModFlags == Parameter.Modifier.OUT) {
600                                                 Report.Error (752, Location, "`{0}': A partial method parameters cannot use `out' modifier",
601                                                         GetSignatureForError ());
602                                         }
603
604                                         if (p.HasDefaultValue && IsPartialImplementation)
605                                                 ((Parameter) p).Warning_UselessOptionalParameter (Report);
606                                 }
607                         }
608                 }
609
610                 protected override void DoMemberTypeDependentChecks ()
611                 {
612                         base.DoMemberTypeDependentChecks ();
613
614                         if (MemberType.IsStatic) {
615                                 Error_StaticReturnType ();
616                         }
617                 }
618
619                 public override void Emit ()
620                 {
621                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
622                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (MethodBuilder);
623                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
624                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (MethodBuilder);
625
626                         if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
627                                 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
628                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
629                         } else if (ReturnType.HasDynamicElement) {
630                                 return_attributes = new ReturnParameter (this, MethodBuilder, Location);
631                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
632                         }
633
634                         if (OptAttributes != null)
635                                 OptAttributes.Emit ();
636
637                         if (declarative_security != null) {
638                                 foreach (var de in declarative_security) {
639 #if STATIC
640                                         MethodBuilder.__AddDeclarativeSecurity (de);
641 #else
642                                         MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
643 #endif
644                                 }
645                         }
646
647                         if (MethodData != null)
648                                 MethodData.Emit (Parent);
649
650                         base.Emit ();
651
652                         Block = null;
653                         MethodData = null;
654                 }
655
656                 protected void Error_ConditionalAttributeIsNotValid ()
657                 {
658                         Report.Error (577, Location,
659                                 "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
660                                 GetSignatureForError ());
661                 }
662
663                 public bool IsPartialDefinition {
664                         get {
665                                 return (ModFlags & Modifiers.PARTIAL) != 0 && Block == null;
666                         }
667                 }
668
669                 public bool IsPartialImplementation {
670                         get {
671                                 return (ModFlags & Modifiers.PARTIAL) != 0 && Block != null;
672                         }
673                 }
674
675                 public override string[] ValidAttributeTargets {
676                         get {
677                                 return attribute_targets;
678                         }
679                 }
680
681                 #region IMethodData Members
682
683                 public TypeSpec ReturnType {
684                         get {
685                                 return MemberType;
686                         }
687                 }
688
689                 public MemberName MethodName {
690                         get {
691                                 return MemberName;
692                         }
693                 }
694
695                 /// <summary>
696                 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
697                 /// </summary>
698                 public override string[] ConditionalConditions ()
699                 {
700                         if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
701                                 return null;
702
703                         if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.Excluded) != 0)
704                                 return new string [0];
705
706                         caching_flags &= ~Flags.Excluded_Undetected;
707                         string[] conditions;
708
709                         if (base_method == null) {
710                                 if (OptAttributes == null)
711                                         return null;
712
713                                 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
714                                 if (attrs == null)
715                                         return null;
716
717                                 conditions = new string[attrs.Length];
718                                 for (int i = 0; i < conditions.Length; ++i)
719                                         conditions[i] = attrs[i].GetConditionalAttributeValue ();
720                         } else {
721                                 conditions = base_method.MemberDefinition.ConditionalConditions();
722                         }
723
724                         if (conditions != null)
725                                 caching_flags |= Flags.Excluded;
726
727                         return conditions;
728                 }
729
730                 GenericMethod IMethodData.GenericMethod {
731                         get {
732                                 return GenericMethod;
733                         }
734                 }
735
736                 public virtual void EmitExtraSymbolInfo (SourceMethod source)
737                 { }
738
739                 #endregion
740
741         }
742
743         public class SourceMethod : IMethodDef
744         {
745                 MethodBase method;
746                 SourceMethodBuilder builder;
747
748                 protected SourceMethod (DeclSpace parent, MethodBase method, ICompileUnit file)
749                 {
750                         this.method = method;
751                         
752                         builder = SymbolWriter.OpenMethod (file, parent.NamespaceEntry.SymbolFileID, this);
753                 }
754
755                 public string Name {
756                         get { return method.Name; }
757                 }
758
759                 public int Token {
760                         get {
761                                 MethodToken token;
762                                 var mb = method as MethodBuilder;
763                                 if (mb != null)
764                                         token = mb.GetToken ();
765                                 else
766                                         token = ((ConstructorBuilder) method).GetToken ();
767 #if STATIC
768                                 if (token.IsPseudoToken)
769                                         return ((ModuleBuilder) method.Module).ResolvePseudoToken (token.Token);
770 #endif
771                                 return token.Token;
772                         }
773                 }
774
775                 public void CloseMethod ()
776                 {
777                         SymbolWriter.CloseMethod ();
778                 }
779
780                 public void SetRealMethodName (string name)
781                 {
782                         if (builder != null)
783                                 builder.SetRealMethodName (name);
784                 }
785
786                 public static SourceMethod Create (DeclSpace parent, MethodBase method, Block block)
787                 {
788                         if (!SymbolWriter.HasSymbolWriter)
789                                 return null;
790                         if (block == null)
791                                 return null;
792
793                         Location start_loc = block.StartLocation;
794                         if (start_loc.IsNull)
795                                 return null;
796
797                         ICompileUnit compile_unit = start_loc.CompilationUnit;
798                         if (compile_unit == null)
799                                 return null;
800
801                         return new SourceMethod (parent, method, compile_unit);
802                 }
803         }
804
805         public class Method : MethodOrOperator, IGenericMethodDefinition
806         {
807                 Method partialMethodImplementation;
808
809                 public Method (DeclSpace parent, GenericMethod generic,
810                                FullNamedExpression return_type, Modifiers mod,
811                                MemberName name, ParametersCompiled parameters, Attributes attrs)
812                         : base (parent, generic, return_type, mod,
813                                 parent.PartialContainer.Kind == MemberKind.Interface ? AllowedModifiersInterface :
814                                 parent.PartialContainer.Kind == MemberKind.Struct ? AllowedModifiersStruct :
815                                 AllowedModifiersClass,
816                                 name, attrs, parameters)
817                 {
818                 }
819
820                 protected Method (DeclSpace parent, FullNamedExpression return_type, Modifiers mod, Modifiers amod,
821                                         MemberName name, ParametersCompiled parameters, Attributes attrs)
822                         : base (parent, null, return_type, mod, amod, name, attrs, parameters)
823                 {
824                 }
825
826                 #region Properties
827
828                 public override TypeParameter[] CurrentTypeParameters {
829                         get {
830                                 if (GenericMethod != null)
831                                         return GenericMethod.CurrentTypeParameters;
832
833                                 return null;
834                         }
835                 }
836
837                 public override bool HasUnresolvedConstraints {
838                         get {
839                                 if (CurrentTypeParameters == null)
840                                         return false;
841
842                                 // When overriding base method constraints are fetched from
843                                 // base method but to find it we have to resolve parameters
844                                 // to find exact base method match
845                                 if (IsExplicitImpl || (ModFlags & Modifiers.OVERRIDE) != 0)
846                                         return base_method == null;
847
848                                 // Even for non-override generic method constraints check has to be
849                                 // delayed after all constraints are resolved
850                                 return true;
851                         }
852                 }
853
854                 public TypeParameterSpec[] TypeParameters {
855                         get {
856                                 // TODO: Cache this
857                                 return CurrentTypeParameters.Select (l => l.Type).ToArray ();
858                         }
859                 }
860
861                 public int TypeParametersCount {
862                         get {
863                                 return CurrentTypeParameters == null ? 0 : CurrentTypeParameters.Length;
864                         }
865                 }
866
867 #endregion
868
869                 public override string GetSignatureForError()
870                 {
871                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
872                 }
873
874                 void Error_DuplicateEntryPoint (Method b)
875                 {
876                         Report.Error (17, b.Location,
877                                 "Program `{0}' has more than one entry point defined: `{1}'",
878                                 b.Module.Builder.ScopeName, b.GetSignatureForError ());
879                 }
880
881                 bool IsEntryPoint ()
882                 {
883                         if (ReturnType.Kind != MemberKind.Void && ReturnType.BuiltinType != BuiltinTypeSpec.Type.Int)
884                                 return false;
885
886                         if (parameters.IsEmpty)
887                                 return true;
888
889                         if (parameters.Count > 1)
890                                 return false;
891
892                         var ac = parameters.Types [0] as ArrayContainer;
893                         return ac != null && ac.Rank == 1 && ac.Element.BuiltinType == BuiltinTypeSpec.Type.String &&
894                                         (parameters[0].ModFlags & ~Parameter.Modifier.PARAMS) == Parameter.Modifier.NONE;
895                 }
896
897                 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, Location loc, bool ignore_cs0104)
898                 {
899                         if (arity == 0) {
900                                 TypeParameter[] tp = CurrentTypeParameters;
901                                 if (tp != null) {
902                                         TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
903                                         if (t != null)
904                                                 return new TypeParameterExpr (t, loc);
905                                 }
906                         }
907
908                         return base.LookupNamespaceOrType (name, arity, loc, ignore_cs0104);
909                 }
910
911                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
912                 {
913                         if (a.Type == pa.Conditional) {
914                                 if (IsExplicitImpl) {
915                                         Error_ConditionalAttributeIsNotValid ();
916                                         return;
917                                 }
918
919                                 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
920                                         Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
921                                         return;
922                                 }
923
924                                 if (ReturnType.Kind != MemberKind.Void) {
925                                         Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
926                                         return;
927                                 }
928
929                                 if (IsInterface) {
930                                         Report.Error (582, Location, "Conditional not valid on interface members");
931                                         return;
932                                 }
933
934                                 if (MethodData.implementing != null) {
935                                         Report.SymbolRelatedToPreviousError (MethodData.implementing.DeclaringType);
936                                         Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
937                                                 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
938                                         return;
939                                 }
940
941                                 for (int i = 0; i < parameters.Count; ++i) {
942                                         if (parameters.FixedParameters [i].ModFlags == Parameter.Modifier.OUT) {
943                                                 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
944                                                 return;
945                                         }
946                                 }
947                         }
948
949                         if (a.Type == pa.Extension) {
950                                 a.Error_MisusedExtensionAttribute ();
951                                 return;
952                         }
953
954                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
955                 }
956
957                 protected virtual void DefineTypeParameters ()
958                 {
959                         var tparams = CurrentTypeParameters;
960
961                         TypeParameterSpec[] base_tparams = null;
962                         TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
963                         TypeSpec[] base_targs = TypeSpec.EmptyTypes;
964                         if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
965                                 if (base_method != null) {
966                                         base_tparams = base_method.GenericDefinition.TypeParameters;
967                                 
968                                         if (base_method.DeclaringType.IsGeneric) {
969                                                 base_decl_tparams = base_method.DeclaringType.MemberDefinition.TypeParameters;
970
971                                                 var base_type_parent = CurrentType;
972                                                 while (base_type_parent.BaseType != base_method.DeclaringType) {
973                                                         base_type_parent = base_type_parent.BaseType;
974                                                 }
975
976                                                 base_targs = base_type_parent.BaseType.TypeArguments;
977                                         }
978
979                                         if (base_method.IsGeneric) {
980                                                 ObsoleteAttribute oa;
981                                                 foreach (var base_tp in base_tparams) {
982                                                         oa = base_tp.BaseType.GetAttributeObsolete ();
983                                                         if (oa != null) {
984                                                                 AttributeTester.Report_ObsoleteMessage (oa, base_tp.BaseType.GetSignatureForError (), Location, Report);
985                                                         }
986
987                                                         if (base_tp.InterfacesDefined != null) {
988                                                                 foreach (var iface in base_tp.InterfacesDefined) {
989                                                                         oa = iface.GetAttributeObsolete ();
990                                                                         if (oa != null) {
991                                                                                 AttributeTester.Report_ObsoleteMessage (oa, iface.GetSignatureForError (), Location, Report);
992                                                                         }
993                                                                 }
994                                                         }
995                                                 }
996
997                                                 if (base_decl_tparams.Length != 0) {
998                                                         base_decl_tparams = base_decl_tparams.Concat (base_tparams).ToArray ();
999                                                         base_targs = base_targs.Concat (tparams.Select<TypeParameter, TypeSpec> (l => l.Type)).ToArray ();
1000                                                 } else {
1001                                                         base_decl_tparams = base_tparams;
1002                                                         base_targs = tparams.Select (l => l.Type).ToArray ();
1003                                                 }
1004                                         }
1005                                 } else if (MethodData.implementing != null) {
1006                                         base_tparams = MethodData.implementing.GenericDefinition.TypeParameters;
1007                                         if (MethodData.implementing.DeclaringType.IsGeneric) {
1008                                                 base_decl_tparams = MethodData.implementing.DeclaringType.MemberDefinition.TypeParameters;
1009                                                 foreach (var iface in Parent.CurrentType.Interfaces) {
1010                                                         if (iface == MethodData.implementing.DeclaringType) {
1011                                                                 base_targs = iface.TypeArguments;
1012                                                                 break;
1013                                                         }
1014                                                 }
1015                                         }
1016                                 }
1017                         }
1018
1019                         for (int i = 0; i < tparams.Length; ++i) {
1020                                 var tp = tparams[i];
1021
1022                                 if (!tp.ResolveConstraints (this))
1023                                         continue;
1024
1025                                 //
1026                                 // Copy base constraints for override/explicit methods
1027                                 //
1028                                 if (base_tparams != null) {
1029                                         var base_tparam = base_tparams[i];
1030                                         var local_tparam = tp.Type;
1031                                         local_tparam.SpecialConstraint = base_tparam.SpecialConstraint;
1032
1033                                         var inflator = new TypeParameterInflator (this, CurrentType, base_decl_tparams, base_targs);
1034                                         base_tparam.InflateConstraints (inflator, local_tparam);
1035
1036                                         //
1037                                         // Check all type argument constraints for possible collision
1038                                         // introduced by inflating inherited constraints in this context
1039                                         //
1040                                         // Conflict example:
1041                                         //
1042                                         // class A<T> { virtual void Foo<U> () where U : class, T {} }
1043                                         // class B : A<int> { override void Foo<U> {} }
1044                                         //
1045                                         var local_tparam_targs = local_tparam.TypeArguments;
1046                                         if (local_tparam_targs != null) {                                       
1047                                                 for (int ii = 0; ii < local_tparam_targs.Length; ++ii) {
1048                                                         var ta = local_tparam_targs [ii];
1049                                                         if (!ta.IsClass && !ta.IsStruct)
1050                                                                 continue;
1051
1052                                                         if (Constraints.CheckConflictingInheritedConstraint (local_tparam, ta, this, Location)) {
1053                                                                 local_tparam.ChangeTypeArgumentToBaseType (ii);
1054                                                         }
1055                                                 }
1056                                         }
1057
1058                                         continue;
1059                                 }
1060                                 
1061                                 if (MethodData.implementing != null) {
1062                                         var base_tp = MethodData.implementing.Constraints[i];
1063                                         if (!tp.Type.HasSameConstraintsImplementation (base_tp)) {
1064                                                 Report.SymbolRelatedToPreviousError (MethodData.implementing);
1065                                                 Report.Error (425, Location,
1066                                                         "The constraints for type parameter `{0}' of method `{1}' must match the constraints for type parameter `{2}' of interface method `{3}'. Consider using an explicit interface implementation instead",
1067                                                         tp.GetSignatureForError (), GetSignatureForError (), base_tp.GetSignatureForError (), MethodData.implementing.GetSignatureForError ());
1068                                         }
1069                                 }
1070                         }
1071                 }
1072
1073                 //
1074                 // Creates the type
1075                 //
1076                 public override bool Define ()
1077                 {
1078                         if (!base.Define ())
1079                                 return false;
1080
1081                         if (type_expr.Type.Kind == MemberKind.Void && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
1082                                 Report.Warning (465, 1, Location,
1083                                         "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
1084                         }
1085
1086                         if (partialMethodImplementation != null && IsPartialDefinition)
1087                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1088
1089                         if (Compiler.Settings.StdLib && ReturnType.IsSpecialRuntimeType) {
1090                                 Error1599 (Location, ReturnType, Report);
1091                                 return false;
1092                         }
1093
1094                         if (CurrentTypeParameters == null) {
1095                                 if (base_method != null) {
1096                                         if (parameters.Count == 1 && ParameterTypes[0].BuiltinType == BuiltinTypeSpec.Type.Object && Name == "Equals")
1097                                                 Parent.PartialContainer.Mark_HasEquals ();
1098                                         else if (parameters.IsEmpty && Name == "GetHashCode")
1099                                                 Parent.PartialContainer.Mark_HasGetHashCode ();
1100                                 }
1101                                         
1102                         } else {
1103                                 DefineTypeParameters ();
1104                         }
1105
1106                         if (block != null && block.IsIterator) {
1107                                 //
1108                                 // Current method is turned into automatically generated
1109                                 // wrapper which creates an instance of iterator
1110                                 //
1111                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1112                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
1113                         }
1114
1115                         if ((ModFlags & Modifiers.STATIC) == 0)
1116                                 return true;
1117
1118                         if (parameters.HasExtensionMethodType) {
1119                                 if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) {
1120                                         if (!Parent.IsTopLevel)
1121                                                 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
1122                                                         GetSignatureForError ());
1123
1124                                         PredefinedAttribute pa = Module.PredefinedAttributes.Extension;
1125                                         if (!pa.IsDefined) {
1126                                                 Report.Error (1110, Location,
1127                                                         "`{0}': Extension methods cannot be declared without a reference to System.Core.dll assembly. Add the assembly reference or remove `this' modifer from the first parameter",
1128                                                         GetSignatureForError ());
1129                                         }
1130
1131                                         ModFlags |= Modifiers.METHOD_EXTENSION;
1132                                         Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
1133                                         Spec.DeclaringType.SetExtensionMethodContainer ();
1134                                         Parent.Module.HasExtensionMethod = true;
1135                                 } else {
1136                                         Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
1137                                                 GetSignatureForError ());
1138                                 }
1139                         }
1140
1141                         //
1142                         // This is used to track the Entry Point,
1143                         //
1144                         var settings = Compiler.Settings;
1145                         if (settings.NeedsEntryPoint && Name == "Main" && (settings.MainClass == null || settings.MainClass == Parent.TypeBuilder.FullName)) {
1146                                 if (IsEntryPoint ()) {
1147                                         if (Parent.DeclaringAssembly.EntryPoint == null) {
1148                                                 if (Parent.IsGeneric || MemberName.IsGeneric) {
1149                                                         Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1150                                                                 GetSignatureForError ());
1151                                                 } else {
1152                                                         SetIsUsed ();
1153                                                         Parent.DeclaringAssembly.EntryPoint = this;
1154                                                 }
1155                                         } else {
1156                                                 Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
1157                                                 Error_DuplicateEntryPoint (this);
1158                                         }
1159                                 } else {
1160                                         Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1161                                                 GetSignatureForError ());
1162                                 }
1163                         }
1164
1165                         return true;
1166                 }
1167
1168                 //
1169                 // Emits the code
1170                 // 
1171                 public override void Emit ()
1172                 {
1173                         try {
1174                                 if (IsPartialDefinition) {
1175                                         //
1176                                         // Use partial method implementation builder for partial method declaration attributes
1177                                         //
1178                                         if (partialMethodImplementation != null) {
1179                                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1180                                         }
1181
1182                                         return;
1183                                 }
1184                                 
1185                                 if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1186                                         Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1187                                                 GetSignatureForError ());
1188                                 }
1189
1190                                 if (CurrentTypeParameters != null) {
1191                                         var ge = type_expr as GenericTypeExpr;
1192                                         if (ge != null)
1193                                                 ge.CheckConstraints (this);
1194
1195                                         foreach (Parameter p in parameters.FixedParameters) {
1196                                                 ge = p.TypeExpression as GenericTypeExpr;
1197                                                 if (ge != null)
1198                                                         ge.CheckConstraints (this);
1199                                         }
1200
1201                                         for (int i = 0; i < CurrentTypeParameters.Length; ++i) {
1202                                                 var tp = CurrentTypeParameters [i];
1203                                                 tp.CheckGenericConstraints ();
1204                                                 tp.Emit ();
1205                                         }
1206                                 }
1207
1208                                 base.Emit ();
1209                                 
1210                                 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1211                                         Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder);
1212                         } catch {
1213                                 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
1214                                                    Location, MethodBuilder);
1215                                 throw;
1216                         }
1217                 }
1218
1219                 public override bool EnableOverloadChecks (MemberCore overload)
1220                 {
1221                         // TODO: It can be deleted when members will be defined in correct order
1222                         if (overload is Operator)
1223                                 return overload.EnableOverloadChecks (this);
1224
1225                         if (overload is Indexer)
1226                                 return false;
1227
1228                         return base.EnableOverloadChecks (overload);
1229                 }
1230
1231                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1232                 {
1233                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
1234                 }
1235
1236                 protected override bool ResolveMemberType ()
1237                 {
1238                         if (GenericMethod != null) {
1239                                 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
1240                                 if (!GenericMethod.Define (this))
1241                                         return false;
1242                         }
1243
1244                         return base.ResolveMemberType ();
1245                 }
1246
1247                 public void SetPartialDefinition (Method methodDefinition)
1248                 {
1249                         caching_flags |= Flags.PartialDefinitionExists;
1250                         methodDefinition.partialMethodImplementation = this;
1251
1252                         // Ensure we are always using method declaration parameters
1253                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1254                                 parameters [i].Name = methodDefinition.parameters [i].Name;
1255                                 parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue;
1256                         }
1257
1258                         if (methodDefinition.attributes == null)
1259                                 return;
1260
1261                         if (attributes == null) {
1262                                 attributes = methodDefinition.attributes;
1263                         } else {
1264                                 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1265                         }
1266                 }
1267         }
1268
1269         public abstract class ConstructorInitializer : ExpressionStatement
1270         {
1271                 Arguments argument_list;
1272                 MethodSpec base_ctor;
1273
1274                 public ConstructorInitializer (Arguments argument_list, Location loc)
1275                 {
1276                         this.argument_list = argument_list;
1277                         this.loc = loc;
1278                 }
1279
1280                 public Arguments Arguments {
1281                         get {
1282                                 return argument_list;
1283                         }
1284                 }
1285
1286                 public override Expression CreateExpressionTree (ResolveContext ec)
1287                 {
1288                         throw new NotSupportedException ("ET");
1289                 }
1290
1291                 protected override Expression DoResolve (ResolveContext ec)
1292                 {
1293                         eclass = ExprClass.Value;
1294
1295                         // FIXME: Hack
1296                         var caller_builder = (Constructor) ec.MemberContext;
1297
1298                         //
1299                         // Spec mandates that constructor initializer will not have `this' access
1300                         //
1301                         using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1302                                 if (argument_list != null) {
1303                                         bool dynamic;
1304                                         argument_list.Resolve (ec, out dynamic);
1305
1306                                         if (dynamic) {
1307                                                 ec.Report.Error (1975, loc,
1308                                                         "The constructor call cannot be dynamically dispatched within constructor initializer");
1309
1310                                                 return null;
1311                                         }
1312                                 }
1313
1314                                 type = ec.CurrentType;
1315                                 if (this is ConstructorBaseInitializer) {
1316                                         if (ec.CurrentType.BaseType == null)
1317                                                 return this;
1318
1319                                         type = ec.CurrentType.BaseType;
1320                                         if (ec.CurrentType.IsStruct) {
1321                                                 ec.Report.Error (522, loc,
1322                                                         "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1323                                                 return this;
1324                                         }
1325                                 } else {
1326                                         //
1327                                         // It is legal to have "this" initializers that take no arguments
1328                                         // in structs, they are just no-ops.
1329                                         //
1330                                         // struct D { public D (int a) : this () {}
1331                                         //
1332                                         if (ec.CurrentType.IsStruct && argument_list == null)
1333                                                 return this;
1334                                 }
1335
1336                                 base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
1337                         }
1338         
1339                         // TODO MemberCache: Does it work for inflated types ?
1340                         if (base_ctor == caller_builder.Spec){
1341                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1342                                         caller_builder.GetSignatureForError ());
1343                         }
1344                                                 
1345                         return this;
1346                 }
1347
1348                 public override void Emit (EmitContext ec)
1349                 {
1350                         // It can be null for static initializers
1351                         if (base_ctor == null)
1352                                 return;
1353                         
1354                         ec.Mark (loc);
1355
1356                         Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc);
1357                 }
1358
1359                 public override void EmitStatement (EmitContext ec)
1360                 {
1361                         Emit (ec);
1362                 }
1363         }
1364
1365         public class ConstructorBaseInitializer : ConstructorInitializer {
1366                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1367                         base (argument_list, l)
1368                 {
1369                 }
1370         }
1371
1372         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1373                 public GeneratedBaseInitializer (Location loc):
1374                         base (null, loc)
1375                 {
1376                 }
1377         }
1378
1379         public class ConstructorThisInitializer : ConstructorInitializer {
1380                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1381                         base (argument_list, l)
1382                 {
1383                 }
1384         }
1385         
1386         public class Constructor : MethodCore, IMethodData {
1387                 public ConstructorBuilder ConstructorBuilder;
1388                 public ConstructorInitializer Initializer;
1389                 SecurityType declarative_security;
1390                 bool has_compliant_args;
1391
1392                 // <summary>
1393                 //   Modifiers allowed for a constructor.
1394                 // </summary>
1395                 public const Modifiers AllowedModifiers =
1396                         Modifiers.PUBLIC |
1397                         Modifiers.PROTECTED |
1398                         Modifiers.INTERNAL |
1399                         Modifiers.STATIC |
1400                         Modifiers.UNSAFE |
1401                         Modifiers.EXTERN |              
1402                         Modifiers.PRIVATE;
1403
1404                 static readonly string[] attribute_targets = new string [] { "method" };
1405
1406                 public static readonly string ConstructorName = ".ctor";
1407                 public static readonly string TypeConstructorName = ".cctor";
1408
1409                 //
1410                 // The spec claims that static is not permitted, but
1411                 // my very own code has static constructors.
1412                 //
1413                 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1414                                     ConstructorInitializer init, Location loc)
1415                         : base (parent, null, null, mod, AllowedModifiers,
1416                                 new MemberName (name, loc), attrs, args)
1417                 {
1418                         Initializer = init;
1419                 }
1420
1421                 public bool HasCompliantArgs {
1422                         get { return has_compliant_args; }
1423                 }
1424
1425                 public override AttributeTargets AttributeTargets {
1426                         get { return AttributeTargets.Constructor; }
1427                 }
1428
1429                 //
1430                 // Returns true if this is a default constructor
1431                 //
1432                 public bool IsDefault ()
1433                 {
1434                         if ((ModFlags & Modifiers.STATIC) != 0)
1435                                 return parameters.IsEmpty;
1436
1437                         return parameters.IsEmpty &&
1438                                         (Initializer is ConstructorBaseInitializer) &&
1439                                         (Initializer.Arguments == null);
1440                 }
1441
1442                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1443                 {
1444                         if (a.IsValidSecurityAttribute ()) {
1445                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
1446                                 return;
1447                         }
1448
1449                         if (a.Type == pa.MethodImpl) {
1450                                 is_external_implementation = a.IsInternalCall ();
1451                         }
1452
1453                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1454                 }
1455
1456                 protected override bool CheckBase ()
1457                 {
1458                         if ((ModFlags & Modifiers.STATIC) != 0) {
1459                                 if (!parameters.IsEmpty) {
1460                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1461                                                 GetSignatureForError ());
1462                                         return false;
1463                                 }
1464
1465                                 // the rest can be ignored
1466                                 return true;
1467                         }
1468
1469                         // Check whether arguments were correct.
1470                         if (!DefineParameters (parameters))
1471                                 return false;
1472
1473                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1474                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1475
1476                         if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
1477                                 Report.Error (568, Location, 
1478                                         "Structs cannot contain explicit parameterless constructors");
1479                                 return false;
1480                         }
1481
1482                         CheckProtectedModifier ();
1483                         
1484                         return true;
1485                 }
1486                 
1487                 //
1488                 // Creates the ConstructorBuilder
1489                 //
1490                 public override bool Define ()
1491                 {
1492                         if (ConstructorBuilder != null)
1493                                 return true;
1494
1495                         var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1496                         
1497                         if ((ModFlags & Modifiers.STATIC) != 0) {
1498                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
1499                         } else {
1500                                 ca |= ModifiersExtensions.MethodAttr (ModFlags);
1501                         }
1502
1503                         if (!CheckAbstractAndExtern (block != null))
1504                                 return false;
1505                         
1506                         // Check if arguments were correct.
1507                         if (!CheckBase ())
1508                                 return false;
1509
1510                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1511                                 ca, CallingConventions,
1512                                 parameters.GetMetaInfo ());
1513
1514                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, ConstructorBuilder, parameters, ModFlags);
1515                         
1516                         Parent.MemberCache.AddMember (spec);
1517                         
1518                         // It's here only to report an error
1519                         if (block != null && block.IsIterator) {
1520                                 member_type = Compiler.BuiltinTypes.Void;
1521                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1522                         }
1523
1524                         return true;
1525                 }
1526
1527                 //
1528                 // Emits the code
1529                 //
1530                 public override void Emit ()
1531                 {
1532                         if (Parent.PartialContainer.IsComImport) {
1533                                 if (!IsDefault ()) {
1534                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1535                                                 Parent.GetSignatureForError ());
1536                                 }
1537
1538                                 // Set as internal implementation and reset block data
1539                                 // to ensure no IL is generated
1540                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1541                                 block = null;
1542                         }
1543
1544                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1545                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1546
1547                         if (OptAttributes != null)
1548                                 OptAttributes.Emit ();
1549
1550                         base.Emit ();
1551
1552                         //
1553                         // If we use a "this (...)" constructor initializer, then
1554                         // do not emit field initializers, they are initialized in the other constructor
1555                         //
1556                         bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1557                                 !(Initializer is ConstructorThisInitializer);
1558
1559                         BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void);
1560                         bc.Set (ResolveContext.Options.ConstructorScope);
1561
1562                         if (emit_field_initializers)
1563                                 Parent.PartialContainer.ResolveFieldInitializers (bc);
1564
1565                         if (block != null) {
1566                                 // If this is a non-static `struct' constructor and doesn't have any
1567                                 // initializer, it must initialize all of the struct's fields.
1568                                 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1569                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1570                                         block.AddThisVariable (bc, Parent, Location);
1571
1572                                 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1573                                         if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1574                                                 Initializer = new GeneratedBaseInitializer (Location);
1575
1576                                         if (Initializer != null) {
1577                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1578                                         }
1579                                 }
1580                         }
1581
1582                         parameters.ApplyAttributes (this, ConstructorBuilder);
1583
1584                         SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1585
1586                         if (block != null) {
1587                                 if (block.Resolve (null, bc, this)) {
1588                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1589                                         ec.With (EmitContext.Options.ConstructorScope, true);
1590
1591                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1592                                                 ec.ReturnLabel = bc.ReturnLabel;
1593                                                 ec.HasReturnLabel = true;
1594                                         }
1595
1596                                         block.Emit (ec);
1597                                 }
1598                         }
1599
1600                         if (source != null)
1601                                 source.CloseMethod ();
1602
1603                         if (declarative_security != null) {
1604                                 foreach (var de in declarative_security) {
1605 #if STATIC
1606                                         ConstructorBuilder.__AddDeclarativeSecurity (de);
1607 #else
1608                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1609 #endif
1610                                 }
1611                         }
1612
1613                         block = null;
1614                 }
1615
1616                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
1617                 {
1618                         // Is never override
1619                         bestCandidate = null;
1620                         return null;
1621                 }
1622
1623                 public override string GetSignatureForError()
1624                 {
1625                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1626                 }
1627
1628                 public override string[] ValidAttributeTargets {
1629                         get {
1630                                 return attribute_targets;
1631                         }
1632                 }
1633
1634                 protected override bool VerifyClsCompliance ()
1635                 {
1636                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1637                                 return false;
1638                         }
1639
1640                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1641                                 foreach (TypeSpec param in parameters.Types) {
1642                                         if (param.IsArray) {
1643                                                 return true;
1644                                         }
1645                                 }
1646                         }
1647
1648                         has_compliant_args = true;
1649                         return true;
1650                 }
1651
1652                 #region IMethodData Members
1653
1654                 public MemberName MethodName {
1655                         get {
1656                                 return MemberName;
1657                         }
1658                 }
1659
1660                 public TypeSpec ReturnType {
1661                         get {
1662                                 return MemberType;
1663                         }
1664                 }
1665
1666                 public EmitContext CreateEmitContext (ILGenerator ig)
1667                 {
1668                         throw new NotImplementedException ();
1669                 }
1670
1671                 public bool IsExcluded()
1672                 {
1673                         return false;
1674                 }
1675
1676                 GenericMethod IMethodData.GenericMethod {
1677                         get {
1678                                 return null;
1679                         }
1680                 }
1681
1682                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1683                 { }
1684
1685                 #endregion
1686         }
1687
1688         /// <summary>
1689         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1690         /// </summary>
1691         public interface IMethodData : IMemberContext
1692         {
1693                 CallingConventions CallingConventions { get; }
1694                 Location Location { get; }
1695                 MemberName MethodName { get; }
1696                 TypeSpec ReturnType { get; }
1697                 GenericMethod GenericMethod { get; }
1698                 ParametersCompiled ParameterInfo { get; }
1699                 MethodSpec Spec { get; }
1700
1701                 Attributes OptAttributes { get; }
1702                 ToplevelBlock Block { get; set; }
1703
1704                 EmitContext CreateEmitContext (ILGenerator ig);
1705                 void EmitExtraSymbolInfo (SourceMethod source);
1706         }
1707
1708         //
1709         // Encapsulates most of the Method's state
1710         //
1711         public class MethodData
1712         {
1713 #if !STATIC
1714                 static FieldInfo methodbuilder_attrs_field;
1715 #endif
1716
1717                 public readonly IMethodData method;
1718
1719                 public readonly GenericMethod GenericMethod;
1720
1721                 //
1722                 // Are we implementing an interface ?
1723                 //
1724                 public MethodSpec implementing;
1725
1726                 //
1727                 // Protected data.
1728                 //
1729                 protected InterfaceMemberBase member;
1730                 protected Modifiers modifiers;
1731                 protected MethodAttributes flags;
1732                 protected TypeSpec declaring_type;
1733                 protected MethodSpec parent_method;
1734
1735                 MethodBuilder builder;
1736                 public MethodBuilder MethodBuilder {
1737                         get {
1738                                 return builder;
1739                         }
1740                 }
1741
1742                 public TypeSpec DeclaringType {
1743                         get {
1744                                 return declaring_type;
1745                         }
1746                 }
1747
1748                 public MethodData (InterfaceMemberBase member,
1749                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1750                 {
1751                         this.member = member;
1752                         this.modifiers = modifiers;
1753                         this.flags = flags;
1754
1755                         this.method = method;
1756                 }
1757
1758                 public MethodData (InterfaceMemberBase member,
1759                                    Modifiers modifiers, MethodAttributes flags, 
1760                                    IMethodData method, MethodBuilder builder,
1761                                    GenericMethod generic, MethodSpec parent_method)
1762                         : this (member, modifiers, flags, method)
1763                 {
1764                         this.builder = builder;
1765                         this.GenericMethod = generic;
1766                         this.parent_method = parent_method;
1767                 }
1768
1769                 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1770                 {
1771                         TypeContainer container = parent.PartialContainer;
1772
1773                         PendingImplementation pending = container.PendingImplementations;
1774                         if (pending != null){
1775                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this);
1776
1777                                 if (member.InterfaceType != null){
1778                                         if (implementing == null){
1779                                                 if (member is PropertyBase) {
1780                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1781                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1782                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1783
1784                                                 } else {
1785                                                         Report.Error (539, method.Location,
1786                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
1787                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1788                                                 }
1789                                                 return false;
1790                                         }
1791                                         if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) {
1792                                                 Report.SymbolRelatedToPreviousError (implementing);
1793                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1794                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1795                                                 return false;
1796                                         }
1797                                 } else {
1798                                         if (implementing != null) {
1799                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1800                                                 if (prop_method == null) {
1801                                                         if (implementing.IsAccessor) {
1802                                                                 Report.SymbolRelatedToPreviousError (implementing);
1803                                                                 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'",
1804                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1805                                                         }
1806                                                 } else if (implementing.DeclaringType.IsInterface) {
1807                                                         if (!implementing.IsAccessor) {
1808                                                                 Report.SymbolRelatedToPreviousError (implementing);
1809                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1810                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1811                                                         } else {
1812                                                                 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1813                                                                 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1814                                                                         Report.SymbolRelatedToPreviousError (implementing);
1815                                                                         Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1816                                                                                 method.GetSignatureForError (), implementing.GetSignatureForError ());
1817                                                                 }
1818                                                         }
1819                                                 }
1820                                         }
1821                                 }
1822                         }
1823
1824                         //
1825                         // For implicit implementations, make sure we are public, for
1826                         // explicit implementations, make sure we are private.
1827                         //
1828                         if (implementing != null){
1829                                 //
1830                                 // Setting null inside this block will trigger a more
1831                                 // verbose error reporting for missing interface implementations
1832                                 //
1833                                 // The "candidate" function has been flagged already
1834                                 // but it wont get cleared
1835                                 //
1836                                 if (member.IsExplicitImpl){
1837                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
1838                                                 Report.SymbolRelatedToPreviousError (implementing);
1839                                                 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1840                                                         method.GetSignatureForError ());
1841                                         }
1842                                 } else {
1843                                         if (implementing.DeclaringType.IsInterface) {
1844                                                 //
1845                                                 // If this is an interface method implementation,
1846                                                 // check for public accessibility
1847                                                 //
1848                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1849                                                 {
1850                                                         implementing = null;
1851                                                 }
1852                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1853                                                 // We may never be private.
1854                                                 implementing = null;
1855
1856                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1857                                                 //
1858                                                 // We may be protected if we're overriding something.
1859                                                 //
1860                                                 implementing = null;
1861                                         }
1862                                 }
1863                                         
1864                                 //
1865                                 // Static is not allowed
1866                                 //
1867                                 if ((modifiers & Modifiers.STATIC) != 0){
1868                                         implementing = null;
1869                                 }
1870                         }
1871                         
1872                         //
1873                         // If implementing is still valid, set flags
1874                         //
1875                         if (implementing != null){
1876                                 //
1877                                 // When implementing interface methods, set NewSlot
1878                                 // unless, we are overwriting a method.
1879                                 //
1880                                 if (implementing.DeclaringType.IsInterface){
1881                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
1882                                                 flags |= MethodAttributes.NewSlot;
1883                                 }
1884
1885                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
1886
1887                                 // Set Final unless we're virtual, abstract or already overriding a method.
1888                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1889                                         flags |= MethodAttributes.Final;
1890
1891                                 //
1892                                 // clear the pending implementation flag (requires explicit methods to be defined first)
1893                                 //
1894                                 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName,
1895                                         member.InterfaceType, this, member.IsExplicitImpl);
1896
1897                                 //
1898                                 // Update indexer accessor name to match implementing abstract accessor
1899                                 //
1900                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
1901                                         method_full_name = implementing.MemberDefinition.Name;
1902                         }
1903
1904                         DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1905
1906                         if (builder == null)
1907                                 return false;
1908
1909 //                      if (container.CurrentType != null)
1910 //                              declaring_type = container.CurrentType;
1911 //                      else
1912                                 declaring_type = container.Definition;
1913
1914                         if (implementing != null && member.IsExplicitImpl) {
1915                                 container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
1916                         }
1917
1918                         return true;
1919                 }
1920
1921
1922                 /// <summary>
1923                 /// Create the MethodBuilder for the method 
1924                 /// </summary>
1925                 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1926                 {
1927                         var return_type = method.ReturnType.GetMetaInfo ();
1928                         var p_types = param.GetMetaInfo ();
1929
1930                         if (builder == null) {
1931                                 builder = container.TypeBuilder.DefineMethod (
1932                                         method_name, flags, method.CallingConventions,
1933                                         return_type, p_types);
1934                                 return;
1935                         }
1936
1937                         //
1938                         // Generic method has been already defined to resolve method parameters
1939                         // correctly when they use type parameters
1940                         //
1941                         builder.SetParameters (p_types);
1942                         builder.SetReturnType (return_type);
1943                         if (builder.Attributes != flags) {
1944 #if STATIC
1945                                 builder.__SetAttributes (flags);
1946 #else
1947                                 try {
1948                                         if (methodbuilder_attrs_field == null)
1949                                                 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1950                                         methodbuilder_attrs_field.SetValue (builder, flags);
1951                                 } catch {
1952                                         container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1953                                 }
1954 #endif
1955                         }
1956                 }
1957
1958                 //
1959                 // Emits the code
1960                 // 
1961                 public void Emit (DeclSpace parent)
1962                 {
1963                         if (GenericMethod != null)
1964                                 GenericMethod.EmitAttributes ();
1965
1966                         var mc = (IMemberContext) method;
1967
1968                         method.ParameterInfo.ApplyAttributes (mc, MethodBuilder);
1969
1970                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1971
1972                         ToplevelBlock block = method.Block;
1973                         if (block != null) {
1974                                 BlockContext bc = new BlockContext (mc, block, method.ReturnType);
1975                                 if (block.Resolve (null, bc, method)) {
1976                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1977                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1978                                                 ec.ReturnLabel = bc.ReturnLabel;
1979                                                 ec.HasReturnLabel = true;
1980                                         }
1981
1982                                         block.Emit (ec);
1983                                 }
1984                         }
1985
1986                         if (source != null) {
1987                                 method.EmitExtraSymbolInfo (source);
1988                                 source.CloseMethod ();
1989                         }
1990                 }
1991         }
1992
1993         public class Destructor : MethodOrOperator
1994         {
1995                 const Modifiers AllowedModifiers =
1996                         Modifiers.UNSAFE |
1997                         Modifiers.EXTERN;
1998
1999                 static readonly string[] attribute_targets = new string [] { "method" };
2000
2001                 public static readonly string MetadataName = "Finalize";
2002
2003                 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
2004                         : base (parent, null, null, mod, AllowedModifiers,
2005                                 new MemberName (MetadataName, l), attrs, parameters)
2006                 {
2007                         ModFlags &= ~Modifiers.PRIVATE;
2008                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
2009                 }
2010
2011                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2012                 {
2013                         if (a.Type == pa.Conditional) {
2014                                 Error_ConditionalAttributeIsNotValid ();
2015                                 return;
2016                         }
2017
2018                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2019                 }
2020
2021                 protected override bool CheckBase ()
2022                 {
2023                         // Don't check base, destructors have special syntax
2024                         return true;
2025                 }
2026
2027                 public override void Emit()
2028                 {
2029                         var base_type = Parent.PartialContainer.BaseType;
2030                         if (base_type != null && Block != null) {
2031                                 var base_dtor = MemberCache.FindMember (base_type,
2032                                         new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
2033
2034                                 if (base_dtor == null)
2035                                         throw new NotImplementedException ();
2036
2037                                 MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
2038                                 method_expr.InstanceExpression = new BaseThis (base_type, Location);
2039
2040                                 var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation);
2041                                 var finaly_block = new ExplicitBlock (block, Location, Location);
2042
2043                                 //
2044                                 // 0-size arguments to avoid CS0250 error
2045                                 // TODO: Should use AddScopeStatement or something else which emits correct
2046                                 // debugger scope
2047                                 //
2048                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
2049
2050                                 var tf = new TryFinally (try_block, finaly_block, Location);
2051                                 block.WrapIntoDestructor (tf, try_block);
2052                         }
2053
2054                         base.Emit ();
2055                 }
2056
2057                 public override string GetSignatureForError ()
2058                 {
2059                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
2060                 }
2061
2062                 protected override bool ResolveMemberType ()
2063                 {
2064                         member_type = Compiler.BuiltinTypes.Void;
2065                         return true;
2066                 }
2067
2068                 public override string[] ValidAttributeTargets {
2069                         get {
2070                                 return attribute_targets;
2071                         }
2072                 }
2073         }
2074
2075         // Ooouh Martin, templates are missing here.
2076         // When it will be possible move here a lot of child code and template method type.
2077         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
2078                 protected MethodData method_data;
2079                 protected ToplevelBlock block;
2080                 protected SecurityType declarative_security;
2081
2082                 protected readonly string prefix;
2083
2084                 ReturnParameter return_attributes;
2085
2086                 public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2087                         : base (member.Parent, SetupName (prefix, member, loc), attrs)
2088                 {
2089                         this.prefix = prefix;
2090                 }
2091
2092                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2093                 {
2094                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
2095                 }
2096
2097                 public void UpdateName (InterfaceMemberBase member)
2098                 {
2099                         SetMemberName (SetupName (prefix, member, Location));
2100                 }
2101
2102                 #region IMethodData Members
2103
2104                 public ToplevelBlock Block {
2105                         get {
2106                                 return block;
2107                         }
2108
2109                         set {
2110                                 block = value;
2111                         }
2112                 }
2113
2114                 public CallingConventions CallingConventions {
2115                         get {
2116                                 return CallingConventions.Standard;
2117                         }
2118                 }
2119
2120                 public EmitContext CreateEmitContext (ILGenerator ig)
2121                 {
2122                         return new EmitContext (this, ig, ReturnType);
2123                 }
2124
2125                 public bool IsExcluded ()
2126                 {
2127                         return false;
2128                 }
2129
2130                 GenericMethod IMethodData.GenericMethod {
2131                         get {
2132                                 return null;
2133                         }
2134                 }
2135
2136                 public MemberName MethodName {
2137                         get {
2138                                 return MemberName;
2139                         }
2140                 }
2141
2142                 public TypeSpec[] ParameterTypes { 
2143                         get {
2144                                 return ParameterInfo.Types;
2145                         }
2146                 }
2147
2148                 public abstract ParametersCompiled ParameterInfo { get ; }
2149                 public abstract TypeSpec ReturnType { get; }
2150
2151                 #endregion
2152
2153                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2154                 {
2155                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2156                                 Report.Error (1667, a.Location,
2157                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2158                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
2159                                 return;
2160                         }
2161
2162                         if (a.IsValidSecurityAttribute ()) {
2163                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2164                                 return;
2165                         }
2166
2167                         if (a.Target == AttributeTargets.Method) {
2168                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2169                                 return;
2170                         }
2171
2172                         if (a.Target == AttributeTargets.ReturnValue) {
2173                                 if (return_attributes == null)
2174                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2175
2176                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2177                                 return;
2178                         }
2179
2180                         ApplyToExtraTarget (a, ctor, cdata, pa);
2181                 }
2182
2183                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2184                 {
2185                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2186                 }
2187
2188                 // It is not supported for the accessors
2189                 public sealed override bool Define()
2190                 {
2191                         throw new NotSupportedException ();
2192                 }
2193
2194                 public virtual void Emit (DeclSpace parent)
2195                 {
2196                         method_data.Emit (parent);
2197
2198                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2199                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2200                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2201                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2202
2203                         if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2204                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2205                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
2206                         } else if (ReturnType.HasDynamicElement) {
2207                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2208                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
2209                         }
2210
2211                         if (OptAttributes != null)
2212                                 OptAttributes.Emit ();
2213
2214                         if (declarative_security != null) {
2215                                 foreach (var de in declarative_security) {
2216 #if STATIC
2217                                         method_data.MethodBuilder.__AddDeclarativeSecurity (de);
2218 #else
2219                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2220 #endif
2221                                 }
2222                         }
2223
2224                         block = null;
2225                 }
2226
2227                 public override bool EnableOverloadChecks (MemberCore overload)
2228                 {
2229                         if (overload is MethodCore) {
2230                                 caching_flags |= Flags.MethodOverloadsExist;
2231                                 return true;
2232                         }
2233
2234                         // This can only happen with indexers and it will
2235                         // be catched as indexer difference
2236                         if (overload is AbstractPropertyEventMethod)
2237                                 return true;
2238
2239                         return false;
2240                 }
2241
2242                 public override bool IsClsComplianceRequired()
2243                 {
2244                         return false;
2245                 }
2246
2247                 public MethodSpec Spec { get; protected set; }
2248
2249                 //
2250                 //   Represents header string for documentation comment.
2251                 //
2252                 public override string DocCommentHeader {
2253                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2254                 }
2255
2256                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2257                 { }
2258         }
2259
2260         public class Operator : MethodOrOperator {
2261
2262                 const Modifiers AllowedModifiers =
2263                         Modifiers.PUBLIC |
2264                         Modifiers.UNSAFE |
2265                         Modifiers.EXTERN |
2266                         Modifiers.STATIC;
2267
2268                 public enum OpType : byte {
2269
2270                         // Unary operators
2271                         LogicalNot,
2272                         OnesComplement,
2273                         Increment,
2274                         Decrement,
2275                         True,
2276                         False,
2277
2278                         // Unary and Binary operators
2279                         Addition,
2280                         Subtraction,
2281
2282                         UnaryPlus,
2283                         UnaryNegation,
2284                         
2285                         // Binary operators
2286                         Multiply,
2287                         Division,
2288                         Modulus,
2289                         BitwiseAnd,
2290                         BitwiseOr,
2291                         ExclusiveOr,
2292                         LeftShift,
2293                         RightShift,
2294                         Equality,
2295                         Inequality,
2296                         GreaterThan,
2297                         LessThan,
2298                         GreaterThanOrEqual,
2299                         LessThanOrEqual,
2300
2301                         // Implicit and Explicit
2302                         Implicit,
2303                         Explicit,
2304
2305                         // Just because of enum
2306                         TOP
2307                 };
2308
2309                 public readonly OpType OperatorType;
2310
2311                 static readonly string [] [] names;
2312
2313                 static Operator ()
2314                 {
2315                         names = new string[(int)OpType.TOP][];
2316                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2317                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2318                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2319                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2320                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2321                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2322                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2323                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2324                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2325                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2326                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2327                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2328                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2329                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2330                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2331                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2332                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2333                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2334                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2335                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2336                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2337                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2338                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2339                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2340                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2341                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2342                 }
2343                 
2344                 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2345                                  Modifiers mod_flags, ParametersCompiled parameters,
2346                                  ToplevelBlock block, Attributes attrs, Location loc)
2347                         : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2348                                 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2349                 {
2350                         OperatorType = type;
2351                         Block = block;
2352                 }
2353
2354                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2355                 {
2356                         if (a.Type == pa.Conditional) {
2357                                 Error_ConditionalAttributeIsNotValid ();
2358                                 return;
2359                         }
2360
2361                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2362                 }
2363                 
2364                 public override bool Define ()
2365                 {
2366                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2367                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2368                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2369                         }
2370
2371                         if (!base.Define ())
2372                                 return false;
2373
2374                         if (block != null && block.IsIterator) {
2375                                 //
2376                                 // Current method is turned into automatically generated
2377                                 // wrapper which creates an instance of iterator
2378                                 //
2379                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
2380                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2381                         }
2382
2383                         // imlicit and explicit operator of same types are not allowed
2384                         if (OperatorType == OpType.Explicit)
2385                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2386                         else if (OperatorType == OpType.Implicit)
2387                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2388
2389                         TypeSpec declaring_type = Parent.CurrentType;
2390                         TypeSpec return_type = MemberType;
2391                         TypeSpec first_arg_type = ParameterTypes [0];
2392                         
2393                         TypeSpec first_arg_type_unwrap = first_arg_type;
2394                         if (first_arg_type.IsNullableType)
2395                                 first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type);
2396                         
2397                         TypeSpec return_type_unwrap = return_type;
2398                         if (return_type.IsNullableType)
2399                                 return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type);
2400
2401                         //
2402                         // Rules for conversion operators
2403                         //
2404                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2405                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2406                                         Report.Error (555, Location,
2407                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2408                                         return false;
2409                                 }
2410
2411                                 TypeSpec conv_type;
2412                                 if (declaring_type == return_type || declaring_type == return_type_unwrap) {
2413                                         conv_type = first_arg_type;
2414                                 } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
2415                                         conv_type = return_type;
2416                                 } else {
2417                                         Report.Error (556, Location,
2418                                                 "User-defined conversion must convert to or from the enclosing type");
2419                                         return false;
2420                                 }
2421
2422                                 if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2423                                         Report.Error (1964, Location,
2424                                                 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2425                                                 GetSignatureForError ());
2426
2427                                         return false;
2428                                 }
2429
2430                                 if (conv_type.IsInterface) {
2431                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2432                                                 GetSignatureForError ());
2433                                         return false;
2434                                 }
2435
2436                                 if (conv_type.IsClass) {
2437                                         if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
2438                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2439                                                         GetSignatureForError ());
2440                                                 return false;
2441                                         }
2442
2443                                         if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
2444                                                 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2445                                                         GetSignatureForError ());
2446                                                 return false;
2447                                         }
2448                                 }
2449                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2450                                 if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) {
2451                                         Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
2452                                         return false;
2453                                 }
2454                         } else if (parameters.Count == 1) {
2455                                 // Checks for Unary operators
2456
2457                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2458                                         if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
2459                                                 Report.Error (448, Location,
2460                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2461                                                 return false;
2462                                         }
2463                                         if (first_arg_type != declaring_type) {
2464                                                 Report.Error (
2465                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2466                                                 return false;
2467                                         }
2468                                 }
2469
2470                                 if (first_arg_type_unwrap != declaring_type) {
2471                                         Report.Error (562, Location,
2472                                                 "The parameter type of a unary operator must be the containing type");
2473                                         return false;
2474                                 }
2475
2476                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2477                                         if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) {
2478                                                 Report.Error (
2479                                                         215, Location,
2480                                                         "The return type of operator True or False " +
2481                                                         "must be bool");
2482                                                 return false;
2483                                         }
2484                                 }
2485
2486                         } else if (first_arg_type_unwrap != declaring_type) {
2487                                 // Checks for Binary operators
2488
2489                                 var second_arg_type = ParameterTypes[1];
2490                                 if (second_arg_type.IsNullableType)
2491                                         second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type);
2492
2493                                 if (second_arg_type != declaring_type) {
2494                                         Report.Error (563, Location,
2495                                                 "One of the parameters of a binary operator must be the containing type");
2496                                         return false;
2497                                 }
2498                         }
2499
2500                         return true;
2501                 }
2502
2503                 protected override bool ResolveMemberType ()
2504                 {
2505                         if (!base.ResolveMemberType ())
2506                                 return false;
2507
2508                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2509                         return true;
2510                 }
2511
2512                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
2513                 {
2514                         // Operator cannot be override
2515                         bestCandidate = null;
2516                         return null;
2517                 }
2518
2519                 public static string GetName (OpType ot)
2520                 {
2521                         return names [(int) ot] [0];
2522                 }
2523
2524                 public static string GetName (string metadata_name)
2525                 {
2526                         for (int i = 0; i < names.Length; ++i) {
2527                                 if (names [i] [1] == metadata_name)
2528                                         return names [i] [0];
2529                         }
2530                         return null;
2531                 }
2532
2533                 public static string GetMetadataName (OpType ot)
2534                 {
2535                         return names [(int) ot] [1];
2536                 }
2537
2538                 public static string GetMetadataName (string name)
2539                 {
2540                         for (int i = 0; i < names.Length; ++i) {
2541                                 if (names [i] [0] == name)
2542                                         return names [i] [1];
2543                         }
2544                         return null;
2545                 }
2546
2547                 public static OpType? GetType (string metadata_name)
2548                 {
2549                         for (int i = 0; i < names.Length; ++i) {
2550                                 if (names[i][1] == metadata_name)
2551                                         return (OpType) i;
2552                         }
2553
2554                         return null;
2555                 }
2556
2557                 public OpType GetMatchingOperator ()
2558                 {
2559                         switch (OperatorType) {
2560                         case OpType.Equality:
2561                                 return OpType.Inequality;
2562                         case OpType.Inequality:
2563                                 return OpType.Equality;
2564                         case OpType.True:
2565                                 return OpType.False;
2566                         case OpType.False:
2567                                 return OpType.True;
2568                         case OpType.GreaterThan:
2569                                 return OpType.LessThan;
2570                         case OpType.LessThan:
2571                                 return OpType.GreaterThan;
2572                         case OpType.GreaterThanOrEqual:
2573                                 return OpType.LessThanOrEqual;
2574                         case OpType.LessThanOrEqual:
2575                                 return OpType.GreaterThanOrEqual;
2576                         default:
2577                                 return OpType.TOP;
2578                         }
2579                 }
2580
2581                 public override string GetSignatureForError ()
2582                 {
2583                         StringBuilder sb = new StringBuilder ();
2584                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2585                                 sb.AppendFormat ("{0}.{1} operator {2}",
2586                                         Parent.GetSignatureForError (), GetName (OperatorType), type_expr.GetSignatureForError ());
2587                         }
2588                         else {
2589                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2590                         }
2591
2592                         sb.Append (parameters.GetSignatureForError ());
2593                         return sb.ToString ();
2594                 }
2595         }
2596 }
2597