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