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