Rework top-level type AST hierarchy to include namespaces. Allows MD to iterate full...
[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                 protected SourceMethod (TypeDefinition parent, MethodBase method, ICompileUnit file)
790                 {
791                         this.method = method;
792
793                         TypeContainer ns = parent.Parent;
794                         while (ns != null && !(ns is NamespaceContainer))
795                                 ns = ns.Parent;
796
797                         builder = SymbolWriter.OpenMethod (file, ns == null ? -1 : ((NamespaceContainer) ns).SymbolFileID, this);
798                 }
799
800                 public string Name {
801                         get { return method.Name; }
802                 }
803
804                 public int Token {
805                         get {
806                                 MethodToken token;
807                                 var mb = method as MethodBuilder;
808                                 if (mb != null)
809                                         token = mb.GetToken ();
810                                 else
811                                         token = ((ConstructorBuilder) method).GetToken ();
812 #if STATIC
813                                 if (token.IsPseudoToken)
814                                         return ((ModuleBuilder) method.Module).ResolvePseudoToken (token.Token);
815 #endif
816                                 return token.Token;
817                         }
818                 }
819
820                 public void CloseMethod ()
821                 {
822                         SymbolWriter.CloseMethod ();
823                 }
824
825                 public void SetRealMethodName (string name)
826                 {
827                         if (builder != null)
828                                 builder.SetRealMethodName (name);
829                 }
830
831                 public static SourceMethod Create (TypeDefinition parent, MethodBase method, Block block)
832                 {
833                         if (!SymbolWriter.HasSymbolWriter)
834                                 return null;
835                         if (block == null)
836                                 return null;
837
838                         Location start_loc = block.StartLocation;
839                         if (start_loc.IsNull)
840                                 return null;
841
842                         ICompileUnit compile_unit = start_loc.CompilationUnit;
843                         if (compile_unit == null)
844                                 return null;
845
846                         return new SourceMethod (parent, method, compile_unit);
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                         // TODO: It can be deleted when members will be defined in correct order
1365                         if (overload is Operator)
1366                                 return overload.EnableOverloadChecks (this);
1367
1368                         if (overload is Indexer)
1369                                 return false;
1370
1371                         return base.EnableOverloadChecks (overload);
1372                 }
1373
1374                 public static void Error1599 (Location loc, TypeSpec t, Report Report)
1375                 {
1376                         Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
1377                 }
1378
1379                 protected override bool ResolveMemberType ()
1380                 {
1381                         if (CurrentTypeParameters != null) {
1382                                 MethodBuilder = Parent.TypeBuilder.DefineMethod (GetFullName (MemberName), flags);
1383                                 CreateTypeParameters ();
1384                         }
1385
1386                         return base.ResolveMemberType ();
1387                 }
1388
1389                 public void SetPartialDefinition (Method methodDefinition)
1390                 {
1391                         caching_flags |= Flags.PartialDefinitionExists;
1392                         methodDefinition.partialMethodImplementation = this;
1393
1394                         // Ensure we are always using method declaration parameters
1395                         for (int i = 0; i < methodDefinition.parameters.Count; ++i ) {
1396                                 parameters [i].Name = methodDefinition.parameters [i].Name;
1397                                 parameters [i].DefaultValue = methodDefinition.parameters [i].DefaultValue;
1398                         }
1399
1400                         if (methodDefinition.attributes == null)
1401                                 return;
1402
1403                         if (attributes == null) {
1404                                 attributes = methodDefinition.attributes;
1405                         } else {
1406                                 attributes.Attrs.AddRange (methodDefinition.attributes.Attrs);
1407                         }
1408                 }
1409         }
1410
1411         public abstract class ConstructorInitializer : ExpressionStatement
1412         {
1413                 Arguments argument_list;
1414                 MethodSpec base_ctor;
1415
1416                 public ConstructorInitializer (Arguments argument_list, Location loc)
1417                 {
1418                         this.argument_list = argument_list;
1419                         this.loc = loc;
1420                 }
1421
1422                 public Arguments Arguments {
1423                         get {
1424                                 return argument_list;
1425                         }
1426                 }
1427
1428                 public override bool ContainsEmitWithAwait ()
1429                 {
1430                         throw new NotSupportedException ();
1431                 }
1432
1433                 public override Expression CreateExpressionTree (ResolveContext ec)
1434                 {
1435                         throw new NotSupportedException ("ET");
1436                 }
1437
1438                 protected override Expression DoResolve (ResolveContext ec)
1439                 {
1440                         eclass = ExprClass.Value;
1441
1442                         // FIXME: Hack
1443                         var caller_builder = (Constructor) ec.MemberContext;
1444
1445                         //
1446                         // Spec mandates that constructor initializer will not have `this' access
1447                         //
1448                         using (ec.Set (ResolveContext.Options.BaseInitializer)) {
1449                                 if (argument_list != null) {
1450                                         bool dynamic;
1451                                         argument_list.Resolve (ec, out dynamic);
1452
1453                                         if (dynamic) {
1454                                                 ec.Report.Error (1975, loc,
1455                                                         "The constructor call cannot be dynamically dispatched within constructor initializer");
1456
1457                                                 return null;
1458                                         }
1459                                 }
1460
1461                                 type = ec.CurrentType;
1462                                 if (this is ConstructorBaseInitializer) {
1463                                         if (ec.CurrentType.BaseType == null)
1464                                                 return this;
1465
1466                                         type = ec.CurrentType.BaseType;
1467                                         if (ec.CurrentType.IsStruct) {
1468                                                 ec.Report.Error (522, loc,
1469                                                         "`{0}': Struct constructors cannot call base constructors", caller_builder.GetSignatureForError ());
1470                                                 return this;
1471                                         }
1472                                 } else {
1473                                         //
1474                                         // It is legal to have "this" initializers that take no arguments
1475                                         // in structs, they are just no-ops.
1476                                         //
1477                                         // struct D { public D (int a) : this () {}
1478                                         //
1479                                         if (ec.CurrentType.IsStruct && argument_list == null)
1480                                                 return this;
1481                                 }
1482
1483                                 base_ctor = ConstructorLookup (ec, type, ref argument_list, loc);
1484                         }
1485         
1486                         // TODO MemberCache: Does it work for inflated types ?
1487                         if (base_ctor == caller_builder.Spec){
1488                                 ec.Report.Error (516, loc, "Constructor `{0}' cannot call itself",
1489                                         caller_builder.GetSignatureForError ());
1490                         }
1491                                                 
1492                         return this;
1493                 }
1494
1495                 public override void Emit (EmitContext ec)
1496                 {
1497                         // It can be null for static initializers
1498                         if (base_ctor == null)
1499                                 return;
1500                         
1501                         ec.Mark (loc);
1502
1503                         var call = new CallEmitter ();
1504                         call.InstanceExpression = new CompilerGeneratedThis (type, loc); 
1505                         call.EmitPredefined (ec, base_ctor, argument_list);
1506                 }
1507
1508                 public override void EmitStatement (EmitContext ec)
1509                 {
1510                         Emit (ec);
1511                 }
1512         }
1513
1514         public class ConstructorBaseInitializer : ConstructorInitializer {
1515                 public ConstructorBaseInitializer (Arguments argument_list, Location l) :
1516                         base (argument_list, l)
1517                 {
1518                 }
1519         }
1520
1521         class GeneratedBaseInitializer: ConstructorBaseInitializer {
1522                 public GeneratedBaseInitializer (Location loc):
1523                         base (null, loc)
1524                 {
1525                 }
1526         }
1527
1528         public class ConstructorThisInitializer : ConstructorInitializer {
1529                 public ConstructorThisInitializer (Arguments argument_list, Location l) :
1530                         base (argument_list, l)
1531                 {
1532                 }
1533         }
1534         
1535         public class Constructor : MethodCore, IMethodData {
1536                 public ConstructorBuilder ConstructorBuilder;
1537                 public ConstructorInitializer Initializer;
1538                 SecurityType declarative_security;
1539                 bool has_compliant_args;
1540
1541                 // <summary>
1542                 //   Modifiers allowed for a constructor.
1543                 // </summary>
1544                 public const Modifiers AllowedModifiers =
1545                         Modifiers.PUBLIC |
1546                         Modifiers.PROTECTED |
1547                         Modifiers.INTERNAL |
1548                         Modifiers.STATIC |
1549                         Modifiers.UNSAFE |
1550                         Modifiers.EXTERN |              
1551                         Modifiers.PRIVATE;
1552
1553                 static readonly string[] attribute_targets = new string [] { "method" };
1554
1555                 public static readonly string ConstructorName = ".ctor";
1556                 public static readonly string TypeConstructorName = ".cctor";
1557
1558                 public Constructor (TypeDefinition parent, string name, Modifiers mod, Attributes attrs, ParametersCompiled args, Location loc)
1559                         : base (parent, null, mod, AllowedModifiers, new MemberName (name, loc), attrs, args)
1560                 {
1561                 }
1562
1563                 public bool HasCompliantArgs {
1564                         get {
1565                                 return has_compliant_args;
1566                         }
1567                 }
1568
1569                 public override AttributeTargets AttributeTargets {
1570                         get {
1571                                 return AttributeTargets.Constructor;
1572                         }
1573                 }
1574
1575                 bool IMethodData.IsAccessor {
1576                         get {
1577                                 return false;
1578                         }
1579                 }
1580
1581                 //
1582                 // Returns true if this is a default constructor
1583                 //
1584                 public bool IsDefault ()
1585                 {
1586                         if ((ModFlags & Modifiers.STATIC) != 0)
1587                                 return parameters.IsEmpty;
1588
1589                         return parameters.IsEmpty &&
1590                                         (Initializer is ConstructorBaseInitializer) &&
1591                                         (Initializer.Arguments == null);
1592                 }
1593
1594                 public override void Accept (StructuralVisitor visitor)
1595                 {
1596                         visitor.Visit (this);
1597                 }
1598
1599                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
1600                 {
1601                         if (a.IsValidSecurityAttribute ()) {
1602                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
1603                                 return;
1604                         }
1605
1606                         if (a.Type == pa.MethodImpl) {
1607                                 is_external_implementation = a.IsInternalCall ();
1608                         }
1609
1610                         ConstructorBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
1611                 }
1612
1613                 protected override bool CheckBase ()
1614                 {
1615                         if ((ModFlags & Modifiers.STATIC) != 0) {
1616                                 if (!parameters.IsEmpty) {
1617                                         Report.Error (132, Location, "`{0}': The static constructor must be parameterless",
1618                                                 GetSignatureForError ());
1619                                         return false;
1620                                 }
1621
1622                                 // the rest can be ignored
1623                                 return true;
1624                         }
1625
1626                         // Check whether arguments were correct.
1627                         if (!DefineParameters (parameters))
1628                                 return false;
1629
1630                         if ((caching_flags & Flags.MethodOverloadsExist) != 0)
1631                                 Parent.MemberCache.CheckExistingMembersOverloads (this, parameters);
1632
1633                         if (Parent.PartialContainer.Kind == MemberKind.Struct && parameters.IsEmpty) {
1634                                 Report.Error (568, Location, 
1635                                         "Structs cannot contain explicit parameterless constructors");
1636                                 return false;
1637                         }
1638
1639                         CheckProtectedModifier ();
1640                         
1641                         return true;
1642                 }
1643                 
1644                 //
1645                 // Creates the ConstructorBuilder
1646                 //
1647                 public override bool Define ()
1648                 {
1649                         if (ConstructorBuilder != null)
1650                                 return true;
1651
1652                         var ca = MethodAttributes.RTSpecialName | MethodAttributes.SpecialName;
1653                         
1654                         if ((ModFlags & Modifiers.STATIC) != 0) {
1655                                 ca |= MethodAttributes.Static | MethodAttributes.Private;
1656                         } else {
1657                                 ca |= ModifiersExtensions.MethodAttr (ModFlags);
1658                         }
1659
1660                         if (!CheckAbstractAndExtern (block != null))
1661                                 return false;
1662                         
1663                         // Check if arguments were correct.
1664                         if (!CheckBase ())
1665                                 return false;
1666
1667                         ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
1668                                 ca, CallingConventions,
1669                                 parameters.GetMetaInfo ());
1670
1671                         spec = new MethodSpec (MemberKind.Constructor, Parent.Definition, this, Compiler.BuiltinTypes.Void, ConstructorBuilder, parameters, ModFlags);
1672                         
1673                         Parent.MemberCache.AddMember (spec);
1674                         
1675                         // It's here only to report an error
1676                         if (block != null && block.IsIterator) {
1677                                 member_type = Compiler.BuiltinTypes.Void;
1678                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
1679                         }
1680
1681                         return true;
1682                 }
1683
1684                 //
1685                 // Emits the code
1686                 //
1687                 public override void Emit ()
1688                 {
1689                         if (Parent.PartialContainer.IsComImport) {
1690                                 if (!IsDefault ()) {
1691                                         Report.Error (669, Location, "`{0}': A class with the ComImport attribute cannot have a user-defined constructor",
1692                                                 Parent.GetSignatureForError ());
1693                                 }
1694
1695                                 // Set as internal implementation and reset block data
1696                                 // to ensure no IL is generated
1697                                 ConstructorBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall);
1698                                 block = null;
1699                         }
1700
1701                         if ((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1702                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (ConstructorBuilder);
1703
1704                         if (OptAttributes != null)
1705                                 OptAttributes.Emit ();
1706
1707                         base.Emit ();
1708                         parameters.ApplyAttributes (this, ConstructorBuilder);
1709
1710                         //
1711                         // If we use a "this (...)" constructor initializer, then
1712                         // do not emit field initializers, they are initialized in the other constructor
1713                         //
1714                         bool emit_field_initializers = ((ModFlags & Modifiers.STATIC) != 0) ||
1715                                 !(Initializer is ConstructorThisInitializer);
1716
1717                         BlockContext bc = new BlockContext (this, block, Compiler.BuiltinTypes.Void);
1718                         bc.Set (ResolveContext.Options.ConstructorScope);
1719
1720                         if (emit_field_initializers)
1721                                 Parent.PartialContainer.ResolveFieldInitializers (bc);
1722
1723                         if (block != null) {
1724                                 // If this is a non-static `struct' constructor and doesn't have any
1725                                 // initializer, it must initialize all of the struct's fields.
1726                                 if ((Parent.PartialContainer.Kind == MemberKind.Struct) &&
1727                                         ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
1728                                         block.AddThisVariable (bc);
1729
1730                                 if ((ModFlags & Modifiers.STATIC) == 0){
1731                                         if (Parent.PartialContainer.Kind == MemberKind.Class && Initializer == null)
1732                                                 Initializer = new GeneratedBaseInitializer (Location);
1733
1734                                         if (Initializer != null) {
1735                                                 block.AddScopeStatement (new StatementExpression (Initializer));
1736                                         }
1737                                 }
1738                         }
1739
1740                         SourceMethod source = SourceMethod.Create (Parent, ConstructorBuilder, block);
1741
1742                         if (block != null) {
1743                                 if (block.Resolve (null, bc, this)) {
1744                                         EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType);
1745                                         ec.With (EmitContext.Options.ConstructorScope, true);
1746
1747                                         block.Emit (ec);
1748                                 }
1749                         }
1750
1751                         if (source != null)
1752                                 source.CloseMethod ();
1753
1754                         if (declarative_security != null) {
1755                                 foreach (var de in declarative_security) {
1756 #if STATIC
1757                                         ConstructorBuilder.__AddDeclarativeSecurity (de);
1758 #else
1759                                         ConstructorBuilder.AddDeclarativeSecurity (de.Key, de.Value);
1760 #endif
1761                                 }
1762                         }
1763
1764                         block = null;
1765                 }
1766
1767                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
1768                 {
1769                         // Is never override
1770                         bestCandidate = null;
1771                         return null;
1772                 }
1773
1774                 public override string GetSignatureForDocumentation ()
1775                 {
1776                         return Parent.GetSignatureForDocumentation () + ".#ctor" + parameters.GetSignatureForDocumentation ();
1777                 }
1778
1779                 public override string GetSignatureForError()
1780                 {
1781                         return base.GetSignatureForError () + parameters.GetSignatureForError ();
1782                 }
1783
1784                 public override string[] ValidAttributeTargets {
1785                         get {
1786                                 return attribute_targets;
1787                         }
1788                 }
1789
1790                 protected override bool VerifyClsCompliance ()
1791                 {
1792                         if (!base.VerifyClsCompliance () || !IsExposedFromAssembly ()) {
1793                                 return false;
1794                         }
1795
1796                         if (!parameters.IsEmpty && Parent.Definition.IsAttribute) {
1797                                 foreach (TypeSpec param in parameters.Types) {
1798                                         if (param.IsArray) {
1799                                                 return true;
1800                                         }
1801                                 }
1802                         }
1803
1804                         has_compliant_args = true;
1805                         return true;
1806                 }
1807
1808                 #region IMethodData Members
1809
1810                 public MemberName MethodName {
1811                         get {
1812                                 return MemberName;
1813                         }
1814                 }
1815
1816                 public TypeSpec ReturnType {
1817                         get {
1818                                 return MemberType;
1819                         }
1820                 }
1821
1822                 public EmitContext CreateEmitContext (ILGenerator ig)
1823                 {
1824                         throw new NotImplementedException ();
1825                 }
1826
1827                 public bool IsExcluded()
1828                 {
1829                         return false;
1830                 }
1831
1832                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
1833                 { }
1834
1835                 #endregion
1836         }
1837
1838         /// <summary>
1839         /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
1840         /// </summary>
1841         public interface IMethodData : IMemberContext
1842         {
1843                 CallingConventions CallingConventions { get; }
1844                 Location Location { get; }
1845                 MemberName MethodName { get; }
1846                 TypeSpec ReturnType { get; }
1847                 ParametersCompiled ParameterInfo { get; }
1848                 MethodSpec Spec { get; }
1849                 bool IsAccessor { get; }
1850
1851                 Attributes OptAttributes { get; }
1852                 ToplevelBlock Block { get; set; }
1853
1854                 EmitContext CreateEmitContext (ILGenerator ig);
1855                 void EmitExtraSymbolInfo (SourceMethod source);
1856         }
1857
1858         //
1859         // Encapsulates most of the Method's state
1860         //
1861         public class MethodData
1862         {
1863 #if !STATIC
1864                 static FieldInfo methodbuilder_attrs_field;
1865 #endif
1866
1867                 public readonly IMethodData method;
1868
1869                 //
1870                 // Are we implementing an interface ?
1871                 //
1872                 public MethodSpec implementing;
1873
1874                 //
1875                 // Protected data.
1876                 //
1877                 protected InterfaceMemberBase member;
1878                 protected Modifiers modifiers;
1879                 protected MethodAttributes flags;
1880                 protected TypeSpec declaring_type;
1881                 protected MethodSpec parent_method;
1882
1883                 MethodBuilder builder;
1884                 public MethodBuilder MethodBuilder {
1885                         get {
1886                                 return builder;
1887                         }
1888                 }
1889
1890                 public TypeSpec DeclaringType {
1891                         get {
1892                                 return declaring_type;
1893                         }
1894                 }
1895
1896                 public MethodData (InterfaceMemberBase member,
1897                                    Modifiers modifiers, MethodAttributes flags, IMethodData method)
1898                 {
1899                         this.member = member;
1900                         this.modifiers = modifiers;
1901                         this.flags = flags;
1902
1903                         this.method = method;
1904                 }
1905
1906                 public MethodData (InterfaceMemberBase member,
1907                                    Modifiers modifiers, MethodAttributes flags, 
1908                                    IMethodData method, MethodBuilder builder,
1909                                    //GenericMethod generic, 
1910                                    MethodSpec parent_method)
1911                         : this (member, modifiers, flags, method)
1912                 {
1913                         this.builder = builder;
1914                         //this.GenericMethod = generic;
1915                         this.parent_method = parent_method;
1916                 }
1917
1918                 public bool Define (TypeDefinition container, string method_full_name)
1919                 {
1920                         PendingImplementation pending = container.PendingImplementations;
1921                         MethodSpec ambig_iface_method;
1922                         bool optional = false;
1923
1924                         if (pending != null) {
1925                                 implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional);
1926
1927                                 if (member.InterfaceType != null) {
1928                                         if (implementing == null) {
1929                                                 if (member is PropertyBase) {
1930                                                         container.Compiler.Report.Error (550, method.Location,
1931                                                                 "`{0}' is an accessor not found in interface member `{1}{2}'",
1932                                                                           method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
1933                                                                           member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
1934
1935                                                 } else {
1936                                                         container.Compiler.Report.Error (539, method.Location,
1937                                                                           "`{0}.{1}' in explicit interface declaration is not a member of interface",
1938                                                                           TypeManager.CSharpName (member.InterfaceType), member.ShortName);
1939                                                 }
1940                                                 return false;
1941                                         }
1942                                         if (implementing.IsAccessor && !method.IsAccessor) {
1943                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1944                                                 container.Compiler.Report.Error (683, method.Location,
1945                                                         "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
1946                                                         member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1947                                                 return false;
1948                                         }
1949                                 } else {
1950                                         if (implementing != null) {
1951                                                 if (!method.IsAccessor) {
1952                                                         if (implementing.IsAccessor) {
1953                                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1954                                                                 container.Compiler.Report.Error (470, method.Location,
1955                                                                         "Method `{0}' cannot implement interface accessor `{1}'",
1956                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
1957                                                         }
1958                                                 } else if (implementing.DeclaringType.IsInterface) {
1959                                                         if (!implementing.IsAccessor) {
1960                                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1961                                                                 container.Compiler.Report.Error (686, method.Location,
1962                                                                         "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
1963                                                                         method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
1964                                                         } else {
1965                                                                 PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod;
1966                                                                 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
1967                                                                         container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1968                                                                         container.Compiler.Report.Error (277, method.Location,
1969                                                                                 "Accessor `{0}' must be declared public to implement interface member `{1}'",
1970                                                                                 method.GetSignatureForError (), implementing.GetSignatureForError ());
1971                                                                 }
1972                                                         }
1973                                                 }
1974                                         }
1975                                 }
1976                         } else {
1977                                 ambig_iface_method = null;
1978                         }
1979
1980                         //
1981                         // For implicit implementations, make sure we are public, for
1982                         // explicit implementations, make sure we are private.
1983                         //
1984                         if (implementing != null){
1985                                 if (member.IsExplicitImpl) {
1986                                         if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) {
1987                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1988                                                 container.Compiler.Report.Error (466, method.Location,
1989                                                         "`{0}': the explicit interface implementation cannot introduce the params modifier",
1990                                                         method.GetSignatureForError ());
1991                                         }
1992
1993                                         if (ambig_iface_method != null) {
1994                                                 container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method);
1995                                                 container.Compiler.Report.SymbolRelatedToPreviousError (implementing);
1996                                                 container.Compiler.Report.Warning (473, 2, method.Location,
1997                                                         "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead",
1998                                                         method.GetSignatureForError ());
1999                                         }
2000                                 } else {
2001                                         //
2002                                         // Setting implementin to null inside this block will trigger a more
2003                                         // verbose error reporting for missing interface implementations
2004                                         //
2005                                         if (implementing.DeclaringType.IsInterface) {
2006                                                 //
2007                                                 // If this is an interface method implementation,
2008                                                 // check for public accessibility
2009                                                 //
2010                                                 if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) {
2011                                                         implementing = null;
2012                                                 } else if (optional && (container.Interfaces == null || Array.IndexOf (container.Interfaces, implementing.DeclaringType) < 0)) {
2013                                                         //
2014                                                         // We are not implementing interface when base class already implemented it
2015                                                         //
2016                                                         implementing = null;
2017                                                 }
2018                                         } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) {
2019                                                 // We may never be private.
2020                                                 implementing = null;
2021
2022                                         } else if ((modifiers & Modifiers.OVERRIDE) == 0) {
2023                                                 //
2024                                                 // We may be protected if we're overriding something.
2025                                                 //
2026                                                 implementing = null;
2027                                         }
2028                                 }
2029                                         
2030                                 //
2031                                 // Static is not allowed
2032                                 //
2033                                 if ((modifiers & Modifiers.STATIC) != 0){
2034                                         implementing = null;
2035                                 }
2036                         }
2037                         
2038                         //
2039                         // If implementing is still valid, set flags
2040                         //
2041                         if (implementing != null){
2042                                 //
2043                                 // When implementing interface methods, set NewSlot
2044                                 // unless, we are overwriting a method.
2045                                 //
2046                                 if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) {
2047                                         flags |= MethodAttributes.NewSlot;
2048                                 }
2049
2050                                 flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig;
2051
2052                                 // Set Final unless we're virtual, abstract or already overriding a method.
2053                                 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
2054                                         flags |= MethodAttributes.Final;
2055
2056                                 //
2057                                 // clear the pending implementation flag (requires explicit methods to be defined first)
2058                                 //
2059                                 pending.ImplementMethod (method.MethodName,
2060                                         member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional);
2061
2062                                 //
2063                                 // Update indexer accessor name to match implementing abstract accessor
2064                                 //
2065                                 if (!implementing.DeclaringType.IsInterface && !member.IsExplicitImpl && implementing.IsAccessor)
2066                                         method_full_name = implementing.MemberDefinition.Name;
2067                         }
2068
2069                         DefineMethodBuilder (container, method_full_name, method.ParameterInfo);
2070
2071                         if (builder == null)
2072                                 return false;
2073
2074 //                      if (container.CurrentType != null)
2075 //                              declaring_type = container.CurrentType;
2076 //                      else
2077                                 declaring_type = container.Definition;
2078
2079                         if (implementing != null && member.IsExplicitImpl) {
2080                                 container.TypeBuilder.DefineMethodOverride (builder, (MethodInfo) implementing.GetMetaInfo ());
2081                         }
2082
2083                         return true;
2084                 }
2085
2086
2087                 /// <summary>
2088                 /// Create the MethodBuilder for the method 
2089                 /// </summary>
2090                 void DefineMethodBuilder (TypeDefinition container, string method_name, ParametersCompiled param)
2091                 {
2092                         var return_type = method.ReturnType.GetMetaInfo ();
2093                         var p_types = param.GetMetaInfo ();
2094
2095                         if (builder == null) {
2096                                 builder = container.TypeBuilder.DefineMethod (
2097                                         method_name, flags, method.CallingConventions,
2098                                         return_type, p_types);
2099                                 return;
2100                         }
2101
2102                         //
2103                         // Generic method has been already defined to resolve method parameters
2104                         // correctly when they use type parameters
2105                         //
2106                         builder.SetParameters (p_types);
2107                         builder.SetReturnType (return_type);
2108                         if (builder.Attributes != flags) {
2109 #if STATIC
2110                                 builder.__SetAttributes (flags);
2111 #else
2112                                 try {
2113                                         if (methodbuilder_attrs_field == null)
2114                                                 methodbuilder_attrs_field = typeof (MethodBuilder).GetField ("attrs", BindingFlags.NonPublic | BindingFlags.Instance);
2115                                         methodbuilder_attrs_field.SetValue (builder, flags);
2116                                 } catch {
2117                                         container.Compiler.Report.RuntimeMissingSupport (method.Location, "Generic method MethodAttributes");
2118                                 }
2119 #endif
2120                         }
2121                 }
2122
2123                 //
2124                 // Emits the code
2125                 // 
2126                 public void Emit (TypeDefinition parent)
2127                 {
2128                         var mc = (IMemberContext) method;
2129
2130                         method.ParameterInfo.ApplyAttributes (mc, MethodBuilder);
2131
2132                         SourceMethod source = SourceMethod.Create (parent, MethodBuilder, method.Block);
2133
2134                         ToplevelBlock block = method.Block;
2135                         if (block != null) {
2136                                 BlockContext bc = new BlockContext (mc, block, method.ReturnType);
2137                                 if (block.Resolve (null, bc, method)) {
2138                                         EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ());
2139
2140                                         block.Emit (ec);
2141                                 }
2142                         }
2143
2144                         if (source != null) {
2145                                 method.EmitExtraSymbolInfo (source);
2146                                 source.CloseMethod ();
2147                         }
2148                 }
2149         }
2150
2151         public class Destructor : MethodOrOperator
2152         {
2153                 const Modifiers AllowedModifiers =
2154                         Modifiers.UNSAFE |
2155                         Modifiers.EXTERN;
2156
2157                 static readonly string[] attribute_targets = new string [] { "method" };
2158
2159                 public static readonly string MetadataName = "Finalize";
2160
2161                 public Destructor (TypeDefinition parent, Modifiers mod, ParametersCompiled parameters, Attributes attrs, Location l)
2162                         : base (parent, null, mod, AllowedModifiers, new MemberName (MetadataName, l), attrs, parameters)
2163                 {
2164                         ModFlags &= ~Modifiers.PRIVATE;
2165                         ModFlags |= Modifiers.PROTECTED | Modifiers.OVERRIDE;
2166                 }
2167
2168                 public override void Accept (StructuralVisitor visitor)
2169                 {
2170                         visitor.Visit (this);
2171                 }
2172
2173                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2174                 {
2175                         if (a.Type == pa.Conditional) {
2176                                 Error_ConditionalAttributeIsNotValid ();
2177                                 return;
2178                         }
2179
2180                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2181                 }
2182
2183                 protected override bool CheckBase ()
2184                 {
2185                         // Don't check base, destructors have special syntax
2186                         return true;
2187                 }
2188
2189                 public override void Emit()
2190                 {
2191                         var base_type = Parent.PartialContainer.BaseType;
2192                         if (base_type != null && Block != null) {
2193                                 var base_dtor = MemberCache.FindMember (base_type,
2194                                         new MemberFilter (MetadataName, 0, MemberKind.Destructor, null, null), BindingRestriction.InstanceOnly) as MethodSpec;
2195
2196                                 if (base_dtor == null)
2197                                         throw new NotImplementedException ();
2198
2199                                 MethodGroupExpr method_expr = MethodGroupExpr.CreatePredefined (base_dtor, base_type, Location);
2200                                 method_expr.InstanceExpression = new BaseThis (base_type, Location);
2201
2202                                 var try_block = new ExplicitBlock (block, block.StartLocation, block.EndLocation);
2203                                 var finaly_block = new ExplicitBlock (block, Location, Location);
2204
2205                                 //
2206                                 // 0-size arguments to avoid CS0250 error
2207                                 // TODO: Should use AddScopeStatement or something else which emits correct
2208                                 // debugger scope
2209                                 //
2210                                 finaly_block.AddStatement (new StatementExpression (new Invocation (method_expr, new Arguments (0))));
2211
2212                                 var tf = new TryFinally (try_block, finaly_block, Location);
2213                                 block.WrapIntoDestructor (tf, try_block);
2214                         }
2215
2216                         base.Emit ();
2217                 }
2218
2219                 public override string GetSignatureForError ()
2220                 {
2221                         return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
2222                 }
2223
2224                 protected override bool ResolveMemberType ()
2225                 {
2226                         member_type = Compiler.BuiltinTypes.Void;
2227                         return true;
2228                 }
2229
2230                 public override string[] ValidAttributeTargets {
2231                         get {
2232                                 return attribute_targets;
2233                         }
2234                 }
2235         }
2236
2237         // Ooouh Martin, templates are missing here.
2238         // When it will be possible move here a lot of child code and template method type.
2239         public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
2240                 protected MethodData method_data;
2241                 protected ToplevelBlock block;
2242                 protected SecurityType declarative_security;
2243
2244                 protected readonly string prefix;
2245
2246                 ReturnParameter return_attributes;
2247
2248                 public AbstractPropertyEventMethod (InterfaceMemberBase member, string prefix, Attributes attrs, Location loc)
2249                         : base (member.Parent, SetupName (prefix, member, loc), attrs)
2250                 {
2251                         this.prefix = prefix;
2252                 }
2253
2254                 static MemberName SetupName (string prefix, InterfaceMemberBase member, Location loc)
2255                 {
2256                         return new MemberName (member.MemberName.Left, prefix + member.ShortName, member.MemberName.ExplicitInterface, loc);
2257                 }
2258
2259                 public void UpdateName (InterfaceMemberBase member)
2260                 {
2261                         SetMemberName (SetupName (prefix, member, Location));
2262                 }
2263
2264                 #region IMethodData Members
2265
2266                 public ToplevelBlock Block {
2267                         get {
2268                                 return block;
2269                         }
2270
2271                         set {
2272                                 block = value;
2273                         }
2274                 }
2275
2276                 public CallingConventions CallingConventions {
2277                         get {
2278                                 return CallingConventions.Standard;
2279                         }
2280                 }
2281
2282                 public EmitContext CreateEmitContext (ILGenerator ig)
2283                 {
2284                         return new EmitContext (this, ig, ReturnType);
2285                 }
2286
2287                 public bool IsAccessor {
2288                         get {
2289                                 return true;
2290                         }
2291                 }
2292
2293                 public bool IsExcluded ()
2294                 {
2295                         return false;
2296                 }
2297
2298                 public MemberName MethodName {
2299                         get {
2300                                 return MemberName;
2301                         }
2302                 }
2303
2304                 public TypeSpec[] ParameterTypes { 
2305                         get {
2306                                 return ParameterInfo.Types;
2307                         }
2308                 }
2309
2310                 public abstract ParametersCompiled ParameterInfo { get ; }
2311                 public abstract TypeSpec ReturnType { get; }
2312
2313                 #endregion
2314
2315                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2316                 {
2317                         if (a.Type == pa.CLSCompliant || a.Type == pa.Obsolete || a.Type == pa.Conditional) {
2318                                 Report.Error (1667, a.Location,
2319                                         "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
2320                                         TypeManager.CSharpName (a.Type), a.GetValidTargets ());
2321                                 return;
2322                         }
2323
2324                         if (a.IsValidSecurityAttribute ()) {
2325                                 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2326                                 return;
2327                         }
2328
2329                         if (a.Target == AttributeTargets.Method) {
2330                                 method_data.MethodBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
2331                                 return;
2332                         }
2333
2334                         if (a.Target == AttributeTargets.ReturnValue) {
2335                                 if (return_attributes == null)
2336                                         return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2337
2338                                 return_attributes.ApplyAttributeBuilder (a, ctor, cdata, pa);
2339                                 return;
2340                         }
2341
2342                         ApplyToExtraTarget (a, ctor, cdata, pa);
2343                 }
2344
2345                 protected virtual void ApplyToExtraTarget (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2346                 {
2347                         throw new NotSupportedException ("You forgot to define special attribute target handling");
2348                 }
2349
2350                 // It is not supported for the accessors
2351                 public sealed override bool Define()
2352                 {
2353                         throw new NotSupportedException ();
2354                 }
2355
2356                 public virtual void Emit (TypeDefinition parent)
2357                 {
2358                         method_data.Emit (parent);
2359
2360                         if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2361                                 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (method_data.MethodBuilder);
2362                         if (((ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0))
2363                                 Module.PredefinedAttributes.DebuggerHidden.EmitAttribute (method_data.MethodBuilder);
2364
2365                         if (ReturnType.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2366                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2367                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder);
2368                         } else if (ReturnType.HasDynamicElement) {
2369                                 return_attributes = new ReturnParameter (this, method_data.MethodBuilder, Location);
2370                                 Module.PredefinedAttributes.Dynamic.EmitAttribute (return_attributes.Builder, ReturnType, Location);
2371                         }
2372
2373                         if (OptAttributes != null)
2374                                 OptAttributes.Emit ();
2375
2376                         if (declarative_security != null) {
2377                                 foreach (var de in declarative_security) {
2378 #if STATIC
2379                                         method_data.MethodBuilder.__AddDeclarativeSecurity (de);
2380 #else
2381                                         method_data.MethodBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2382 #endif
2383                                 }
2384                         }
2385
2386                         block = null;
2387                 }
2388
2389                 public override bool EnableOverloadChecks (MemberCore overload)
2390                 {
2391                         if (overload is MethodCore) {
2392                                 caching_flags |= Flags.MethodOverloadsExist;
2393                                 return true;
2394                         }
2395
2396                         // This can only happen with indexers and it will
2397                         // be catched as indexer difference
2398                         if (overload is AbstractPropertyEventMethod)
2399                                 return true;
2400
2401                         return false;
2402                 }
2403
2404                 public override string GetSignatureForDocumentation ()
2405                 {
2406                         // should not be called
2407                         throw new NotSupportedException ();
2408                 }
2409
2410                 public override bool IsClsComplianceRequired()
2411                 {
2412                         return false;
2413                 }
2414
2415                 public MethodSpec Spec { get; protected set; }
2416
2417                 //
2418                 //   Represents header string for documentation comment.
2419                 //
2420                 public override string DocCommentHeader {
2421                         get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
2422                 }
2423
2424                 void IMethodData.EmitExtraSymbolInfo (SourceMethod source)
2425                 { }
2426         }
2427
2428         public class Operator : MethodOrOperator {
2429
2430                 const Modifiers AllowedModifiers =
2431                         Modifiers.PUBLIC |
2432                         Modifiers.UNSAFE |
2433                         Modifiers.EXTERN |
2434                         Modifiers.STATIC;
2435
2436                 public enum OpType : byte {
2437
2438                         // Unary operators
2439                         LogicalNot,
2440                         OnesComplement,
2441                         Increment,
2442                         Decrement,
2443                         True,
2444                         False,
2445
2446                         // Unary and Binary operators
2447                         Addition,
2448                         Subtraction,
2449
2450                         UnaryPlus,
2451                         UnaryNegation,
2452                         
2453                         // Binary operators
2454                         Multiply,
2455                         Division,
2456                         Modulus,
2457                         BitwiseAnd,
2458                         BitwiseOr,
2459                         ExclusiveOr,
2460                         LeftShift,
2461                         RightShift,
2462                         Equality,
2463                         Inequality,
2464                         GreaterThan,
2465                         LessThan,
2466                         GreaterThanOrEqual,
2467                         LessThanOrEqual,
2468
2469                         // Implicit and Explicit
2470                         Implicit,
2471                         Explicit,
2472
2473                         // Just because of enum
2474                         TOP
2475                 };
2476
2477                 public readonly OpType OperatorType;
2478
2479                 static readonly string [] [] names;
2480
2481                 static Operator ()
2482                 {
2483                         names = new string[(int)OpType.TOP][];
2484                         names [(int) OpType.LogicalNot] = new string [] { "!", "op_LogicalNot" };
2485                         names [(int) OpType.OnesComplement] = new string [] { "~", "op_OnesComplement" };
2486                         names [(int) OpType.Increment] = new string [] { "++", "op_Increment" };
2487                         names [(int) OpType.Decrement] = new string [] { "--", "op_Decrement" };
2488                         names [(int) OpType.True] = new string [] { "true", "op_True" };
2489                         names [(int) OpType.False] = new string [] { "false", "op_False" };
2490                         names [(int) OpType.Addition] = new string [] { "+", "op_Addition" };
2491                         names [(int) OpType.Subtraction] = new string [] { "-", "op_Subtraction" };
2492                         names [(int) OpType.UnaryPlus] = new string [] { "+", "op_UnaryPlus" };
2493                         names [(int) OpType.UnaryNegation] = new string [] { "-", "op_UnaryNegation" };
2494                         names [(int) OpType.Multiply] = new string [] { "*", "op_Multiply" };
2495                         names [(int) OpType.Division] = new string [] { "/", "op_Division" };
2496                         names [(int) OpType.Modulus] = new string [] { "%", "op_Modulus" };
2497                         names [(int) OpType.BitwiseAnd] = new string [] { "&", "op_BitwiseAnd" };
2498                         names [(int) OpType.BitwiseOr] = new string [] { "|", "op_BitwiseOr" };
2499                         names [(int) OpType.ExclusiveOr] = new string [] { "^", "op_ExclusiveOr" };
2500                         names [(int) OpType.LeftShift] = new string [] { "<<", "op_LeftShift" };
2501                         names [(int) OpType.RightShift] = new string [] { ">>", "op_RightShift" };
2502                         names [(int) OpType.Equality] = new string [] { "==", "op_Equality" };
2503                         names [(int) OpType.Inequality] = new string [] { "!=", "op_Inequality" };
2504                         names [(int) OpType.GreaterThan] = new string [] { ">", "op_GreaterThan" };
2505                         names [(int) OpType.LessThan] = new string [] { "<", "op_LessThan" };
2506                         names [(int) OpType.GreaterThanOrEqual] = new string [] { ">=", "op_GreaterThanOrEqual" };
2507                         names [(int) OpType.LessThanOrEqual] = new string [] { "<=", "op_LessThanOrEqual" };
2508                         names [(int) OpType.Implicit] = new string [] { "implicit", "op_Implicit" };
2509                         names [(int) OpType.Explicit] = new string [] { "explicit", "op_Explicit" };
2510                 }
2511
2512                 public Operator (TypeDefinition parent, OpType type, FullNamedExpression ret_type, Modifiers mod_flags, ParametersCompiled parameters,
2513                                  ToplevelBlock block, Attributes attrs, Location loc)
2514                         : base (parent, ret_type, mod_flags, AllowedModifiers, new MemberName (GetMetadataName (type), loc), attrs, parameters)
2515                 {
2516                         OperatorType = type;
2517                         Block = block;
2518                 }
2519
2520                 public override void Accept (StructuralVisitor visitor)
2521                 {
2522                         visitor.Visit (this);
2523                 }
2524
2525                 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2526                 {
2527                         if (a.Type == pa.Conditional) {
2528                                 Error_ConditionalAttributeIsNotValid ();
2529                                 return;
2530                         }
2531
2532                         base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2533                 }
2534                 
2535                 public override bool Define ()
2536                 {
2537                         const Modifiers RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
2538                         if ((ModFlags & RequiredModifiers) != RequiredModifiers){
2539                                 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
2540                         }
2541
2542                         if (!base.Define ())
2543                                 return false;
2544
2545                         if (block != null && block.IsIterator) {
2546                                 //
2547                                 // Current method is turned into automatically generated
2548                                 // wrapper which creates an instance of iterator
2549                                 //
2550                                 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags);
2551                                 ModFlags |= Modifiers.DEBUGGER_HIDDEN;
2552                         }
2553
2554                         // imlicit and explicit operator of same types are not allowed
2555                         if (OperatorType == OpType.Explicit)
2556                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Implicit), parameters);
2557                         else if (OperatorType == OpType.Implicit)
2558                                 Parent.MemberCache.CheckExistingMembersOverloads (this, GetMetadataName (OpType.Explicit), parameters);
2559
2560                         TypeSpec declaring_type = Parent.CurrentType;
2561                         TypeSpec return_type = MemberType;
2562                         TypeSpec first_arg_type = ParameterTypes [0];
2563                         
2564                         TypeSpec first_arg_type_unwrap = first_arg_type;
2565                         if (first_arg_type.IsNullableType)
2566                                 first_arg_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (first_arg_type);
2567                         
2568                         TypeSpec return_type_unwrap = return_type;
2569                         if (return_type.IsNullableType)
2570                                 return_type_unwrap = Nullable.NullableInfo.GetUnderlyingType (return_type);
2571
2572                         //
2573                         // Rules for conversion operators
2574                         //
2575                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2576                                 if (first_arg_type_unwrap == return_type_unwrap && first_arg_type_unwrap == declaring_type) {
2577                                         Report.Error (555, Location,
2578                                                 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
2579                                         return false;
2580                                 }
2581
2582                                 TypeSpec conv_type;
2583                                 if (declaring_type == return_type || declaring_type == return_type_unwrap) {
2584                                         conv_type = first_arg_type;
2585                                 } else if (declaring_type == first_arg_type || declaring_type == first_arg_type_unwrap) {
2586                                         conv_type = return_type;
2587                                 } else {
2588                                         Report.Error (556, Location,
2589                                                 "User-defined conversion must convert to or from the enclosing type");
2590                                         return false;
2591                                 }
2592
2593                                 if (conv_type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
2594                                         Report.Error (1964, Location,
2595                                                 "User-defined conversion `{0}' cannot convert to or from the dynamic type",
2596                                                 GetSignatureForError ());
2597
2598                                         return false;
2599                                 }
2600
2601                                 if (conv_type.IsInterface) {
2602                                         Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
2603                                                 GetSignatureForError ());
2604                                         return false;
2605                                 }
2606
2607                                 if (conv_type.IsClass) {
2608                                         if (TypeSpec.IsBaseClass (declaring_type, conv_type, true)) {
2609                                                 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from a base class",
2610                                                         GetSignatureForError ());
2611                                                 return false;
2612                                         }
2613
2614                                         if (TypeSpec.IsBaseClass (conv_type, declaring_type, false)) {
2615                                                 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from a derived class",
2616                                                         GetSignatureForError ());
2617                                                 return false;
2618                                         }
2619                                 }
2620                         } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
2621                                 if (first_arg_type != declaring_type || parameters.Types[1].BuiltinType != BuiltinTypeSpec.Type.Int) {
2622                                         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");
2623                                         return false;
2624                                 }
2625                         } else if (parameters.Count == 1) {
2626                                 // Checks for Unary operators
2627
2628                                 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
2629                                         if (return_type != declaring_type && !TypeSpec.IsBaseClass (return_type, declaring_type, false)) {
2630                                                 Report.Error (448, Location,
2631                                                         "The return type for ++ or -- operator must be the containing type or derived from the containing type");
2632                                                 return false;
2633                                         }
2634                                         if (first_arg_type != declaring_type) {
2635                                                 Report.Error (
2636                                                         559, Location, "The parameter type for ++ or -- operator must be the containing type");
2637                                                 return false;
2638                                         }
2639                                 }
2640
2641                                 if (first_arg_type_unwrap != declaring_type) {
2642                                         Report.Error (562, Location,
2643                                                 "The parameter type of a unary operator must be the containing type");
2644                                         return false;
2645                                 }
2646
2647                                 if (OperatorType == OpType.True || OperatorType == OpType.False) {
2648                                         if (return_type.BuiltinType != BuiltinTypeSpec.Type.Bool) {
2649                                                 Report.Error (
2650                                                         215, Location,
2651                                                         "The return type of operator True or False " +
2652                                                         "must be bool");
2653                                                 return false;
2654                                         }
2655                                 }
2656
2657                         } else if (first_arg_type_unwrap != declaring_type) {
2658                                 // Checks for Binary operators
2659
2660                                 var second_arg_type = ParameterTypes[1];
2661                                 if (second_arg_type.IsNullableType)
2662                                         second_arg_type = Nullable.NullableInfo.GetUnderlyingType (second_arg_type);
2663
2664                                 if (second_arg_type != declaring_type) {
2665                                         Report.Error (563, Location,
2666                                                 "One of the parameters of a binary operator must be the containing type");
2667                                         return false;
2668                                 }
2669                         }
2670
2671                         return true;
2672                 }
2673
2674                 protected override bool ResolveMemberType ()
2675                 {
2676                         if (!base.ResolveMemberType ())
2677                                 return false;
2678
2679                         flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2680                         return true;
2681                 }
2682
2683                 protected override MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
2684                 {
2685                         // Operator cannot be override
2686                         bestCandidate = null;
2687                         return null;
2688                 }
2689
2690                 public static string GetName (OpType ot)
2691                 {
2692                         return names [(int) ot] [0];
2693                 }
2694
2695                 public static string GetName (string metadata_name)
2696                 {
2697                         for (int i = 0; i < names.Length; ++i) {
2698                                 if (names [i] [1] == metadata_name)
2699                                         return names [i] [0];
2700                         }
2701                         return null;
2702                 }
2703
2704                 public static string GetMetadataName (OpType ot)
2705                 {
2706                         return names [(int) ot] [1];
2707                 }
2708
2709                 public static string GetMetadataName (string name)
2710                 {
2711                         for (int i = 0; i < names.Length; ++i) {
2712                                 if (names [i] [0] == name)
2713                                         return names [i] [1];
2714                         }
2715                         return null;
2716                 }
2717
2718                 public static OpType? GetType (string metadata_name)
2719                 {
2720                         for (int i = 0; i < names.Length; ++i) {
2721                                 if (names[i][1] == metadata_name)
2722                                         return (OpType) i;
2723                         }
2724
2725                         return null;
2726                 }
2727
2728                 public OpType GetMatchingOperator ()
2729                 {
2730                         switch (OperatorType) {
2731                         case OpType.Equality:
2732                                 return OpType.Inequality;
2733                         case OpType.Inequality:
2734                                 return OpType.Equality;
2735                         case OpType.True:
2736                                 return OpType.False;
2737                         case OpType.False:
2738                                 return OpType.True;
2739                         case OpType.GreaterThan:
2740                                 return OpType.LessThan;
2741                         case OpType.LessThan:
2742                                 return OpType.GreaterThan;
2743                         case OpType.GreaterThanOrEqual:
2744                                 return OpType.LessThanOrEqual;
2745                         case OpType.LessThanOrEqual:
2746                                 return OpType.GreaterThanOrEqual;
2747                         default:
2748                                 return OpType.TOP;
2749                         }
2750                 }
2751
2752                 public override string GetSignatureForDocumentation ()
2753                 {
2754                         string s = base.GetSignatureForDocumentation ();
2755                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2756                                 s = s + "~" + ReturnType.GetSignatureForDocumentation ();
2757                         }
2758
2759                         return s;
2760                 }
2761
2762                 public override string GetSignatureForError ()
2763                 {
2764                         StringBuilder sb = new StringBuilder ();
2765                         if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
2766                                 sb.AppendFormat ("{0}.{1} operator {2}",
2767                                         Parent.GetSignatureForError (), GetName (OperatorType),
2768                                         member_type == null ? type_expr.GetSignatureForError () : member_type.GetSignatureForError ());
2769                         }
2770                         else {
2771                                 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
2772                         }
2773
2774                         sb.Append (parameters.GetSignatureForError ());
2775                         return sb.ToString ();
2776                 }
2777         }
2778 }
2779