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