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