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