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