Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/method.cs @ 16240

Last change on this file since 16240 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

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