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