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