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