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