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