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