[csharp] repl using statement fix + support for --fatal
[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 (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 (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 (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 (RootContext.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                         if (RootContext.NeedsEntryPoint &&
1145                                 Name == "Main" &&
1146                                 (RootContext.MainClass == null ||
1147                                 RootContext.MainClass == Parent.TypeBuilder.FullName)){
1148                                 if (IsEntryPoint ()) {
1149
1150                                         if (Parent.DeclaringAssembly.EntryPoint == null) {
1151                                                 if (Parent.IsGeneric || MemberName.IsGeneric) {
1152                                                         Report.Warning (402, 4, Location, "`{0}': an entry point cannot be generic or in a generic type",
1153                                                                 GetSignatureForError ());
1154                                                 } else {
1155                                                         SetIsUsed ();
1156                                                         Parent.DeclaringAssembly.EntryPoint = this;
1157                                                 }
1158                                         } else {
1159                                                 Error_DuplicateEntryPoint (Parent.DeclaringAssembly.EntryPoint);
1160                                                 Error_DuplicateEntryPoint (this);
1161                                         }
1162                                 } else {
1163                                         Report.Warning (28, 4, Location, "`{0}' has the wrong signature to be an entry point",
1164                                                 GetSignatureForError ());
1165                                 }
1166                         }
1167
1168                         return true;
1169                 }
1170
1171                 //
1172                 // Emits the code
1173                 // 
1174                 public override void Emit ()
1175                 {
1176                         try {
1177                                 if (IsPartialDefinition) {
1178                                         //
1179                                         // Use partial method implementation builder for partial method declaration attributes
1180                                         //
1181                                         if (partialMethodImplementation != null) {
1182                                                 MethodBuilder = partialMethodImplementation.MethodBuilder;
1183                                         }
1184
1185                                         return;
1186                                 }
1187                                 
1188                                 if ((ModFlags & Modifiers.PARTIAL) != 0 && (caching_flags & Flags.PartialDefinitionExists) == 0) {
1189                                         Report.Error (759, Location, "A partial method `{0}' implementation is missing a partial method declaration",
1190                                                 GetSignatureForError ());
1191                                 }
1192
1193                                 if (CurrentTypeParameters != null) {
1194                                         var ge = type_expr as GenericTypeExpr;
1195                                         if (ge != null)
1196                                                 ge.CheckConstraints (this);
1197
1198                                         foreach (Parameter p in parameters.FixedParameters) {
1199                                                 ge = p.TypeExpression as GenericTypeExpr;
1200                                                 if (ge != null)
1201                                                         ge.CheckConstraints (this);
1202                                         }
1203
1204                                         for (int i = 0; i < CurrentTypeParameters.Length; ++i) {
1205                                                 var tp = CurrentTypeParameters [i];
1206                                                 tp.CheckGenericConstraints ();
1207                                                 tp.Emit ();
1208                                         }
1209                                 }
1210
1211                                 base.Emit ();
1212                                 
1213                                 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
1214                                         Module.PredefinedAttributes.Extension.EmitAttribute (MethodBuilder);
1215                         } catch {
1216                                 Console.WriteLine ("Internal compiler error at {0}: exception caught while emitting {1}",
1217                                                    Location, MethodBuilder);
1218                                 throw;
1219                         }
1220                 }
1221
1222                 public override bool EnableOverloadChecks (MemberCore overload)
1223                 {
1224                         // TODO: It can be deleted when members will be defined in correct order
1225                         if (overload is Operator)
1226                                 return overload.EnableOverloadChecks (this);
1227
1228                         if (overload is Indexer)
1229                                 return false;
1230
1231                         return base.EnableOverloadChecks (overload);
1232                 }
1233
1234                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1235                 {
1236                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
1237                 }
1238
1239                 protected override bool ResolveMemberType ()
1240                 {
1241                         if (GenericMethod != null) {
1242                                 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
1243                                 if (!GenericMethod.Define (this))
1244                                         return false;
1245                         }
1246
1247                         return base.ResolveMemberType ();
1248                 }
1249
1250                 public void SetPartialDefinition (Method methodDefinition)
1251                 {
1252                         caching_flags |= Flags.PartialDefinitionExists;
1253                         methodDefinition.partialMethodImplementation = this;
1254
1255                         // Ensure we are always using method declaration parameters
1256                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1257                                 parameters [i].Name = methodDefinition.parameters [i].Name;
1258                                 parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue;
1259                         }
1260
1261                         if (methodDefinition.attributes == null)
1262                                 return;
1263
1264                         if (attributes == null) {
1265                                 attributes = methodDefinition.attributes;
1266                         } else {
1267                                 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1268                         }
1269                 }
1270         }
1271
1272         public abstract class ConstructorInitializer : ExpressionStatement
1273         {
1274                 Arguments argument_list;
1275                 MethodSpec base_ctor;
1276
1277                 public ConstructorInitializer (Arguments argument_list, Location loc)
1278                 {
1279                         this.argument_list = argument_list;
1280                         this.loc = loc;
1281                 }
1282
1283                 public Arguments Arguments {
1284                         get {
1285                                 return argument_list;
1286                         }
1287                 }
1288
1289                 public override Expression CreateExpressionTree (ResolveContext ec)
1290                 {
1291                         throw new NotSupportedException ("ET");
1292                 }
1293
1294                 protected override Expression DoResolve (ResolveContext ec)
1295                 {
1296                         eclass = ExprClass.Value;
1297
1298                         // FIXME: Hack
1299                         var caller_builder = (Constructor) ec.MemberContext;
1300
1301                         //
1302                         // Spec mandates that constructor initializer will not have `this' access
1303                         //
1304                         using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1305                                 if (argument_list != null) {
1306                                         bool dynamic;
1307                                         argument_list.Resolve (ec, out dynamic);
1308
1309                                         if (dynamic) {
1310                                                 ec.Report.Error (1975, loc,
1311                                                         "The constructor call cannot be dynamically dispatched within constructor initializer");
1312
1313                                                 return null;
1314                                         }
1315                                 }
1316
1317                                 type = ec.CurrentType;
1318                                 if (this is ConstructorBaseInitializer) {
1319                                         if (ec.CurrentType.BaseType == null)
1320                                                 return this;
1321
1322                                         type = ec.CurrentType.BaseType;
1323                                         if (ec.CurrentType.IsStruct) {
1324                                                 ec.Report.Error (522, loc,
1325                                                         "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1326                                                 return this;
1327                                         }
1328                                 } else {
1329                                         //
1330                                         // It is legal to have "this" initializers that take no arguments
1331                                         // in structs, they are just no-ops.
1332                                         //
1333                                         // struct D { public D (int a) : this () {}
1334                                         //
1335                                         if (TypeManager.IsStruct (ec.CurrentType) && argument_list == null)
1336                                                 return this;
1337                                 }
1338
1339                                 base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
1340                         }
1341         
1342                         // TODO MemberCache: Does it work for inflated types ?
1343                         if (base_ctor == caller_builder.Spec){
1344                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1345                                         caller_builder.GetSignatureForError ());
1346                         }
1347                                                 
1348                         return this;
1349                 }
1350
1351                 public override void Emit (EmitContext ec)
1352                 {
1353                         // It can be null for static initializers
1354                         if (base_ctor == null)
1355                                 return;
1356                         
1357                         ec.Mark (loc);
1358
1359                         Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc);
1360                 }
1361
1362                 public override void EmitStatement (EmitContext ec)
1363                 {
1364                         Emit (ec);
1365                 }
1366         }
1367
1368         public class ConstructorBaseInitializer : ConstructorInitializer {
1369                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1370                         base (argument_list, l)
1371                 {
1372                 }
1373         }
1374
1375         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1376                 public GeneratedBaseInitializer (Location loc):
1377                         base (null, loc)
1378                 {
1379                 }
1380         }
1381
1382         public class ConstructorThisInitializer : ConstructorInitializer {
1383                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1384                         base (argument_list, l)
1385                 {
1386                 }
1387         }
1388         
1389         public class Constructor : MethodCore, IMethodData {
1390                 public ConstructorBuilder ConstructorBuilder;
1391                 public ConstructorInitializer Initializer;
1392                 SecurityType declarative_security;
1393                 bool has_compliant_args;
1394
1395                 // <summary>
1396                 //   Modifiers allowed for a constructor.
1397                 // </summary>
1398                 public const Modifiers AllowedModifiers =
1399                         Modifiers.PUBLIC |
1400                         Modifiers.PROTECTED |
1401                         Modifiers.INTERNAL |
1402                         Modifiers.STATIC |
1403                         Modifiers.UNSAFE |
1404                         Modifiers.EXTERN |              
1405                         Modifiers.PRIVATE;
1406
1407                 static readonly string[] attribute_targets = new string [] { "method" };
1408
1409                 public static readonly string ConstructorName = ".ctor";
1410                 public static readonly string TypeConstructorName = ".cctor";
1411
1412                 //
1413                 // The spec claims that static is not permitted, but
1414                 // my very own code has static constructors.
1415                 //
1416                 public Constructor (DeclSpace parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args,
1417                                     ConstructorInitializer init, Location loc)
1418                         : base (parent, null, null, mod, AllowedModifiers,
1419                                 new MemberName (name, loc), attrs, args)
1420                 {
1421                         Initializer = init;
1422                 }
1423
1424                 public bool HasCompliantArgs {
1425                         get { return has_compliant_args; }
1426                 }
1427
1428                 public override AttributeTargets AttributeTargets {
1429                         get { return AttributeTargets.Constructor; }
1430                 }
1431
1432                 //
1433                 // Returns true if this is a default constructor
1434                 //
1435                 public bool IsDefault ()
1436                 {
1437                         if ((ModFlags & Modifiers.STATIC) != 0)
1438                                 return parameters.IsEmpty;
1439
1440                         return parameters.IsEmpty &&
1441                                         (Initializer is ConstructorBaseInitializer) &&
1442                                         (Initializer.Arguments == null);
1443                 }
1444
1445                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1446                 {
1447                         if (a.IsValidSecurityAttribute ()) {
1448                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
1449                                 return;
1450                         }
1451
1452                         if (a.Type == pa.MethodImpl) {
1453                                 is_external_implementation = a.IsInternalCall ();
1454                         }
1455
1456                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1457                 }
1458
1459                 protected override bool CheckBase ()
1460                 {
1461                         if ((ModFlags & Modifiers.STATIC) != 0) {
1462                                 if (!parameters.IsEmpty) {
1463                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1464                                                 GetSignatureForError ());
1465                                         return false;
1466                                 }
1467
1468                                 // the rest can be ignored
1469                                 return true;
1470                         }
1471
1472                         // Check whether arguments were correct.
1473                         if (!DefineParameters (parameters))
1474                                 return false;
1475
1476                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1477                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1478
1479                         if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
1480                                 Report.Error (568, Location, 
1481                                         "Structs cannot contain explicit parameterless constructors");
1482                                 return false;
1483                         }
1484
1485                         CheckProtectedModifier ();
1486                         
1487                         return true;
1488                 }
1489                 
1490                 //
1491                 // Creates the ConstructorBuilder
1492                 //
1493                 public override bool Define ()
1494                 {
1495                         if (ConstructorBuilder != null)
1496                                 return true;
1497
1498                         var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1499                         
1500                         if ((ModFlags & Modifiers.STATIC) != 0) {
1501                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
1502                         } else {
1503                                 ca |= ModifiersExtensions.MethodAttr (ModFlags);
1504                         }
1505
1506                         if (!CheckAbstractAndExtern (block != null))
1507                                 return false;
1508                         
1509                         // Check if arguments were correct.
1510                         if (!CheckBase ())
1511                                 return false;
1512
1513                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1514                                 ca, CallingConventions,
1515                                 parameters.GetMetaInfo ());
1516
1517                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, TypeManager.void_type, ConstructorBuilder, parameters, ModFlags);
1518                         
1519                         Parent.MemberCache.AddMember (spec);
1520                         
1521                         // It's here only to report an error
1522                         if (block != null && block.IsIterator) {
1523                                 member_type = TypeManager.void_type;
1524                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
1525                         }
1526
1527                         return true;
1528                 }
1529
1530                 //
1531                 // Emits the code
1532                 //
1533                 public override void Emit ()
1534                 {
1535                         if (Parent.PartialContainer.IsComImport) {
1536                                 if (!IsDefault ()) {
1537                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1538                                                 Parent.GetSignatureForError ());
1539                                 }
1540
1541                                 // Set as internal implementation and reset block data
1542                                 // to ensure no IL is generated
1543                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1544                                 block = null;
1545                         }
1546
1547                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1548                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1549
1550                         if (OptAttributes != null)
1551                                 OptAttributes.Emit ();
1552
1553                         base.Emit ();
1554
1555                         //
1556                         // If we use a "this (...)" constructor initializer, then
1557                         // do not emit field initializers, they are initialized in the other constructor
1558                         //
1559                         bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1560                                 !(Initializer is ConstructorThisInitializer);
1561
1562                         BlockContext bc = new BlockContext (this, block, TypeManager.void_type);
1563                         bc.Set (ResolveContext.Options.ConstructorScope);
1564
1565                         if (emit_field_initializers)
1566                                 Parent.PartialContainer.ResolveFieldInitializers (bc);
1567
1568                         if (block != null) {
1569                                 // If this is a non-static `struct' constructor and doesn't have any
1570                                 // initializer, it must initialize all of the struct's fields.
1571                                 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1572                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1573                                         block.AddThisVariable (bc, Parent, Location);
1574
1575                                 if (block != null && (ModFlags & Modifiers.STATIC) == 0){
1576                                         if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1577                                                 Initializer = new GeneratedBaseInitializer (Location);
1578
1579                                         if (Initializer != null) {
1580                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1581                                         }
1582                                 }
1583                         }
1584
1585                         parameters.ApplyAttributes (this, ConstructorBuilder);
1586
1587                         SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1588
1589                         if (block != null) {
1590                                 if (block.Resolve (null, bc, this)) {
1591                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1592                                         ec.With (EmitContext.Options.ConstructorScope, true);
1593
1594                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1595                                                 ec.ReturnLabel = bc.ReturnLabel;
1596                                                 ec.HasReturnLabel = true;
1597                                         }
1598
1599                                         block.Emit (ec);
1600                                 }
1601                         }
1602
1603                         if (source != null)
1604                                 source.CloseMethod ();
1605
1606                         if (declarative_security != null) {
1607                                 foreach (var de in declarative_security) {
1608 #if STATIC
1609                                         ConstructorBuilder.__AddDeclarativeSecurity (de);
1610 #else
1611                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1612 #endif
1613                                 }
1614                         }
1615
1616                         block = null;
1617                 }
1618
1619                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
1620                 {
1621                         // Is never override
1622                         bestCandidate = null;
1623                         return null;
1624                 }
1625
1626                 public override string GetSignatureForError()
1627                 {
1628                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1629                 }
1630
1631                 public override string[] ValidAttributeTargets {
1632                         get {
1633                                 return attribute_targets;
1634                         }
1635                 }
1636
1637                 protected override bool VerifyClsCompliance ()
1638                 {
1639                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1640                                 return false;
1641                         }
1642
1643                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1644                                 foreach (TypeSpec param in parameters.Types) {
1645                                         if (param.IsArray) {
1646                                                 return true;
1647                                         }
1648                                 }
1649                         }
1650
1651                         has_compliant_args = true;
1652                         return true;
1653                 }
1654
1655                 #region IMethodData Members
1656
1657                 public MemberName MethodName {
1658                         get {
1659                                 return MemberName;
1660                         }
1661                 }
1662
1663                 public TypeSpec ReturnType {
1664                         get {
1665                                 return MemberType;
1666                         }
1667                 }
1668
1669                 public EmitContext CreateEmitContext (ILGenerator ig)
1670                 {
1671                         throw new NotImplementedException ();
1672                 }
1673
1674                 public bool IsExcluded()
1675                 {
1676                         return false;
1677                 }
1678
1679                 GenericMethod IMethodData.GenericMethod {
1680                         get {
1681                                 return null;
1682                         }
1683                 }
1684
1685                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1686                 { }
1687
1688                 #endregion
1689         }
1690
1691         /// <summary>
1692         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1693         /// </summary>
1694         public interface IMethodData
1695         {
1696                 CallingConventions CallingConventions { get; }
1697                 Location Location { get; }
1698                 MemberName MethodName { get; }
1699                 TypeSpec ReturnType { get; }
1700                 GenericMethod GenericMethod { get; }
1701                 ParametersCompiled ParameterInfo { get; }
1702                 MethodSpec Spec { get; }
1703
1704                 Attributes OptAttributes { get; }
1705                 ToplevelBlock Block { get; set; }
1706
1707                 EmitContext CreateEmitContext (ILGenerator ig);
1708                 string GetSignatureForError ();
1709                 void EmitExtraSymbolInfo (SourceMethod source);
1710         }
1711
1712         //
1713         // Encapsulates most of the Method's state
1714         //
1715         public class MethodData {
1716                 static FieldInfo methodbuilder_attrs_field;
1717                 public readonly IMethodData method;
1718
1719                 public readonly GenericMethod GenericMethod;
1720
1721                 //
1722                 // Are we implementing an interface ?
1723                 //
1724                 public MethodSpec implementing;
1725
1726                 //
1727                 // Protected data.
1728                 //
1729                 protected InterfaceMemberBase member;
1730                 protected Modifiers modifiers;
1731                 protected MethodAttributes flags;
1732                 protected TypeSpec declaring_type;
1733                 protected MethodSpec parent_method;
1734
1735                 MethodBuilder builder;
1736                 public MethodBuilder MethodBuilder {
1737                         get {
1738                                 return builder;
1739                         }
1740                 }
1741
1742                 public TypeSpec DeclaringType {
1743                         get {
1744                                 return declaring_type;
1745                         }
1746                 }
1747
1748                 public MethodData (InterfaceMemberBase member,
1749                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1750                 {
1751                         this.member = member;
1752                         this.modifiers = modifiers;
1753                         this.flags = flags;
1754
1755                         this.method = method;
1756                 }
1757
1758                 public MethodData (InterfaceMemberBase member,
1759                                    Modifiers modifiers, MethodAttributes flags, 
1760                                    IMethodData method, MethodBuilder builder,
1761                                    GenericMethod generic, MethodSpec parent_method)
1762                         : this (member, modifiers, flags, method)
1763                 {
1764                         this.builder = builder;
1765                         this.GenericMethod = generic;
1766                         this.parent_method = parent_method;
1767                 }
1768
1769                 public bool Define (DeclSpace parent, string method_full_name, Report Report)
1770                 {
1771                         TypeContainer container = parent.PartialContainer;
1772
1773                         PendingImplementation pending = container.PendingImplementations;
1774                         if (pending != null){
1775                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this);
1776
1777                                 if (member.InterfaceType != null){
1778                                         if (implementing == null){
1779                                                 if (member is PropertyBase) {
1780                                                         Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
1781                                                                       method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1782                                                                       member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1783
1784                                                 } else {
1785                                                         Report.Error (539, method.Location,
1786                                                                       "`{0}.{1}' in explicit interface declaration is not a member of interface",
1787                                                                       TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1788                                                 }
1789                                                 return false;
1790                                         }
1791                                         if (implementing.IsAccessor && !(method is AbstractPropertyEventMethod)) {
1792                                                 Report.SymbolRelatedToPreviousError (implementing);
1793                                                 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1794                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1795                                                 return false;
1796                                         }
1797                                 } else {
1798                                         if (implementing != null) {
1799                                                 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
1800                                                 if (prop_method == null) {
1801                                                         if (implementing.IsAccessor) {
1802                                                                 Report.SymbolRelatedToPreviousError (implementing);
1803                                                                 Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'",
1804                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1805                                                         }
1806                                                 } else if (implementing.DeclaringType.IsInterface) {
1807                                                         if (!implementing.IsAccessor) {
1808                                                                 Report.SymbolRelatedToPreviousError (implementing);
1809                                                                 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1810                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1811                                                         } else {
1812                                                                 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
1813                                                                 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1814                                                                         Report.SymbolRelatedToPreviousError (implementing);
1815                                                                         Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
1816                                                                                 method.GetSignatureForError (), implementing.GetSignatureForError ());
1817                                                                 }
1818                                                         }
1819                                                 }
1820                                         }
1821                                 }
1822                         }
1823
1824                         //
1825                         // For implicit implementations, make sure we are public, for
1826                         // explicit implementations, make sure we are private.
1827                         //
1828                         if (implementing != null){
1829                                 //
1830                                 // Setting null inside this block will trigger a more
1831                                 // verbose error reporting for missing interface implementations
1832                                 //
1833                                 // The "candidate" function has been flagged already
1834                                 // but it wont get cleared
1835                                 //
1836                                 if (member.IsExplicitImpl){
1837                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
1838                                                 Report.SymbolRelatedToPreviousError (implementing);
1839                                                 Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier",
1840                                                         method.GetSignatureForError ());
1841                                         }
1842                                 } else {
1843                                         if (implementing.DeclaringType.IsInterface) {
1844                                                 //
1845                                                 // If this is an interface method implementation,
1846                                                 // check for public accessibility
1847                                                 //
1848                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public)
1849                                                 {
1850                                                         implementing = null;
1851                                                 }
1852                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
1853                                                 // We may never be private.
1854                                                 implementing = null;
1855
1856                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0){
1857                                                 //
1858                                                 // We may be protected if we're overriding something.
1859                                                 //
1860                                                 implementing = null;
1861                                         }
1862                                 }
1863                                         
1864                                 //
1865                                 // Static is not allowed
1866                                 //
1867                                 if ((modifiers & Modifiers.STATIC) != 0){
1868                                         implementing = null;
1869                                 }
1870                         }
1871                         
1872                         //
1873                         // If implementing is still valid, set flags
1874                         //
1875                         if (implementing != null){
1876                                 //
1877                                 // When implementing interface methods, set NewSlot
1878                                 // unless, we are overwriting a method.
1879                                 //
1880                                 if (implementing.DeclaringType.IsInterface){
1881                                         if ((modifiers & Modifiers.OVERRIDE) == 0)
1882                                                 flags |= MethodAttributes.NewSlot;
1883                                 }
1884
1885                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
1886
1887                                 // Set Final unless we're virtual, abstract or already overriding a method.
1888                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
1889                                         flags |= MethodAttributes.Final;
1890
1891                                 //
1892                                 // clear the pending implementation flag (requires explicit methods to be defined first)
1893                                 //
1894                                 parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName,
1895                                         member.InterfaceType, this, member.IsExplicitImpl);
1896
1897                                 //
1898                                 // Update indexer accessor name to match implementing abstract accessor
1899                                 //
1900                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
1901                                         method_full_name = implementing.MemberDefinition.Name;
1902                         }
1903
1904                         DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
1905
1906                         if (builder == null)
1907                                 return false;
1908
1909 //                      if (container.CurrentType != null)
1910 //                              declaring_type = container.CurrentType;
1911 //                      else
1912                                 declaring_type = container.Definition;
1913
1914                         if (implementing != null && member.IsExplicitImpl) {
1915                                 container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
1916                         }
1917
1918                         return true;
1919                 }
1920
1921
1922                 /// <summary>
1923                 /// Create the MethodBuilder for the method 
1924                 /// </summary>
1925                 void DefineMethodBuilder (TypeContainer container, string method_name, ParametersCompiled param)
1926                 {
1927                         var return_type = method.ReturnType.GetMetaInfo ();
1928                         var p_types = param.GetMetaInfo ();
1929
1930                         if (builder == null) {
1931                                 builder = container.TypeBuilder.DefineMethod (
1932                                         method_name, flags, method.CallingConventions,
1933                                         return_type, p_types);
1934                                 return;
1935                         }
1936
1937                         //
1938                         // Generic method has been already defined to resolve method parameters
1939                         // correctly when they use type parameters
1940                         //
1941                         builder.SetParameters (p_types);
1942                         builder.SetReturnType (return_type);
1943                         if (builder.Attributes != flags) {
1944 #if STATIC
1945                                 builder.__SetAttributes (flags);
1946 #else
1947                                 try {
1948                                         if (methodbuilder_attrs_field == null)
1949                                                 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
1950                                         methodbuilder_attrs_field.SetValue (builder, flags);
1951                                 } catch {
1952                                         container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
1953                                 }
1954 #endif
1955                         }
1956                 }
1957
1958                 //
1959                 // Emits the code
1960                 // 
1961                 public void Emit (DeclSpace parent)
1962                 {
1963                         if (GenericMethod != null)
1964                                 GenericMethod.EmitAttributes ();
1965
1966                         var mc = (IMemberContext) method;
1967
1968                         method.ParameterInfo.ApplyAttributes (mc, MethodBuilder);
1969
1970                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
1971
1972                         ToplevelBlock block = method.Block;
1973                         if (block != null) {
1974                                 BlockContext bc = new BlockContext (mc, block, method.ReturnType);
1975                                 if (block.Resolve (null, bc, method)) {
1976                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
1977                                         if (!ec.HasReturnLabel && bc.HasReturnLabel) {
1978                                                 ec.ReturnLabel = bc.ReturnLabel;
1979                                                 ec.HasReturnLabel = true;
1980                                         }
1981
1982                                         block.Emit (ec);
1983                                 }
1984                         }
1985
1986                         if (source != null) {
1987                                 method.EmitExtraSymbolInfo (source);
1988                                 source.CloseMethod ();
1989                         }
1990                 }
1991         }
1992
1993         public class Destructor : MethodOrOperator
1994         {
1995                 const Modifiers AllowedModifiers =
1996                         Modifiers.UNSAFE |
1997                         Modifiers.EXTERN;
1998
1999                 static readonly string[] attribute_targets = new string [] { "method" };
2000
2001                 public static readonly string MetadataName = "Finalize";
2002
2003                 public Destructor (DeclSpace parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
2004                         : base (parent, null, null, mod, AllowedModifiers,
2005                                 new MemberName (MetadataName, l), attrs, parameters)
2006                 {
2007                         ModFlags &= ~Modifiers.PRIVATE;
2008                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
2009                 }
2010
2011                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2012                 {
2013                         if (a.Type == pa.Conditional) {
2014                                 Error_ConditionalAttributeIsNotValid ();
2015                                 return;
2016                         }
2017
2018                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2019                 }
2020
2021                 protected override bool CheckBase ()
2022                 {
2023                         // Don't check base, destructors have special syntax
2024                         return true;
2025                 }
2026
2027                 public override void Emit()
2028                 {
2029                         var base_type = Parent.PartialContainer.BaseType;
2030                         if (base_type != null && Block != null) {
2031                                 var base_dtor = MemberCache.FindMember (base_type,
2032                                         new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
2033
2034                                 if (base_dtor == null)
2035                                         throw new NotImplementedException ();
2036
2037                                 MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
2038                                 method_expr.InstanceExpression = new BaseThis (base_type, Location);
2039
2040                                 var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation);
2041                                 var finaly_block = new ExplicitBlock (block, Location, Location);
2042
2043                                 //
2044                                 // 0-size arguments to avoid CS0250 error
2045                                 // TODO: Should use AddScopeStatement or something else which emits correct
2046                                 // debugger scope
2047                                 //
2048                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
2049
2050                                 var tf = new TryFinally (try_block, finaly_block, Location);
2051                                 block.WrapIntoDestructor (tf, try_block);
2052                         }
2053
2054                         base.Emit ();
2055                 }
2056
2057                 public override string GetSignatureForError ()
2058                 {
2059                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
2060                 }
2061
2062                 protected override bool ResolveMemberType ()
2063                 {
2064                         member_type = TypeManager.void_type;
2065                         return true;
2066                 }
2067
2068                 public override string[] ValidAttributeTargets {
2069                         get {
2070                                 return attribute_targets;
2071                         }
2072                 }
2073         }
2074
2075         // Ooouh Martin, templates are missing here.
2076         // When it will be possible move here a lot of child code and template method type.
2077         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
2078                 protected MethodData method_data;
2079                 protected ToplevelBlock block;
2080                 protected SecurityType declarative_security;
2081
2082                 protected readonly string prefix;
2083
2084                 ReturnParameter return_attributes;
2085
2086                 public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2087                         : base (member.Parent, SetupName (prefix, member, loc), attrs)
2088                 {
2089                         this.prefix = prefix;
2090                 }
2091
2092                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2093                 {
2094                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
2095                 }
2096
2097                 public void UpdateName (InterfaceMemberBase member)
2098                 {
2099                         SetMemberName (SetupName (prefix, member, Location));
2100                 }
2101
2102                 #region IMethodData Members
2103
2104                 public ToplevelBlock Block {
2105                         get {
2106                                 return block;
2107                         }
2108
2109                         set {
2110                                 block = value;
2111                         }
2112                 }
2113
2114                 public CallingConventions CallingConventions {
2115                         get {
2116                                 return CallingConventions.Standard;
2117                         }
2118                 }
2119
2120                 public EmitContext CreateEmitContext (ILGenerator ig)
2121                 {
2122                         return new EmitContext (this, ig, ReturnType);
2123                 }
2124
2125                 public bool IsExcluded ()
2126                 {
2127                         return false;
2128                 }
2129
2130                 GenericMethod IMethodData.GenericMethod {
2131                         get {
2132                                 return null;
2133                         }
2134                 }
2135
2136                 public MemberName MethodName {
2137                         get {
2138                                 return MemberName;
2139                         }
2140                 }
2141
2142                 public TypeSpec[] ParameterTypes { 
2143                         get {
2144                                 return ParameterInfo.Types;
2145                         }
2146                 }
2147
2148                 public abstract ParametersCompiled ParameterInfo { get ; }
2149                 public abstract TypeSpec ReturnType { get; }
2150
2151                 #endregion
2152
2153                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2154                 {
2155                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2156                                 Report.Error (1667, a.Location,
2157                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2158                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
2159                                 return;
2160                         }
2161
2162                         if (a.IsValidSecurityAttribute ()) {
2163                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2164                                 return;
2165                         }
2166
2167                         if (a.Target == AttributeTargets.Method) {
2168                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2169                                 return;
2170                         }
2171
2172                         if (a.Target == AttributeTargets.ReturnValue) {
2173                                 if (return_attributes == null)
2174                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2175
2176                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2177                                 return;
2178                         }
2179
2180                         ApplyToExtraTarget (a, ctor, cdata, pa);
2181                 }
2182
2183                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2184                 {
2185                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2186                 }
2187
2188                 // It is not supported for the accessors
2189                 public sealed override bool Define()
2190                 {
2191                         throw new NotSupportedException ();
2192                 }
2193
2194                 public virtual void Emit (DeclSpace parent)
2195                 {
2196                         method_data.Emit (parent);
2197
2198                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2199                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2200                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2201                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2202
2203                         if (ReturnType == InternalType.Dynamic) {
2204                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2205                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
2206                         } else if (ReturnType.HasDynamicElement) {
2207                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2208                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
2209                         }
2210
2211                         if (OptAttributes != null)
2212                                 OptAttributes.Emit ();
2213
2214                         if (declarative_security != null) {
2215                                 foreach (var de in declarative_security) {
2216 #if STATIC
2217                                         method_data.MethodBuilder.__AddDeclarativeSecurity (de);
2218 #else
2219                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2220 #endif
2221                                 }
2222                         }
2223
2224                         block = null;
2225                 }
2226
2227                 public override bool EnableOverloadChecks (MemberCore overload)
2228                 {
2229                         if (overload is MethodCore) {
2230                                 caching_flags |= Flags.MethodOverloadsExist;
2231                                 return true;
2232                         }
2233
2234                         // This can only happen with indexers and it will
2235                         // be catched as indexer difference
2236                         if (overload is AbstractPropertyEventMethod)
2237                                 return true;
2238
2239                         return false;
2240                 }
2241
2242                 public override bool IsClsComplianceRequired()
2243                 {
2244                         return false;
2245                 }
2246
2247                 public MethodSpec Spec { get; protected set; }
2248
2249                 //
2250                 //   Represents header string for documentation comment.
2251                 //
2252                 public override string DocCommentHeader {
2253                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2254                 }
2255
2256                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2257                 { }
2258         }
2259
2260         public class Operator : MethodOrOperator {
2261
2262                 const Modifiers AllowedModifiers =
2263                         Modifiers.PUBLIC |
2264                         Modifiers.UNSAFE |
2265                         Modifiers.EXTERN |
2266                         Modifiers.STATIC;
2267
2268                 public enum OpType : byte {
2269
2270                         // Unary operators
2271                         LogicalNot,
2272                         OnesComplement,
2273                         Increment,
2274                         Decrement,
2275                         True,
2276                         False,
2277
2278                         // Unary and Binary operators
2279                         Addition,
2280                         Subtraction,
2281
2282                         UnaryPlus,
2283                         UnaryNegation,
2284                         
2285                         // Binary operators
2286                         Multiply,
2287                         Division,
2288                         Modulus,
2289                         BitwiseAnd,
2290                         BitwiseOr,
2291                         ExclusiveOr,
2292                         LeftShift,
2293                         RightShift,
2294                         Equality,
2295                         Inequality,
2296                         GreaterThan,
2297                         LessThan,
2298                         GreaterThanOrEqual,
2299                         LessThanOrEqual,
2300
2301                         // Implicit and Explicit
2302                         Implicit,
2303                         Explicit,
2304
2305                         // Just because of enum
2306                         TOP
2307                 };
2308
2309                 public readonly OpType OperatorType;
2310
2311                 static readonly string [] [] names;
2312
2313                 static Operator ()
2314                 {
2315                         names = new string[(int)OpType.TOP][];
2316                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2317                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2318                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2319                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2320                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2321                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2322                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2323                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2324                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2325                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2326                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2327                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2328                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2329                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2330                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2331                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2332                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2333                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2334                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2335                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2336                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2337                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2338                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2339                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2340                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2341                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2342                 }
2343                 
2344                 public Operator (DeclSpace parent, OpType type, FullNamedExpression ret_type,
2345                                  Modifiers mod_flags, ParametersCompiled parameters,
2346                                  ToplevelBlock block, Attributes attrs, Location loc)
2347                         : base (parent, null, ret_type, mod_flags, AllowedModifiers,
2348                                 new MemberName (GetMetadataName (type), loc), attrs, parameters)
2349                 {
2350                         OperatorType = type;
2351                         Block = block;
2352                 }
2353
2354                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2355                 {
2356                         if (a.Type == pa.Conditional) {
2357                                 Error_ConditionalAttributeIsNotValid ();
2358                                 return;
2359                         }
2360
2361                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2362                 }
2363                 
2364                 public override bool Define ()
2365                 {
2366                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2367                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2368                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2369                         }
2370
2371                         if (!base.Define ())
2372                                 return false;
2373
2374                         if (block != null && block.IsIterator) {
2375                                 //
2376                                 // Current method is turned into automatically generated
2377                                 // wrapper which creates an instance of iterator
2378                                 //
2379                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
2380                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2381                         }
2382
2383                         // imlicit and explicit operator of same types are not allowed
2384                         if (OperatorType == OpType.Explicit)
2385                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2386                         else if (OperatorType == OpType.Implicit)
2387                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2388
2389                         TypeSpec declaring_type = Parent.CurrentType;
2390                         TypeSpec return_type = MemberType;
2391                         TypeSpec first_arg_type = ParameterTypes [0];
2392                         
2393                         TypeSpec first_arg_type_unwrap = first_arg_type;
2394                         if (TypeManager.IsNullableType (first_arg_type))
2395                                 first_arg_type_unwrap = TypeManager.GetTypeArguments (first_arg_type) [0];
2396                         
2397                         TypeSpec return_type_unwrap = return_type;
2398                         if (TypeManager.IsNullableType (return_type))
2399                                 return_type_unwrap = TypeManager.GetTypeArguments (return_type) [0];
2400
2401                         //
2402                         // Rules for conversion operators
2403                         //
2404                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2405                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2406                                         Report.Error (555, Location,
2407                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2408                                         return false;
2409                                 }
2410
2411                                 TypeSpec conv_type;
2412                                 if (declaring_type == return_type || declaring_type == return_type_unwrap) {
2413                                         conv_type = first_arg_type;
2414                                 } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
2415                                         conv_type = return_type;
2416                                 } else {
2417                                         Report.Error (556, Location,
2418                                                 "User-defined conversion must convert to or from the enclosing type");
2419                                         return false;
2420                                 }
2421
2422                                 if (conv_type == InternalType.Dynamic) {
2423                                         Report.Error (1964, Location,
2424                                                 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2425                                                 GetSignatureForError ());
2426
2427                                         return false;
2428                                 }
2429
2430                                 if (conv_type.IsInterface) {
2431                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2432                                                 GetSignatureForError ());
2433                                         return false;
2434                                 }
2435
2436                                 if (conv_type.IsClass) {
2437                                         if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
2438                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2439                                                         GetSignatureForError ());
2440                                                 return false;
2441                                         }
2442
2443                                         if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
2444                                                 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2445                                                         GetSignatureForError ());
2446                                                 return false;
2447                                         }
2448                                 }
2449                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2450                                 if (first_arg_type != declaring_type || parameters.Types[1] != TypeManager.int32_type) {
2451                                         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");
2452                                         return false;
2453                                 }
2454                         } else if (parameters.Count == 1) {
2455                                 // Checks for Unary operators
2456
2457                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2458                                         if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
2459                                                 Report.Error (448, Location,
2460                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2461                                                 return false;
2462                                         }
2463                                         if (first_arg_type != declaring_type) {
2464                                                 Report.Error (
2465                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2466                                                 return false;
2467                                         }
2468                                 }
2469
2470                                 if (first_arg_type_unwrap != declaring_type) {
2471                                         Report.Error (562, Location,
2472                                                 "The parameter type of a unary operator must be the containing type");
2473                                         return false;
2474                                 }
2475
2476                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2477                                         if (return_type != TypeManager.bool_type) {
2478                                                 Report.Error (
2479                                                         215, Location,
2480                                                         "The return type of operator True or False " +
2481                                                         "must be bool");
2482                                                 return false;
2483                                         }
2484                                 }
2485
2486                         } else if (first_arg_type_unwrap != declaring_type) {
2487                                 // Checks for Binary operators
2488
2489                                 var second_arg_type = ParameterTypes[1];
2490                                 if (TypeManager.IsNullableType (second_arg_type))
2491                                         second_arg_type = TypeManager.GetTypeArguments (second_arg_type)[0];
2492
2493                                 if (second_arg_type != declaring_type) {
2494                                         Report.Error (563, Location,
2495                                                 "One of the parameters of a binary operator must be the containing type");
2496                                         return false;
2497                                 }
2498                         }
2499
2500                         return true;
2501                 }
2502
2503                 protected override bool ResolveMemberType ()
2504                 {
2505                         if (!base.ResolveMemberType ())
2506                                 return false;
2507
2508                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2509                         return true;
2510                 }
2511
2512                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate)
2513                 {
2514                         // Operator cannot be override
2515                         bestCandidate = null;
2516                         return null;
2517                 }
2518
2519                 public static string GetName (OpType ot)
2520                 {
2521                         return names [(int) ot] [0];
2522                 }
2523
2524                 public static string GetName (string metadata_name)
2525                 {
2526                         for (int i = 0; i < names.Length; ++i) {
2527                                 if (names [i] [1] == metadata_name)
2528                                         return names [i] [0];
2529                         }
2530                         return null;
2531                 }
2532
2533                 public static string GetMetadataName (OpType ot)
2534                 {
2535                         return names [(int) ot] [1];
2536                 }
2537
2538                 public static string GetMetadataName (string name)
2539                 {
2540                         for (int i = 0; i < names.Length; ++i) {
2541                                 if (names [i] [0] == name)
2542                                         return names [i] [1];
2543                         }
2544                         return null;
2545                 }
2546
2547                 public static OpType? GetType (string metadata_name)
2548                 {
2549                         for (int i = 0; i < names.Length; ++i) {
2550                                 if (names[i][1] == metadata_name)
2551                                         return (OpType) i;
2552                         }
2553
2554                         return null;
2555                 }
2556
2557                 public OpType GetMatchingOperator ()
2558                 {
2559                         switch (OperatorType) {
2560                         case OpType.Equality:
2561                                 return OpType.Inequality;
2562                         case OpType.Inequality:
2563                                 return OpType.Equality;
2564                         case OpType.True:
2565                                 return OpType.False;
2566                         case OpType.False:
2567                                 return OpType.True;
2568                         case OpType.GreaterThan:
2569                                 return OpType.LessThan;
2570                         case OpType.LessThan:
2571                                 return OpType.GreaterThan;
2572                         case OpType.GreaterThanOrEqual:
2573                                 return OpType.LessThanOrEqual;
2574                         case OpType.LessThanOrEqual:
2575                                 return OpType.GreaterThanOrEqual;
2576                         default:
2577                                 return OpType.TOP;
2578                         }
2579                 }
2580
2581                 public override string GetSignatureForError ()
2582                 {
2583                         StringBuilder sb = new StringBuilder ();
2584                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2585                                 sb.AppendFormat ("{0}.{1} operator {2}",
2586                                         Parent.GetSignatureForError (), GetName (OperatorType), type_expr.GetSignatureForError ());
2587                         }
2588                         else {
2589                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2590                         }
2591
2592                         sb.Append (parameters.GetSignatureForError ());
2593                         return sb.ToString ();
2594                 }
2595         }
2596 }
2597