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