2c0658f41b52a0d3e6f41ae4e48d7c5dedfe2228
[mono.git] / 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                         TypeParameterSpec[] base_decl_tparams = TypeParameterSpec.EmptyTypes;
936                         TypeSpec[] base_targs = TypeSpec.EmptyTypes;
937                         if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
938                                 if (base_method != null) {
939                                         base_tparams = base_method.GenericDefinition.TypeParameters;
940                                         if (base_method.DeclaringType.IsGeneric) {
941                                                 base_decl_tparams = base_method.DeclaringType.MemberDefinition.TypeParameters;
942                                                 base_targs = Parent.BaseType.TypeArguments;
943                                         }
944                                 } else if (MethodData.implementing != null) {
945                                         base_tparams = MethodData.implementing.GenericDefinition.TypeParameters;
946                                         if (MethodData.implementing.DeclaringType.IsGeneric) {
947                                                 base_decl_tparams = MethodData.implementing.DeclaringType.MemberDefinition.TypeParameters;
948                                                 foreach (var iface in Parent.CurrentType.Interfaces) {
949                                                         if (iface == MethodData.implementing.DeclaringType) {
950                                                                 base_targs = iface.TypeArguments;
951                                                                 break;
952                                                         }
953                                                 }
954                                         }
955                                 }
956                         }
957
958                         for (int i = 0; i < tparams.Length; ++i) {
959                                 var tp = tparams[i];
960
961                                 if (!tp.ResolveConstraints (this))
962                                         continue;
963
964                                 //
965                                 // Copy base constraints for override/explicit methods
966                                 //
967                                 if (base_tparams != null) {
968                                         var base_tparam = base_tparams[i];
969                                         tp.Type.SpecialConstraint = base_tparam.SpecialConstraint;
970
971                                         var inflator = new TypeParameterInflator (CurrentType, base_decl_tparams, base_targs);
972                                         base_tparam.InflateConstraints (inflator, tp.Type);
973                                 } else if (MethodData.implementing != null) {
974                                         var base_tp = MethodData.implementing.Constraints[i];
975                                         if (!tp.Type.HasSameConstraintsImplementation (base_tp)) {
976                                                 Report.SymbolRelatedToPreviousError (MethodData.implementing);
977                                                 Report.Error (425, Location,
978                                                         "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",
979                                                         tp.GetSignatureForError (), GetSignatureForError (), base_tp.GetSignatureForError (), MethodData.implementing.GetSignatureForError ());
980                                         }
981                                 }
982                         }
983                 }
984
985                 //
986                 // Creates the type
987                 //
988                 public override bool Define ()
989                 {
990                         if (type_expr.Type == TypeManager.void_type && parameters.IsEmpty && MemberName.Arity == 0 && MemberName.Name == Destructor.MetadataName) {
991                                 Report.Warning (465, 1, Location, "Introducing `Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
992                         }
993
994                         if (!base.Define ())
995                                 return false;
996
997                         if (partialMethodImplementation != null && IsPartialDefinition)
998                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
999
1000                         if (RootContext.StdLib && TypeManager.IsSpecialType (ReturnType)) {
1001                                 Error1599 (Location, ReturnType, Report);
1002                                 return false;
1003                         }
1004
1005                         if (CurrentTypeParameters == null) {
1006                                 if (base_method != null) {
1007                                         if (parameters.Count == 1 && ParameterTypes[0] == TypeManager.object_type && Name == "Equals")
1008                                                 Parent.PartialContainer.Mark_HasEquals ();
1009                                         else if (parameters.IsEmpty && Name == "GetHashCode")
1010                                                 Parent.PartialContainer.Mark_HasGetHashCode ();
1011                                 }
1012                                         
1013                         } else {
1014                                 DefineTypeParameters ();
1015                         }
1016
1017                         if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
1018                                 //
1019                                 // Current method is turned into automatically generated
1020                                 // wrapper which creates an instance of iterator
1021                                 //
1022                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1023                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
1024                         }
1025
1026                         if ((ModFlags & Modifiers.STATIC) == 0)
1027                                 return true;
1028
1029                         if (parameters.HasExtensionMethodType) {
1030                                 if (Parent.PartialContainer.IsStatic && !Parent.IsGeneric) {
1031                                         if (!Parent.IsTopLevel)
1032                                                 Report.Error (1109, Location, "`{0}': Extension methods cannot be defined in a nested class",
1033                                                         GetSignatureForError ());
1034
1035                                         PredefinedAttribute pa = PredefinedAttributes.Get.Extension;
1036                                         if (!pa.IsDefined) {
1037                                                 Report.Error (1110, Location,
1038                                                         "`{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",
1039                                                         GetSignatureForError ());
1040                                         }
1041
1042                                         ModFlags |= Modifiers.METHOD_EXTENSION;
1043                                         Parent.PartialContainer.ModFlags |= Modifiers.METHOD_EXTENSION;
1044                                         Spec.DeclaringType.SetExtensionMethodContainer ();
1045                                         CodeGen.Assembly.HasExtensionMethods = true;
1046                                 } else {
1047                                         Report.Error (1106, Location, "`{0}': Extension methods must be defined in a non-generic static class",
1048                                                 GetSignatureForError ());
1049                                 }
1050                         }
1051
1052                         //
1053                         // This is used to track the Entry Point,
1054                         //
1055                         if (RootContext.NeedsEntryPoint &&
1056                                 Name == "Main" &&
1057                                 (RootContext.MainClass == null ||
1058                                 RootContext.MainClass == Parent.TypeBuilder.FullName)){
1059                                 if (IsEntryPoint ()) {
1060
1061                                         if (RootContext.EntryPoint == null) {
1062                                                 if (Parent.IsGeneric || MemberName.IsGeneric) {
1063                                                         Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1064                                                                 GetSignatureForError ());
1065                                                 } else {
1066                                                         SetIsUsed ();
1067                                                         RootContext.EntryPoint = this;
1068                                                 }
1069                                         } else {
1070                                                 Error_DuplicateEntryPoint (RootContext.EntryPoint);
1071                                                 Error_DuplicateEntryPoint (this);
1072                                         }
1073                                 } else {
1074                                         Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1075                                                 GetSignatureForError ());
1076                                 }
1077                         }
1078
1079                         return true;
1080                 }
1081
1082                 //
1083                 // Emits the code
1084                 // 
1085                 public override void Emit ()
1086                 {
1087                         try {
1088                                 Report.Debug (64, "METHOD EMIT", this, MethodBuilder, Location, Block, MethodData);
1089                                 if (IsPartialDefinition) {
1090                                         //
1091                                         // Use partial method implementation builder for partial method declaration attributes
1092                                         //
1093                                         if (partialMethodImplementation != null) {
1094                                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1095                                                 return;
1096                                         }
1097                                 } else if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1098                                         Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1099                                                 GetSignatureForError ());
1100                                 }
1101
1102                                 if (CurrentTypeParameters != null) {
1103                                         var ge = type_expr as GenericTypeExpr;
1104                                         if (ge != null)
1105                                                 ge.CheckConstraints (this);
1106
1107                                         foreach (Parameter p in parameters.FixedParameters) {
1108                                                 ge = p.TypeExpression as GenericTypeExpr;
1109                                                 if (ge != null)
1110                                                         ge.CheckConstraints (this);
1111                                         }
1112
1113                                         for (int i = 0; i < CurrentTypeParameters.Length; ++i) {
1114                                                 var tp = CurrentTypeParameters [i];
1115                                                 tp.CheckGenericConstraints ();
1116                                                 tp.Emit ();
1117                                         }
1118                                 }
1119
1120                                 base.Emit ();
1121                                 
1122                                 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1123                                         PredefinedAttributes.Get.Extension.EmitAttribute (MethodBuilder);
1124                         } catch {
1125                                 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
1126                                                    Location, MethodBuilder);
1127                                 throw;
1128                         }
1129                 }
1130
1131                 public override bool EnableOverloadChecks (MemberCore overload)
1132                 {
1133                         // TODO: It can be deleted when members will be defined in correct order
1134                         if (overload is Operator)
1135                                 return overload.EnableOverloadChecks (this);
1136
1137                         if (overload is Indexer)
1138                                 return false;
1139
1140                         return base.EnableOverloadChecks (overload);
1141                 }
1142
1143                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1144                 {
1145                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
1146                 }
1147
1148                 protected override bool ResolveMemberType ()
1149                 {
1150                         if (GenericMethod != null) {
1151                                 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
1152                                 if (!GenericMethod.Define (this))
1153                                         return false;
1154                         }
1155
1156                         return base.ResolveMemberType ();
1157                 }
1158
1159                 public void SetPartialDefinition (Method methodDefinition)
1160                 {
1161                         caching_flags |= Flags.PartialDefinitionExists;
1162                         methodDefinition.partialMethodImplementation = this;
1163
1164                         // Ensure we are always using method declaration parameters
1165                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1166                                 parameters [i].Name = methodDefinition.parameters [i].Name;
1167                                 parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue;
1168                         }
1169
1170                         if (methodDefinition.attributes == null)
1171                                 return;
1172
1173                         if (attributes == null) {
1174                                 attributes = methodDefinition.attributes;
1175                         } else {
1176                                 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1177                         }
1178                 }
1179         }
1180
1181         public abstract class ConstructorInitializer : ExpressionStatement
1182         {
1183                 Arguments argument_list;
1184                 MethodGroupExpr base_constructor_group;
1185
1186                 public ConstructorInitializer (Arguments argument_list, Location loc)
1187                 {
1188                         this.argument_list = argument_list;
1189                         this.loc = loc;
1190                 }
1191
1192                 public Arguments Arguments {
1193                         get {
1194                                 return argument_list;
1195                         }
1196                 }
1197
1198                 public override Expression CreateExpressionTree (ResolveContext ec)
1199                 {
1200                         throw new NotSupportedException ("ET");
1201                 }
1202
1203                 protected override Expression DoResolve (ResolveContext ec)
1204                 {
1205                         eclass = ExprClass.Value;
1206
1207                         // FIXME: Hack
1208                         var caller_builder = (Constructor) ec.MemberContext;
1209
1210                         if (argument_list != null) {
1211                                 bool dynamic;
1212
1213                                 //
1214                                 // Spec mandates that constructor initializer will not have `this' access
1215                                 //
1216                                 using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1217                                         argument_list.Resolve (ec, out dynamic);
1218                                 }
1219
1220                                 if (dynamic) {
1221                                         ec.Report.Error (1975, loc,
1222                                                 "The constructor call cannot be dynamically dispatched within constructor initializer");
1223
1224                                         return null;
1225                                 }
1226                         }
1227
1228                         type = ec.CurrentType;
1229                         if (this is ConstructorBaseInitializer) {
1230                                 if (ec.CurrentType.BaseType == null)
1231                                         return this;
1232
1233                                 type = ec.CurrentType.BaseType;
1234                                 if (ec.CurrentType.IsStruct) {
1235                                         ec.Report.Error (522, loc,
1236                                                 "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1237                                         return this;
1238                                 }
1239                         } else {
1240                                 //
1241                                 // It is legal to have "this" initializers that take no arguments
1242                                 // in structs, they are just no-ops.
1243                                 //
1244                                 // struct D { public D (int a) : this () {}
1245                                 //
1246                                 if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
1247                                         return this;                    
1248                         }
1249
1250                         base_constructor_group = MemberLookupFinal (
1251                                 ec, null, type, ConstructorBuilder.ConstructorName, 0, MemberKind.Constructor,
1252                                 BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly,
1253                                 loc) as MethodGroupExpr;
1254                         
1255                         if (base_constructor_group == null)
1256                                 return this;
1257                         
1258                         base_constructor_group = base_constructor_group.OverloadResolve (
1259                                 ec, ref argument_list, false, loc);
1260                         
1261                         if (base_constructor_group == null)
1262                                 return this;
1263
1264                         if (!ec.IsStatic)
1265                                 base_constructor_group.InstanceExpression = ec.GetThis (loc);
1266                         
1267                         var base_ctor = base_constructor_group.BestCandidate;
1268
1269                         // TODO MemberCache: Does it work for inflated types ?
1270                         if (base_ctor == caller_builder.Spec){
1271                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1272                                         caller_builder.GetSignatureForError ());
1273                         }
1274                                                 
1275                         return this;
1276                 }
1277
1278                 public override void Emit (EmitContext ec)
1279                 {
1280                         // It can be null for static initializers
1281                         if (base_constructor_group == null)
1282                                 return;
1283                         
1284                         ec.Mark (loc);
1285
1286                         base_constructor_group.EmitCall (ec, argument_list);
1287                 }
1288
1289                 public override void EmitStatement (EmitContext ec)
1290                 {
1291                         Emit (ec);
1292                 }
1293         }
1294
1295         public class ConstructorBaseInitializer : ConstructorInitializer {
1296                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1297                         base (argument_list, l)
1298                 {
1299                 }
1300         }
1301
1302         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1303                 public GeneratedBaseInitializer (Location loc):
1304                         base (null, loc)
1305                 {
1306                 }
1307         }
1308
1309         public class ConstructorThisInitializer : ConstructorInitializer {
1310                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1311                         base (argument_list, l)
1312                 {
1313                 }
1314         }
1315         
1316         public class Constructor : MethodCore, IMethodData {
1317                 public ConstructorBuilder ConstructorBuilder;
1318                 public ConstructorInitializer Initializer;
1319                 Dictionary<SecurityAction, PermissionSet> declarative_security;
1320                 bool has_compliant_args;
1321
1322                 // <summary>
1323                 //   Modifiers allowed for a constructor.
1324                 // </summary>
1325                 public const Modifiers AllowedModifiers =
1326                         Modifiers.PUBLIC |
1327                         Modifiers.PROTECTED |
1328                         Modifiers.INTERNAL |
1329                         Modifiers.STATIC |
1330                         Modifiers.UNSAFE |
1331                         Modifiers.EXTERN |              
1332                         Modifiers.PRIVATE;
1333
1334                 static readonly string[] attribute_targets = new string [] { "method" };
1335
1336                 //
1337                 // The spec claims that static is not permitted, but
1338                 // my very own code has static constructors.
1339                 //
1340                 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1341                                     ConstructorInitializer init, Location loc)
1342                         : base (parent, null, null, mod, AllowedModifiers,
1343                                 new MemberName (name, loc), attrs, args)
1344                 {
1345                         Initializer = init;
1346                 }
1347
1348                 public bool HasCompliantArgs {
1349                         get { return has_compliant_args; }
1350                 }
1351
1352                 public override AttributeTargets AttributeTargets {
1353                         get { return AttributeTargets.Constructor; }
1354                 }
1355
1356                 //
1357                 // Returns true if this is a default constructor
1358                 //
1359                 public bool IsDefault ()
1360                 {
1361                         if ((ModFlags & Modifiers.STATIC) != 0)
1362                                 return parameters.IsEmpty;
1363
1364                         return parameters.IsEmpty &&
1365                                         (Initializer is ConstructorBaseInitializer) &&
1366                                         (Initializer.Arguments == null);
1367                 }
1368
1369                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1370                 {
1371                         if (a.IsValidSecurityAttribute ()) {
1372                                 if (declarative_security == null) {
1373                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
1374                                 }
1375                                 a.ExtractSecurityPermissionSet (declarative_security);
1376                                 return;
1377                         }
1378
1379                         if (a.IsInternalMethodImplAttribute) {
1380                                 is_external_implementation = true;
1381                         }
1382
1383                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1384                 }
1385
1386                 protected override bool CheckBase ()
1387                 {
1388                         if ((ModFlags & Modifiers.STATIC) != 0) {
1389                                 if (!parameters.IsEmpty) {
1390                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1391                                                 GetSignatureForError ());
1392                                         return false;
1393                                 }
1394
1395                                 // the rest can be ignored
1396                                 return true;
1397                         }
1398
1399                         // Check whether arguments were correct.
1400                         if (!DefineParameters (parameters))
1401                                 return false;
1402
1403                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1404                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1405
1406                         if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
1407                                 Report.Error (568, Location, 
1408                                         "Structs cannot contain explicit parameterless constructors");
1409                                 return false;
1410                         }
1411
1412                         CheckProtectedModifier ();
1413                         
1414                         return true;
1415                 }
1416                 
1417                 //
1418                 // Creates the ConstructorBuilder
1419                 //
1420                 public override bool Define ()
1421                 {
1422                         if (ConstructorBuilder != null)
1423                                 return true;
1424
1425                         var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1426                         
1427                         if ((ModFlags & Modifiers.STATIC) != 0) {
1428                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
1429                         } else {
1430                                 ca |= ModifiersExtensions.MethodAttr (ModFlags);
1431                         }
1432
1433                         if (!CheckAbstractAndExtern (block != null))
1434                                 return false;
1435                         
1436                         // Check if arguments were correct.
1437                         if (!CheckBase ())
1438                                 return false;
1439
1440                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1441                                 ca, CallingConventions,
1442                                 parameters.GetMetaInfo ());
1443
1444                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, TypeManager.void_type, ConstructorBuilder, parameters, ModFlags);
1445                         
1446                         Parent.MemberCache.AddMember (spec);
1447                         
1448                         // It's here only to report an error
1449                         if (block != null && block.IsIterator) {
1450                                 member_type = TypeManager.void_type;
1451                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1452                         }
1453
1454                         return true;
1455                 }
1456
1457                 //
1458                 // Emits the code
1459                 //
1460                 public override void Emit ()
1461                 {
1462                         if (Parent.PartialContainer.IsComImport) {
1463                                 if (!IsDefault ()) {
1464                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1465                                                 Parent.GetSignatureForError ());
1466                                 }
1467                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1468                         }
1469
1470                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1471                                 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1472
1473                         if (OptAttributes != null)
1474                                 OptAttributes.Emit ();
1475
1476                         base.Emit ();
1477
1478                         //
1479                         // If we use a "this (...)" constructor initializer, then
1480                         // do not emit field initializers, they are initialized in the other constructor
1481                         //
1482                         bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1483                                 !(Initializer is ConstructorThisInitializer);
1484
1485                         BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
1486                         bc.Set (ResolveContext.Options.ConstructorScope);
1487
1488                         if (emit_field_initializers)
1489                                 Parent.PartialContainer.ResolveFieldInitializers (bc);
1490
1491                         if (block != null) {
1492                                 // If this is a non-static `struct' constructor and doesn't have any
1493                                 // initializer, it must initialize all of the struct's fields.
1494                                 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1495                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1496                                         block.AddThisVariable (Parent, Location);
1497
1498                                 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1499                                         if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1500                                                 Initializer = new GeneratedBaseInitializer (Location);
1501
1502                                         if (Initializer != null) {
1503                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1504                                         }
1505                                 }
1506                         }
1507
1508                         parameters.ApplyAttributes (ConstructorBuilder);
1509
1510                         SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1511
1512                         if (block != null) {
1513                                 if (block.Resolve (null, bc, parameters, this)) {
1514                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1515                                         ec.With (EmitContext.Options.ConstructorScope, true);
1516
1517                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1518                                                 ec.ReturnLabel = bc.ReturnLabel;
1519                                                 ec.HasReturnLabel = true;
1520                                         }
1521
1522                                         block.Emit (ec);
1523                                 }
1524                         }
1525
1526                         if (source != null)
1527                                 source.CloseMethod ();
1528
1529                         if (declarative_security != null) {
1530                                 foreach (var de in declarative_security) {
1531                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1532                                 }
1533                         }
1534
1535                         block = null;
1536                 }
1537
1538                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
1539                 {
1540                         // Is never override
1541                         bestCandidate = null;
1542                         return null;
1543                 }
1544
1545                 public override string GetSignatureForError()
1546                 {
1547                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1548                 }
1549
1550                 public override string[] ValidAttributeTargets {
1551                         get {
1552                                 return attribute_targets;
1553                         }
1554                 }
1555
1556                 protected override bool VerifyClsCompliance ()
1557                 {
1558                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1559                                 return false;
1560                         }
1561
1562                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1563                                 foreach (TypeSpec param in parameters.Types) {
1564                                         if (param.IsArray) {
1565                                                 return true;
1566                                         }
1567                                 }
1568                         }
1569
1570                         has_compliant_args = true;
1571                         return true;
1572                 }
1573
1574                 #region IMethodData Members
1575
1576                 public MemberName MethodName {
1577                         get {
1578                                 return MemberName;
1579                         }
1580                 }
1581
1582                 public TypeSpec ReturnType {
1583                         get {
1584                                 return MemberType;
1585                         }
1586                 }
1587
1588                 public EmitContext CreateEmitContext (ILGenerator ig)
1589                 {
1590                         throw new NotImplementedException ();
1591                 }
1592
1593                 public bool IsExcluded()
1594                 {
1595                         return false;
1596                 }
1597
1598                 GenericMethod IMethodData.GenericMethod {
1599                         get {
1600                                 return null;
1601                         }
1602                 }
1603
1604                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1605                 { }
1606
1607                 #endregion
1608         }
1609
1610         /// <summary>
1611         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1612         /// </summary>
1613         public interface IMethodData
1614         {
1615                 CallingConventions CallingConventions { get; }
1616                 Location Location { get; }
1617                 MemberName MethodName { get; }
1618                 TypeSpec ReturnType { get; }
1619                 GenericMethod GenericMethod { get; }
1620                 ParametersCompiled ParameterInfo { get; }
1621                 MethodSpec Spec { get; }
1622
1623                 Attributes OptAttributes { get; }
1624                 ToplevelBlock Block { get; set; }
1625
1626                 EmitContext CreateEmitContext (ILGenerator ig);
1627                 string GetSignatureForError ();
1628                 void EmitExtraSymbolInfo (SourceMethod source);
1629         }
1630
1631         //
1632         // Encapsulates most of the Method's state
1633         //
1634         public class MethodData {
1635                 static FieldInfo methodbuilder_attrs_field;
1636                 public readonly IMethodData method;
1637
1638                 public readonly GenericMethod GenericMethod;
1639
1640                 //
1641                 // Are we implementing an interface ?
1642                 //
1643                 public MethodSpec implementing;
1644
1645                 //
1646                 // Protected data.
1647                 //
1648                 protected InterfaceMemberBase member;
1649                 protected Modifiers modifiers;
1650                 protected MethodAttributes flags;
1651                 protected TypeSpec declaring_type;
1652                 protected MethodSpec parent_method;
1653
1654                 MethodBuilder builder;
1655                 public MethodBuilder MethodBuilder {
1656                         get {
1657                                 return builder;
1658                         }
1659                 }
1660
1661                 public TypeSpec DeclaringType {
1662                         get {
1663                                 return declaring_type;
1664                         }
1665                 }
1666
1667                 public MethodData (InterfaceMemberBase member,
1668                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1669                 {
1670                         this.member = member;
1671                         this.modifiers = modifiers;
1672                         this.flags = flags;
1673
1674                         this.method = method;
1675                 }
1676
1677                 public MethodData (InterfaceMemberBase member,
1678                                    Modifiers modifiers, MethodAttributes flags, 
1679                                    IMethodData method, MethodBuilder builder,
1680                                    GenericMethod generic, MethodSpec parent_method)
1681                         : this (member, modifiers, flags, method)
1682                 {
1683                         this.builder = builder;
1684                         this.GenericMethod = generic;
1685                         this.parent_method = parent_method;
1686                 }
1687
1688                 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1689                 {
1690                         TypeContainer container = parent.PartialContainer;
1691
1692                         PendingImplementation pending = container.PendingImplementations;
1693                         if (pending != null){
1694                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this);
1695
1696                                 if (member.InterfaceType != null){
1697                                         if (implementing == null){
1698                                                 if (member is PropertyBase) {
1699                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1700                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1701                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1702
1703                                                 } else {
1704                                                         Report.Error (539, method.Location,
1705                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
1706                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1707                                                 }
1708                                                 return false;
1709                                         }
1710                                         if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) {
1711                                                 Report.SymbolRelatedToPreviousError (implementing);
1712                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1713                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1714                                                 return false;
1715                                         }
1716                                 } else {
1717                                         if (implementing != null) {
1718                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1719                                                 if (prop_method == null) {
1720                                                         if (implementing.IsAccessor) {
1721                                                                 Report.SymbolRelatedToPreviousError (implementing);
1722                                                                 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'",
1723                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1724                                                         }
1725                                                 } else if (implementing.DeclaringType.IsInterface) {
1726                                                         if (!implementing.IsAccessor) {
1727                                                                 Report.SymbolRelatedToPreviousError (implementing);
1728                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1729                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1730                                                         } else {
1731                                                                 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1732                                                                 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1733                                                                         Report.SymbolRelatedToPreviousError (implementing);
1734                                                                         Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1735                                                                                 method.GetSignatureForError (), implementing.GetSignatureForError ());
1736                                                                 }
1737                                                         }
1738                                                 }
1739                                         }
1740                                 }
1741                         }
1742
1743                         //
1744                         // For implicit implementations, make sure we are public, for
1745                         // explicit implementations, make sure we are private.
1746                         //
1747                         if (implementing != null){
1748                                 //
1749                                 // Setting null inside this block will trigger a more
1750                                 // verbose error reporting for missing interface implementations
1751                                 //
1752                                 // The "candidate" function has been flagged already
1753                                 // but it wont get cleared
1754                                 //
1755                                 if (member.IsExplicitImpl){
1756                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
1757                                                 Report.SymbolRelatedToPreviousError (implementing);
1758                                                 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1759                                                         method.GetSignatureForError ());
1760                                         }
1761                                 } else {
1762                                         if (implementing.DeclaringType.IsInterface) {
1763                                                 //
1764                                                 // If this is an interface method implementation,
1765                                                 // check for public accessibility
1766                                                 //
1767                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1768                                                 {
1769                                                         implementing = null;
1770                                                 }
1771                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1772                                                 // We may never be private.
1773                                                 implementing = null;
1774
1775                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1776                                                 //
1777                                                 // We may be protected if we're overriding something.
1778                                                 //
1779                                                 implementing = null;
1780                                         }
1781                                 }
1782                                         
1783                                 //
1784                                 // Static is not allowed
1785                                 //
1786                                 if ((modifiers & Modifiers.STATIC) != 0){
1787                                         implementing = null;
1788                                 }
1789                         }
1790                         
1791                         //
1792                         // If implementing is still valid, set flags
1793                         //
1794                         if (implementing != null){
1795                                 //
1796                                 // When implementing interface methods, set NewSlot
1797                                 // unless, we are overwriting a method.
1798                                 //
1799                                 if (implementing.DeclaringType.IsInterface){
1800                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
1801                                                 flags |= MethodAttributes.NewSlot;
1802                                 }
1803
1804                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
1805
1806                                 // Set Final unless we're virtual, abstract or already overriding a method.
1807                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1808                                         flags |= MethodAttributes.Final;
1809
1810                                 //
1811                                 // clear the pending implementation flag (requires explicit methods to be defined first)
1812                                 //
1813                                 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName,
1814                                         member.InterfaceType, this, member.IsExplicitImpl);
1815
1816                                 //
1817                                 // Update indexer accessor name to match implementing abstract accessor
1818                                 //
1819                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
1820                                         method_full_name = implementing.MemberDefinition.Name;
1821                         }
1822
1823                         DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1824
1825                         if (builder == null)
1826                                 return false;
1827
1828 //                      if (container.CurrentType != null)
1829 //                              declaring_type = container.CurrentType;
1830 //                      else
1831                                 declaring_type = container.Definition;
1832
1833                         if (implementing != null && member.IsExplicitImpl) {
1834                                 container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
1835                         }
1836
1837                         return true;
1838                 }
1839
1840
1841                 /// <summary>
1842                 /// Create the MethodBuilder for the method 
1843                 /// </summary>
1844                 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1845                 {
1846                         var return_type = method.ReturnType.GetMetaInfo ();
1847                         var p_types = param.GetMetaInfo ();
1848
1849                         if (builder == null) {
1850                                 builder = container.TypeBuilder.DefineMethod (
1851                                         method_name, flags, method.CallingConventions,
1852                                         return_type, p_types);
1853                                 return;
1854                         }
1855
1856                         //
1857                         // Generic method has been already defined to resolve method parameters
1858                         // correctly when they use type parameters
1859                         //
1860                         builder.SetParameters (p_types);
1861                         builder.SetReturnType (return_type);
1862                         if (builder.Attributes != flags) {
1863                                 try {
1864                                         if (methodbuilder_attrs_field == null)
1865                                                 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1866                                         methodbuilder_attrs_field.SetValue (builder, flags);
1867                                 } catch {
1868                                         container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1869                                 }
1870                         }
1871                 }
1872
1873                 //
1874                 // Emits the code
1875                 // 
1876                 public void Emit (DeclSpace parent)
1877                 {
1878                         if (GenericMethod != null)
1879                                 GenericMethod.EmitAttributes ();
1880
1881                         method.ParameterInfo.ApplyAttributes (MethodBuilder);
1882
1883                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1884
1885                         ToplevelBlock block = method.Block;
1886                         if (block != null) {
1887                                 BlockContext bc = new BlockContext ((IMemberContext) method, block, method.ReturnType);
1888                                 if (block.Resolve (null, bc, method.ParameterInfo, method)) {
1889                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1890                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1891                                                 ec.ReturnLabel = bc.ReturnLabel;
1892                                                 ec.HasReturnLabel = true;
1893                                         }
1894
1895                                         block.Emit (ec);
1896                                 }
1897                         }
1898
1899                         if (source != null) {
1900                                 method.EmitExtraSymbolInfo (source);
1901                                 source.CloseMethod ();
1902                         }
1903                 }
1904         }
1905
1906         public class Destructor : MethodOrOperator
1907         {
1908                 const Modifiers AllowedModifiers =
1909                         Modifiers.UNSAFE |
1910                         Modifiers.EXTERN;
1911
1912                 static readonly string[] attribute_targets = new string [] { "method" };
1913
1914                 public static readonly string MetadataName = "Finalize";
1915
1916                 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
1917                         : base (parent, null, null, mod, AllowedModifiers,
1918                                 new MemberName (MetadataName, l), attrs, parameters)
1919                 {
1920                         ModFlags &= ~Modifiers.PRIVATE;
1921                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
1922                 }
1923
1924                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1925                 {
1926                         if (a.Type == pa.Conditional) {
1927                                 Error_ConditionalAttributeIsNotValid ();
1928                                 return;
1929                         }
1930
1931                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
1932                 }
1933
1934                 protected override bool CheckBase ()
1935                 {
1936                         // Don't check base, destructors have special syntax
1937                         return true;
1938                 }
1939
1940                 public override void Emit()
1941                 {
1942                         var base_type = Parent.PartialContainer.BaseType;
1943                         if (base_type != null && Block != null) {
1944                                 var base_dtor = MemberCache.FindMember (base_type,
1945                                         new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
1946
1947                                 if (base_dtor == null)
1948                                         throw new NotImplementedException ();
1949
1950                                 MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
1951                                 method_expr.InstanceExpression = new BaseThis (base_type, Location);
1952
1953                                 ToplevelBlock new_block = new ToplevelBlock (Compiler, Block.StartLocation);
1954                                 new_block.EndLocation = Block.EndLocation;
1955
1956                                 Block finaly_block = new ExplicitBlock (new_block, Location, Location);
1957                                 Block try_block = new Block (new_block, block);
1958
1959                                 //
1960                                 // 0-size arguments to avoid CS0250 error
1961                                 // TODO: Should use AddScopeStatement or something else which emits correct
1962                                 // debugger scope
1963                                 //
1964                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
1965                                 new_block.AddStatement (new TryFinally (try_block, finaly_block, Location));
1966
1967                                 block = new_block;
1968                         }
1969
1970                         base.Emit ();
1971                 }
1972
1973                 public override string GetSignatureForError ()
1974                 {
1975                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
1976                 }
1977
1978                 protected override bool ResolveMemberType ()
1979                 {
1980                         member_type = TypeManager.void_type;
1981                         return true;
1982                 }
1983
1984                 public override string[] ValidAttributeTargets {
1985                         get {
1986                                 return attribute_targets;
1987                         }
1988                 }
1989         }
1990
1991         // Ooouh Martin, templates are missing here.
1992         // When it will be possible move here a lot of child code and template method type.
1993         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
1994                 protected MethodData method_data;
1995                 protected ToplevelBlock block;
1996                 protected Dictionary<SecurityAction, PermissionSet> declarative_security;
1997
1998                 protected readonly string prefix;
1999
2000                 ReturnParameter return_attributes;
2001
2002                 public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2003                         : base (member.Parent, SetupName (prefix, member, loc), attrs)
2004                 {
2005                         this.prefix = prefix;
2006                 }
2007
2008                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2009                 {
2010                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
2011                 }
2012
2013                 public void UpdateName (InterfaceMemberBase member)
2014                 {
2015                         SetMemberName (SetupName (prefix, member, Location));
2016                 }
2017
2018                 #region IMethodData Members
2019
2020                 public ToplevelBlock Block {
2021                         get {
2022                                 return block;
2023                         }
2024
2025                         set {
2026                                 block = value;
2027                         }
2028                 }
2029
2030                 public CallingConventions CallingConventions {
2031                         get {
2032                                 return CallingConventions.Standard;
2033                         }
2034                 }
2035
2036                 public EmitContext CreateEmitContext (ILGenerator ig)
2037                 {
2038                         return new EmitContext (this, ig, ReturnType);
2039                 }
2040
2041                 public bool IsExcluded ()
2042                 {
2043                         return false;
2044                 }
2045
2046                 GenericMethod IMethodData.GenericMethod {
2047                         get {
2048                                 return null;
2049                         }
2050                 }
2051
2052                 public MemberName MethodName {
2053                         get {
2054                                 return MemberName;
2055                         }
2056                 }
2057
2058                 public TypeSpec[] ParameterTypes { 
2059                         get {
2060                                 return ParameterInfo.Types;
2061                         }
2062                 }
2063
2064                 public abstract ParametersCompiled ParameterInfo { get ; }
2065                 public abstract TypeSpec ReturnType { get; }
2066
2067                 #endregion
2068
2069                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2070                 {
2071                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2072                                 Report.Error (1667, a.Location,
2073                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2074                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
2075                                 return;
2076                         }
2077
2078                         if (a.IsValidSecurityAttribute ()) {
2079                                 if (declarative_security == null)
2080                                         declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
2081                                 a.ExtractSecurityPermissionSet (declarative_security);
2082                                 return;
2083                         }
2084
2085                         if (a.Target == AttributeTargets.Method) {
2086                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2087                                 return;
2088                         }
2089
2090                         if (a.Target == AttributeTargets.ReturnValue) {
2091                                 if (return_attributes == null)
2092                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2093
2094                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2095                                 return;
2096                         }
2097
2098                         ApplyToExtraTarget (a, ctor, cdata, pa);
2099                 }
2100
2101                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2102                 {
2103                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2104                 }
2105
2106                 // It is not supported for the accessors
2107                 public sealed override bool Define()
2108                 {
2109                         throw new NotSupportedException ();
2110                 }
2111
2112                 public virtual void Emit (DeclSpace parent)
2113                 {
2114                         method_data.Emit (parent);
2115
2116                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2117                                 PredefinedAttributes.Get.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2118                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2119                                 PredefinedAttributes.Get.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2120
2121                         if (ReturnType == InternalType.Dynamic) {
2122                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2123                                 PredefinedAttributes.Get.Dynamic.EmitAttribute (return_attributes.Builder);
2124                         } else {
2125                                 var trans_flags = TypeManager.HasDynamicTypeUsed (ReturnType);
2126                                 if (trans_flags != null) {
2127                                         var pa = PredefinedAttributes.Get.DynamicTransform;
2128                                         if (pa.Constructor != null || pa.ResolveConstructor (Location, ArrayContainer.MakeType (TypeManager.bool_type))) {
2129                                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2130                                                 return_attributes.Builder.SetCustomAttribute (
2131                                                         new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
2132                                         }
2133                                 }
2134                         }
2135
2136                         if (OptAttributes != null)
2137                                 OptAttributes.Emit ();
2138
2139                         if (declarative_security != null) {
2140                                 foreach (var de in declarative_security) {
2141                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2142                                 }
2143                         }
2144
2145                         block = null;
2146                 }
2147
2148                 public override bool EnableOverloadChecks (MemberCore overload)
2149                 {
2150                         if (overload is MethodCore) {
2151                                 caching_flags |= Flags.MethodOverloadsExist;
2152                                 return true;
2153                         }
2154
2155                         // This can only happen with indexers and it will
2156                         // be catched as indexer difference
2157                         if (overload is AbstractPropertyEventMethod)
2158                                 return true;
2159
2160                         return false;
2161                 }
2162
2163                 public override bool IsClsComplianceRequired()
2164                 {
2165                         return false;
2166                 }
2167
2168                 public MethodSpec Spec { get; protected set; }
2169
2170                 //
2171                 //   Represents header string for documentation comment.
2172                 //
2173                 public override string DocCommentHeader {
2174                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2175                 }
2176
2177                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2178                 { }
2179         }
2180
2181         public class Operator : MethodOrOperator {
2182
2183                 const Modifiers AllowedModifiers =
2184                         Modifiers.PUBLIC |
2185                         Modifiers.UNSAFE |
2186                         Modifiers.EXTERN |
2187                         Modifiers.STATIC;
2188
2189                 public enum OpType : byte {
2190
2191                         // Unary operators
2192                         LogicalNot,
2193                         OnesComplement,
2194                         Increment,
2195                         Decrement,
2196                         True,
2197                         False,
2198
2199                         // Unary and Binary operators
2200                         Addition,
2201                         Subtraction,
2202
2203                         UnaryPlus,
2204                         UnaryNegation,
2205                         
2206                         // Binary operators
2207                         Multiply,
2208                         Division,
2209                         Modulus,
2210                         BitwiseAnd,
2211                         BitwiseOr,
2212                         ExclusiveOr,
2213                         LeftShift,
2214                         RightShift,
2215                         Equality,
2216                         Inequality,
2217                         GreaterThan,
2218                         LessThan,
2219                         GreaterThanOrEqual,
2220                         LessThanOrEqual,
2221
2222                         // Implicit and Explicit
2223                         Implicit,
2224                         Explicit,
2225
2226                         // Just because of enum
2227                         TOP
2228                 };
2229
2230                 public readonly OpType OperatorType;
2231
2232                 static readonly string [] [] names;
2233
2234                 static Operator ()
2235                 {
2236                         names = new string[(int)OpType.TOP][];
2237                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2238                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2239                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2240                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2241                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2242                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2243                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2244                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2245                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2246                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2247                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2248                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2249                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2250                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2251                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2252                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2253                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2254                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2255                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2256                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2257                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2258                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2259                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2260                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2261                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2262                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2263                 }
2264                 
2265                 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2266                                  Modifiers mod_flags, ParametersCompiled parameters,
2267                                  ToplevelBlock block, Attributes attrs, Location loc)
2268                         : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2269                                 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2270                 {
2271                         OperatorType = type;
2272                         Block = block;
2273                 }
2274
2275                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2276                 {
2277                         if (a.Type == pa.Conditional) {
2278                                 Error_ConditionalAttributeIsNotValid ();
2279                                 return;
2280                         }
2281
2282                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2283                 }
2284                 
2285                 public override bool Define ()
2286                 {
2287                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2288                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2289                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2290                         }
2291
2292                         if (!base.Define ())
2293                                 return false;
2294
2295                         if (block != null && block.IsIterator && !(Parent is IteratorStorey)) {
2296                                 //
2297                                 // Current method is turned into automatically generated
2298                                 // wrapper which creates an instance of iterator
2299                                 //
2300                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
2301                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2302                         }
2303
2304                         // imlicit and explicit operator of same types are not allowed
2305                         if (OperatorType == OpType.Explicit)
2306                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2307                         else if (OperatorType == OpType.Implicit)
2308                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2309
2310                         TypeSpec declaring_type = Parent.CurrentType;
2311                         TypeSpec return_type = MemberType;
2312                         TypeSpec first_arg_type = ParameterTypes [0];
2313                         
2314                         TypeSpec first_arg_type_unwrap = first_arg_type;
2315                         if (TypeManager.IsNullableType (first_arg_type))
2316                                 first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0];
2317                         
2318                         TypeSpec return_type_unwrap = return_type;
2319                         if (TypeManager.IsNullableType (return_type))
2320                                 return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0];
2321
2322                         //
2323                         // Rules for conversion operators
2324                         //
2325                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2326                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2327                                         Report.Error (555, Location,
2328                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2329                                         return false;
2330                                 }
2331
2332                                 TypeSpec conv_type;
2333                                 if (TypeManager.IsEqual (declaring_type, return_type) || declaring_type == return_type_unwrap) {
2334                                         conv_type = first_arg_type;
2335                                 } else if (TypeManager.IsEqual (declaring_type, first_arg_type) || declaring_type == first_arg_type_unwrap) {
2336                                         conv_type = return_type;
2337                                 } else {
2338                                         Report.Error (556, Location,
2339                                                 "User-defined conversion must convert to or from the enclosing type");
2340                                         return false;
2341                                 }
2342
2343                                 if (conv_type == InternalType.Dynamic) {
2344                                         Report.Error (1964, Location,
2345                                                 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2346                                                 GetSignatureForError ());
2347
2348                                         return false;
2349                                 }
2350
2351                                 if (conv_type.IsInterface) {
2352                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2353                                                 GetSignatureForError ());
2354                                         return false;
2355                                 }
2356
2357                                 if (conv_type.IsClass) {
2358                                         if (TypeManager.IsSubclassOf (declaring_type, conv_type)) {
2359                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2360                                                         GetSignatureForError ());
2361                                                 return false;
2362                                         }
2363
2364                                         if (TypeManager.IsSubclassOf (conv_type, declaring_type)) {
2365                                                 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2366                                                         GetSignatureForError ());
2367                                                 return false;
2368                                         }
2369                                 }
2370                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2371                                 if (first_arg_type != declaring_type || parameters.Types[1] != TypeManager.int32_type) {
2372                                         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");
2373                                         return false;
2374                                 }
2375                         } else if (parameters.Count == 1) {
2376                                 // Checks for Unary operators
2377
2378                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2379                                         if (return_type != declaring_type && !TypeManager.IsSubclassOf (return_type, declaring_type)) {
2380                                                 Report.Error (448, Location,
2381                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2382                                                 return false;
2383                                         }
2384                                         if (first_arg_type != declaring_type) {
2385                                                 Report.Error (
2386                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2387                                                 return false;
2388                                         }
2389                                 }
2390
2391                                 if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
2392                                         Report.Error (562, Location,
2393                                                 "The parameter type of a unary operator must be the containing type");
2394                                         return false;
2395                                 }
2396
2397                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2398                                         if (return_type != TypeManager.bool_type) {
2399                                                 Report.Error (
2400                                                         215, Location,
2401                                                         "The return type of operator True or False " +
2402                                                         "must be bool");
2403                                                 return false;
2404                                         }
2405                                 }
2406
2407                         } else if (!TypeManager.IsEqual (first_arg_type_unwrap, declaring_type)) {
2408                                 // Checks for Binary operators
2409
2410                                 var second_arg_type = ParameterTypes[1];
2411                                 if (TypeManager.IsNullableType (second_arg_type))
2412                                         second_arg_type = TypeManager.GetTypeArguments (second_arg_type)[0];
2413
2414                                 if (!TypeManager.IsEqual (second_arg_type, declaring_type)) {
2415                                         Report.Error (563, Location,
2416                                                 "One of the parameters of a binary operator must be the containing type");
2417                                         return false;
2418                                 }
2419                         }
2420
2421                         return true;
2422                 }
2423
2424                 protected override bool ResolveMemberType ()
2425                 {
2426                         if (!base.ResolveMemberType ())
2427                                 return false;
2428
2429                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2430                         return true;
2431                 }
2432
2433                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
2434                 {
2435                         // Operator cannot be override
2436                         bestCandidate = null;
2437                         return null;
2438                 }
2439
2440                 public static string GetName (OpType ot)
2441                 {
2442                         return names [(int) ot] [0];
2443                 }
2444
2445                 public static string GetName (string metadata_name)
2446                 {
2447                         for (int i = 0; i < names.Length; ++i) {
2448                                 if (names [i] [1] == metadata_name)
2449                                         return names [i] [0];
2450                         }
2451                         return null;
2452                 }
2453
2454                 public static string GetMetadataName (OpType ot)
2455                 {
2456                         return names [(int) ot] [1];
2457                 }
2458
2459                 public static string GetMetadataName (string name)
2460                 {
2461                         for (int i = 0; i < names.Length; ++i) {
2462                                 if (names [i] [0] == name)
2463                                         return names [i] [1];
2464                         }
2465                         return null;
2466                 }
2467
2468                 public static OpType? GetType (string metadata_name)
2469                 {
2470                         for (int i = 0; i < names.Length; ++i) {
2471                                 if (names[i][1] == metadata_name)
2472                                         return (OpType) i;
2473                         }
2474
2475                         return null;
2476                 }
2477
2478                 public OpType GetMatchingOperator ()
2479                 {
2480                         switch (OperatorType) {
2481                         case OpType.Equality:
2482                                 return OpType.Inequality;
2483                         case OpType.Inequality:
2484                                 return OpType.Equality;
2485                         case OpType.True:
2486                                 return OpType.False;
2487                         case OpType.False:
2488                                 return OpType.True;
2489                         case OpType.GreaterThan:
2490                                 return OpType.LessThan;
2491                         case OpType.LessThan:
2492                                 return OpType.GreaterThan;
2493                         case OpType.GreaterThanOrEqual:
2494                                 return OpType.LessThanOrEqual;
2495                         case OpType.LessThanOrEqual:
2496                                 return OpType.GreaterThanOrEqual;
2497                         default:
2498                                 return OpType.TOP;
2499                         }
2500                 }
2501
2502                 public override string GetSignatureForError ()
2503                 {
2504                         StringBuilder sb = new StringBuilder ();
2505                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2506                                 sb.AppendFormat ("{0}.{1} operator {2}",
2507                                         Parent.GetSignatureForError (), GetName (OperatorType), type_expr.GetSignatureForError ());
2508                         }
2509                         else {
2510                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2511                         }
2512
2513                         sb.Append (parameters.GetSignatureForError ());
2514                         return sb.ToString ();
2515                 }
2516         }
2517 }
2518