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