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