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