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