In ilasm/tests:
[mcs.git] / bmcs / class.cs
blob0d1e0073f3cd064c3426a384d496e2c16c2ef4fb
1 //
2 // class.cs: Class and Struct handlers
3 //
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
6 // Marek Safar (marek.safar@seznam.cz)
7 //
8 // Licensed under the terms of the GNU GPL
9 //
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // (C) 2004 Novell, Inc
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
33 #define CACHE
34 using System;
35 using System.Text;
36 using System.Collections;
37 using System.Collections.Specialized;
38 using System.Reflection;
39 using System.Reflection.Emit;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Security;
43 using System.Security.Permissions;
44 using System.Xml;
46 using Mono.CompilerServices.SymbolWriter;
48 namespace Mono.CSharp {
50 public enum Kind {
51 Root,
52 Struct,
53 Class,
54 Interface
57 /// <summary>
58 /// This is the base class for structs and classes.
59 /// </summary>
60 public abstract class TypeContainer : DeclSpace, IMemberContainer {
62 public class MemberCoreArrayList: ArrayList
64 /// <summary>
65 /// Defines the MemberCore objects that are in this array
66 /// </summary>
67 public virtual void DefineContainerMembers ()
69 foreach (MemberCore mc in this) {
70 mc.Define ();
74 public virtual void Emit ()
76 foreach (MemberCore mc in this)
77 mc.Emit ();
81 public class MethodArrayList: MemberCoreArrayList
83 [Flags]
84 enum CachedMethods {
85 Equals = 1,
86 GetHashCode = 1 << 1
89 CachedMethods cached_method;
90 TypeContainer container;
92 public MethodArrayList (TypeContainer container)
94 this.container = container;
97 /// <summary>
98 /// Method container contains Equals method
99 /// </summary>
100 public bool HasEquals {
101 set {
102 cached_method |= CachedMethods.Equals;
105 get {
106 return (cached_method & CachedMethods.Equals) != 0;
110 /// <summary>
111 /// Method container contains GetHashCode method
112 /// </summary>
113 public bool HasGetHashCode {
114 set {
115 cached_method |= CachedMethods.GetHashCode;
118 get {
119 return (cached_method & CachedMethods.GetHashCode) != 0;
123 public override void DefineContainerMembers ()
125 base.DefineContainerMembers ();
127 if ((RootContext.WarningLevel >= 3) && HasEquals && !HasGetHashCode) {
128 Report.Warning (659, container.Location, "'{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
134 public sealed class IndexerArrayList: MemberCoreArrayList
136 /// <summary>
137 /// The indexer name for this container
138 /// </summary>
139 public string IndexerName = DefaultIndexerName;
141 bool seen_normal_indexers = false;
143 TypeContainer container;
145 public IndexerArrayList (TypeContainer container)
147 this.container = container;
150 /// <summary>
151 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
152 /// class is consistent. Either it is `Item' or it is the name defined by all the
153 /// indexers with the `IndexerName' attribute.
155 /// Turns out that the IndexerNameAttribute is applied to each indexer,
156 /// but it is never emitted, instead a DefaultMember attribute is attached
157 /// to the class.
158 /// </summary>
159 public override void DefineContainerMembers()
161 base.DefineContainerMembers ();
163 string class_indexer_name = null;
166 // If there's both an explicit and an implicit interface implementation, the
167 // explicit one actually implements the interface while the other one is just
168 // a normal indexer. See bug #37714.
171 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
172 foreach (Indexer i in this) {
173 if (i.InterfaceType != null) {
174 if (seen_normal_indexers)
175 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
176 continue;
179 seen_normal_indexers = true;
181 if (class_indexer_name == null) {
182 class_indexer_name = i.ShortName;
183 continue;
186 if (i.ShortName != class_indexer_name)
187 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
190 if (class_indexer_name != null)
191 IndexerName = class_indexer_name;
194 public override void Emit ()
196 base.Emit ();
198 if (!seen_normal_indexers)
199 return;
201 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
202 container.TypeBuilder.SetCustomAttribute (cb);
206 public class OperatorArrayList: MemberCoreArrayList
208 TypeContainer container;
210 public OperatorArrayList (TypeContainer container)
212 this.container = container;
216 // Operator pair checking
218 class OperatorEntry
220 public int flags;
221 public Type ret_type;
222 public Type type1, type2;
223 public Operator op;
224 public Operator.OpType ot;
226 public OperatorEntry (int f, Operator o)
228 flags = f;
230 ret_type = o.OperatorMethod.ReturnType;
231 Type [] pt = o.OperatorMethod.ParameterTypes;
232 type1 = pt [0];
233 type2 = pt [1];
234 op = o;
235 ot = o.OperatorType;
238 public override int GetHashCode ()
240 return ret_type.GetHashCode ();
243 public override bool Equals (object o)
245 OperatorEntry other = (OperatorEntry) o;
247 if (other.ret_type != ret_type)
248 return false;
249 if (other.type1 != type1)
250 return false;
251 if (other.type2 != type2)
252 return false;
253 return true;
258 // Checks that some operators come in pairs:
259 // == and !=
260 // > and <
261 // >= and <=
262 // true and false
264 // They are matched based on the return type and the argument types
266 void CheckPairedOperators ()
268 Hashtable pairs = new Hashtable (null, null);
269 Operator true_op = null;
270 Operator false_op = null;
271 bool has_equality_or_inequality = false;
273 // Register all the operators we care about.
274 foreach (Operator op in this){
275 int reg = 0;
277 switch (op.OperatorType){
278 case Operator.OpType.Equality:
279 reg = 1;
280 has_equality_or_inequality = true;
281 break;
282 case Operator.OpType.Inequality:
283 reg = 2;
284 has_equality_or_inequality = true;
285 break;
287 case Operator.OpType.True:
288 true_op = op;
289 break;
290 case Operator.OpType.False:
291 false_op = op;
292 break;
294 case Operator.OpType.GreaterThan:
295 reg = 1; break;
296 case Operator.OpType.LessThan:
297 reg = 2; break;
299 case Operator.OpType.GreaterThanOrEqual:
300 reg = 1; break;
301 case Operator.OpType.LessThanOrEqual:
302 reg = 2; break;
304 if (reg == 0)
305 continue;
307 OperatorEntry oe = new OperatorEntry (reg, op);
309 object o = pairs [oe];
310 if (o == null)
311 pairs [oe] = oe;
312 else {
313 oe = (OperatorEntry) o;
314 oe.flags |= reg;
318 if (true_op != null){
319 if (false_op == null)
320 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
321 } else if (false_op != null)
322 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
325 // Look for the mistakes.
327 foreach (DictionaryEntry de in pairs){
328 OperatorEntry oe = (OperatorEntry) de.Key;
330 if (oe.flags == 3)
331 continue;
333 string s = "";
334 switch (oe.ot){
335 case Operator.OpType.Equality:
336 s = "!=";
337 break;
338 case Operator.OpType.Inequality:
339 s = "==";
340 break;
341 case Operator.OpType.GreaterThan:
342 s = "<";
343 break;
344 case Operator.OpType.LessThan:
345 s = ">";
346 break;
347 case Operator.OpType.GreaterThanOrEqual:
348 s = "<=";
349 break;
350 case Operator.OpType.LessThanOrEqual:
351 s = ">=";
352 break;
354 Report.Error (216, oe.op.Location,
355 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
358 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
359 if (container.Methods == null || !container.Methods.HasEquals)
360 Report.Warning (660, container.Location, "'{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
362 if (container.Methods == null || !container.Methods.HasGetHashCode)
363 Report.Warning (661, container.Location, "'{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
367 public override void DefineContainerMembers ()
369 base.DefineContainerMembers ();
370 CheckPairedOperators ();
375 // Whether this is a struct, class or interface
376 public readonly Kind Kind;
378 // Holds a list of classes and structures
379 ArrayList types;
381 // Holds the list of properties
382 MemberCoreArrayList properties;
384 // Holds the list of enumerations
385 MemberCoreArrayList enums;
387 // Holds the list of delegates
388 MemberCoreArrayList delegates;
390 // Holds the list of constructors
391 protected MemberCoreArrayList instance_constructors;
393 // Holds the list of fields
394 MemberCoreArrayList fields;
396 // Holds a list of fields that have initializers
397 protected ArrayList initialized_fields;
399 // Holds a list of static fields that have initializers
400 protected ArrayList initialized_static_fields;
402 // Holds the list of constants
403 MemberCoreArrayList constants;
405 // Holds the list of
406 MemberCoreArrayList interfaces;
408 // Holds the methods.
409 MethodArrayList methods;
411 // Holds the events
412 protected MemberCoreArrayList events;
414 // Holds the indexers
415 IndexerArrayList indexers;
417 // Holds the operators
418 MemberCoreArrayList operators;
420 // Holds the iterators
421 ArrayList iterators;
423 // Holds the parts of a partial class;
424 ArrayList parts;
427 // Pointers to the default constructor and the default static constructor
429 protected Constructor default_constructor;
430 protected Constructor default_static_constructor;
433 // Whether we have at least one non-static field
435 bool have_nonstatic_fields = false;
438 // This one is computed after we can distinguish interfaces
439 // from classes from the arraylist `type_bases'
441 string base_class_name;
442 TypeExpr base_type;
444 ArrayList type_bases;
446 bool members_defined;
447 bool members_defined_ok;
449 // The interfaces we implement.
450 protected Type[] ifaces;
451 protected Type ptype;
453 // The base member cache and our member cache
454 MemberCache base_cache;
455 MemberCache member_cache;
457 public const string DefaultIndexerName = "Item";
459 Type GenericType;
461 public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
462 Attributes attrs, Kind kind, Location l)
463 : base (ns, parent, name, attrs, l)
465 this.Kind = kind;
467 types = new ArrayList ();
469 base_class_name = null;
472 public bool AddToMemberContainer (MemberCore symbol)
474 return AddToContainer (symbol, String.Concat (Name, '.', symbol.Name), symbol.Name);
477 bool AddToTypeContainer (DeclSpace ds)
479 return AddToContainer (ds, ds.Name, ds.Basename);
482 public void AddConstant (Const constant)
484 if (!AddToMemberContainer (constant))
485 return;
487 if (constants == null)
488 constants = new MemberCoreArrayList ();
490 constants.Add (constant);
493 public void AddEnum (Mono.CSharp.Enum e)
495 if (!AddToTypeContainer (e))
496 return;
498 if (enums == null)
499 enums = new MemberCoreArrayList ();
501 enums.Add (e);
504 public void AddClassOrStruct (TypeContainer c)
506 if (!AddToTypeContainer (c))
507 return;
509 types.Add (c);
512 public void AddDelegate (Delegate d)
514 if (!AddToTypeContainer (d))
515 return;
517 if (delegates == null)
518 delegates = new MemberCoreArrayList ();
520 delegates.Add (d);
523 public void AddMethod (Method method)
525 if (!AddToMemberContainer (method))
526 return;
528 if (methods == null)
529 methods = new MethodArrayList (this);
531 if (method.Name.IndexOf ('.') != -1)
532 methods.Insert (0, method);
533 else
534 methods.Add (method);
537 public void AddConstructor (Constructor c)
539 if (c.Name != Basename) {
540 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
543 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
545 if (is_static){
546 if (default_static_constructor != null) {
547 Report.SymbolRelatedToPreviousError (default_static_constructor);
548 Report.Error (111, c.Location, "Type '{0}' already defines a member " +
549 "called '{1}' with the same parameter types", Name, c.Name);
550 return;
553 default_static_constructor = c;
554 } else {
555 if (c.IsDefault ()){
556 if (default_constructor != null) {
557 Report.SymbolRelatedToPreviousError (default_constructor);
558 Report.Error (111, c.Location, "Type '{0}' already defines a member " +
559 "called '{1}' with the same parameter types", Name, c.Name);
560 return;
562 default_constructor = c;
565 if (instance_constructors == null)
566 instance_constructors = new MemberCoreArrayList ();
568 instance_constructors.Add (c);
572 public void AddInterface (TypeContainer iface)
574 if (!AddToTypeContainer (iface))
575 return;
577 if (interfaces == null) {
578 interfaces = new MemberCoreArrayList ();
581 interfaces.Add (iface);
584 public void AddField (Field field)
586 if (!AddToMemberContainer (field))
587 return;
589 if (fields == null)
590 fields = new MemberCoreArrayList ();
592 fields.Add (field);
594 if (field.HasInitializer){
595 if ((field.ModFlags & Modifiers.STATIC) != 0){
596 if (initialized_static_fields == null)
597 initialized_static_fields = new ArrayList ();
599 initialized_static_fields.Add (field);
601 } else {
602 if (initialized_fields == null)
603 initialized_fields = new ArrayList ();
605 initialized_fields.Add (field);
609 if ((field.ModFlags & Modifiers.STATIC) == 0)
610 have_nonstatic_fields = true;
613 public void AddProperty (Property prop)
615 if (!AddToMemberContainer (prop) ||
616 !AddToMemberContainer (prop.Get) || !AddToMemberContainer (prop.Set))
617 return;
619 if (properties == null)
620 properties = new MemberCoreArrayList ();
622 if (prop.Name.IndexOf ('.') != -1)
623 properties.Insert (0, prop);
624 else
625 properties.Add (prop);
628 public void AddEvent (Event e)
630 if (!AddToMemberContainer (e))
631 return;
633 if (e is EventProperty) {
634 if (!AddToMemberContainer (e.Add))
635 return;
637 if (!AddToMemberContainer (e.Remove))
638 return;
641 if (events == null)
642 events = new MemberCoreArrayList ();
644 events.Add (e);
647 /// <summary>
648 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
649 /// </summary>
650 public void AddIndexer (Indexer i)
652 if (indexers == null)
653 indexers = new IndexerArrayList (this);
655 if (i.IsExplicitImpl)
656 indexers.Insert (0, i);
657 else
658 indexers.Add (i);
661 public void AddOperator (Operator op)
663 if (!AddToMemberContainer (op))
664 return;
666 if (operators == null)
667 operators = new OperatorArrayList (this);
669 operators.Add (op);
672 public void AddIterator (Iterator i)
674 if (iterators == null)
675 iterators = new ArrayList ();
677 iterators.Add (i);
680 public void AddType (TypeContainer tc)
682 types.Add (tc);
685 public void AddPart (ClassPart part)
687 if (parts == null)
688 parts = new ArrayList ();
690 parts.Add (part);
693 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
695 if (a.Type == TypeManager.default_member_type) {
696 if (Indexers != null) {
697 Report.Error (646, a.Location,
698 "Cannot specify the DefaultMember attribute on" +
699 " a type containing an indexer");
700 return;
704 base.ApplyAttributeBuilder (a, cb);
707 public override AttributeTargets AttributeTargets {
708 get {
709 switch (Kind) {
710 case Kind.Class:
711 return AttributeTargets.Class;
712 case Kind.Struct:
713 return AttributeTargets.Struct;
714 case Kind.Interface:
715 return AttributeTargets.Interface;
716 default:
717 throw new NotSupportedException ();
722 public ArrayList Types {
723 get {
724 return types;
728 public MethodArrayList Methods {
729 get {
730 return methods;
734 public ArrayList Constants {
735 get {
736 return constants;
740 public ArrayList Interfaces {
741 get {
742 return interfaces;
746 public ArrayList Iterators {
747 get {
748 return iterators;
752 public string Base {
753 get {
754 return base_class_name;
758 public ArrayList Bases {
759 get {
760 return type_bases;
763 set {
764 type_bases = value;
768 public ArrayList Fields {
769 get {
770 return fields;
774 public ArrayList InstanceConstructors {
775 get {
776 return instance_constructors;
780 public ArrayList Properties {
781 get {
782 return properties;
786 public ArrayList Events {
787 get {
788 return events;
792 public ArrayList Enums {
793 get {
794 return enums;
798 public ArrayList Indexers {
799 get {
800 return indexers;
804 public ArrayList Operators {
805 get {
806 return operators;
810 public ArrayList Delegates {
811 get {
812 return delegates;
816 public ArrayList Parts {
817 get {
818 return parts;
822 public virtual TypeAttributes TypeAttr {
823 get {
824 return Modifiers.TypeAttr (ModFlags, this);
828 public string IndexerName {
829 get {
830 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
835 // Emits the instance field initializers
837 public bool EmitFieldInitializers (EmitContext ec)
839 ArrayList fields;
840 Expression instance_expr;
842 if (ec.IsStatic){
843 fields = initialized_static_fields;
844 instance_expr = null;
845 } else {
846 fields = initialized_fields;
847 instance_expr = new This (Location.Null).Resolve (ec);
850 if (fields == null)
851 return true;
853 foreach (Field f in fields){
854 Expression e = f.GetInitializerExpression (ec);
855 if (e == null)
856 return false;
858 Location l = f.Location;
859 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
860 fe.InstanceExpression = instance_expr;
861 fe.IsFieldInitializer = true;
863 ExpressionStatement a = new Assign (fe, e, l);
865 a = a.ResolveStatement (ec);
866 if (a == null)
867 return false;
869 a.EmitStatement (ec);
872 return true;
876 // Defines the default constructors
878 protected void DefineDefaultConstructor (bool is_static)
880 Constructor c;
882 // The default constructor is public
883 // If the class is abstract, the default constructor is protected
884 // The default static constructor is private
886 int mods = Modifiers.PUBLIC;
887 if (is_static)
888 mods = Modifiers.STATIC | Modifiers.PRIVATE;
889 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
890 mods = Modifiers.PROTECTED;
892 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
893 new ConstructorBaseInitializer (
894 null, Parameters.EmptyReadOnlyParameters,
895 Location),
896 Location);
898 AddConstructor (c);
900 c.Block = new ToplevelBlock (null, Location);
904 /// <remarks>
905 /// The pending methods that need to be implemented
906 // (interfaces or abstract methods)
907 /// </remarks>
908 public PendingImplementation Pending;
910 public abstract void Register ();
912 public abstract PendingImplementation GetPendingImplementations ();
914 TypeExpr[] GetPartialBases (out TypeExpr base_class, out bool error)
916 ArrayList ifaces = new ArrayList ();
918 base_class = null;
919 Location base_loc = Location.Null;
921 foreach (ClassPart part in parts) {
922 TypeExpr new_base_class;
923 TypeExpr[] new_ifaces;
925 new_ifaces = part.GetClassBases (out new_base_class, out error);
926 if (error)
927 return null;
929 if ((base_class != null) && (new_base_class != null) &&
930 !base_class.Equals (new_base_class)) {
931 Report.Error (263, part.Location,
932 "Partial declarations of `{0}' must " +
933 "not specify different base classes",
934 Name);
936 if (!Location.IsNull (base_loc))
937 Report.LocationOfPreviousError (base_loc);
939 error = true;
940 return null;
943 if ((base_class == null) && (new_base_class != null)) {
944 base_class = new_base_class;
945 base_loc = part.Location;
948 if (new_ifaces == null)
949 continue;
951 foreach (TypeExpr iface in new_ifaces) {
952 bool found = false;
953 foreach (TypeExpr old_iface in ifaces) {
954 if (old_iface.Equals (iface)) {
955 found = true;
956 break;
960 if (!found)
961 ifaces.Add (iface);
965 error = false;
967 TypeExpr[] retval = new TypeExpr [ifaces.Count];
968 ifaces.CopyTo (retval, 0);
969 return retval;
972 TypeExpr[] GetNormalBases (out TypeExpr base_class, out bool error)
974 base_class = null;
976 int count = Bases.Count;
977 int start = 0, i, j;
979 if (Kind == Kind.Class){
980 TypeExpr name = ResolveBaseTypeExpr (
981 (Expression) Bases [0], false, Location);
983 if (name == null){
984 error = true;
985 return null;
988 if (!name.IsInterface) {
989 // base_class could be a class, struct, enum, delegate.
990 // This is validated in GetClassBases.
991 base_class = name;
992 start = 1;
996 TypeExpr [] ifaces = new TypeExpr [count-start];
998 for (i = start, j = 0; i < count; i++, j++){
999 TypeExpr resolved = ResolveBaseTypeExpr ((Expression) Bases [i], false, Location);
1000 if (resolved == null) {
1001 error = true;
1002 return null;
1005 ifaces [j] = resolved;
1008 error = false;
1009 return ifaces;
1012 /// <summary>
1013 /// This function computes the Base class and also the
1014 /// list of interfaces that the class or struct @c implements.
1015 ///
1016 /// The return value is an array (might be null) of
1017 /// interfaces implemented (as Types).
1018 ///
1019 /// The @base_class argument is set to the base object or null
1020 /// if this is `System.Object'.
1021 /// </summary>
1022 TypeExpr [] GetClassBases (out TypeExpr base_class, out bool error)
1024 int i;
1026 error = false;
1028 TypeExpr[] ifaces;
1030 if (parts != null)
1031 ifaces = GetPartialBases (out base_class, out error);
1032 else if (Bases == null){
1033 base_class = null;
1034 return null;
1035 } else
1036 ifaces = GetNormalBases (out base_class, out error);
1038 if (error)
1039 return null;
1041 if ((base_class != null) && (Kind == Kind.Class)){
1042 if (base_class is TypeParameterExpr){
1043 Report.Error (
1044 689, base_class.Location,
1045 "Type parameter `{0}' can not be used as a " +
1046 "base class or interface", base_class.Name);
1047 error = true;
1048 return null;
1051 if (IsGeneric && base_class.IsAttribute){
1052 Report.Error (
1053 698, base_class.Location,
1054 "A generic type cannot derive from `{0}' " +
1055 "because it is an attribute class",
1056 base_class.Name);
1057 error = true;
1058 return null;
1061 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
1062 Report.Error (1521, base_class.Location, "Invalid base type");
1063 error = true;
1064 return null;
1067 if (base_class.IsSealed){
1068 error = true;
1069 Report.SymbolRelatedToPreviousError (base_class.Type);
1070 if (base_class.Type.IsAbstract) {
1071 Report.Error (709, Location, "'{0}': Cannot derive from static class", GetSignatureForError ());
1072 } else {
1073 Report.Error (509, Location, "'{0}': Cannot derive from sealed class", GetSignatureForError ());
1075 return null;
1078 if (!base_class.CanInheritFrom ()){
1079 Report.Error (644, Location,
1080 "`{0}' cannot inherit from special class `{1}'",
1081 Name, base_class.Name);
1082 error = true;
1083 return null;
1086 if (!base_class.AsAccessible (this, ModFlags)) {
1087 Report.SymbolRelatedToPreviousError (base_class.Type);
1088 Report.Error (60, Location, "Inconsistent accessibility: base class '{0}' is less accessible than class '{1}'",
1089 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
1093 if (base_class != null)
1094 base_class_name = base_class.Name;
1096 if (ifaces == null)
1097 return null;
1099 int count = ifaces != null ? ifaces.Length : 0;
1101 for (i = 0; i < count; i++) {
1102 TypeExpr iface = (TypeExpr) ifaces [i];
1104 if (!iface.IsInterface) {
1105 error = true;
1106 if (Kind != Kind.Class) {
1107 string what = Kind == Kind.Struct ? "Struct" : "Interface";
1109 Report.Error (527, Location,
1110 "In {0} `{1}', type `{2}' is not "+
1111 "an interface", what, Name, iface.Name);
1113 else if (base_class != null)
1114 Report.Error (1721, Location,
1115 "In Class `{0}', `{1}' is not an interface, and a base class has already been defined",
1116 Name, iface.Name);
1117 else {
1118 Report.Error (1722, Location,
1119 "In Class `{0}', `{1}' is not " +
1120 "an interface, a base class must be listed first", Name, iface.Name);
1122 continue;
1125 for (int x = 0; x < i; x++) {
1126 if (iface.Equals (ifaces [x])) {
1127 Report.Error (528, Location,
1128 "`{0}' is already listed in " +
1129 "interface list", iface.Name);
1130 error = true;
1134 if ((Kind == Kind.Interface) &&
1135 !iface.AsAccessible (Parent, ModFlags)) {
1136 Report.Error (61, Location,
1137 "Inconsistent accessibility: base " +
1138 "interface `{0}' is less accessible " +
1139 "than interface `{1}'", iface.Name,
1140 Name);
1141 error = true;
1145 if (error)
1146 return null;
1148 return ifaces;
1151 bool CheckGenericInterfaces (Type[] ifaces)
1153 ArrayList already_checked = new ArrayList ();
1155 for (int i = 0; i < ifaces.Length; i++) {
1156 Type iface = ifaces [i];
1157 foreach (Type t in already_checked) {
1158 if (iface == t)
1159 continue;
1161 Type[] infered = new Type [CountTypeParameters];
1162 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, infered, null))
1163 continue;
1165 Report.Error (
1166 695, Location,
1167 "`{0}' cannot implement both `{1}' and `{2}' " +
1168 "because they may unify for some type " +
1169 "parameter substitutions",
1170 TypeManager.GetFullName (TypeBuilder),
1171 iface, t);
1172 return false;
1175 already_checked.Add (iface);
1178 return true;
1181 bool error = false;
1184 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1186 public override TypeBuilder DefineType ()
1188 if (error)
1189 return null;
1191 if (TypeBuilder != null)
1192 return TypeBuilder;
1194 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
1196 TypeAttributes type_attributes = TypeAttr;
1198 try {
1199 if (IsTopLevel){
1200 if (TypeManager.NamespaceClash (Name, Location)) {
1201 error = true;
1202 return null;
1205 ModuleBuilder builder = CodeGen.Module.Builder;
1206 TypeBuilder = builder.DefineType (
1207 Name, type_attributes, null, null);
1208 } else {
1209 TypeBuilder builder;
1210 if (Parent.TypeBuilder != null)
1211 builder = Parent.TypeBuilder;
1212 else
1213 builder = Parent.DefineType ();
1215 if (builder == null) {
1216 error = true;
1217 return null;
1220 TypeBuilder = builder.DefineNestedType (
1221 MemberName.Basename, type_attributes,
1222 null, null);
1225 catch (ArgumentException) {
1226 Report.RuntimeMissingSupport (Location, "static classes");
1227 return null;
1230 TypeManager.AddUserType (Name, TypeBuilder, this);
1232 TypeExpr current_type = null;
1234 if (IsGeneric) {
1235 string[] param_names = new string [TypeParameters.Length];
1236 for (int i = 0; i < TypeParameters.Length; i++)
1237 param_names [i] = TypeParameters [i].Name;
1239 GenericTypeParameterBuilder[] gen_params;
1240 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1242 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1243 for (int i = offset; i < gen_params.Length; i++)
1244 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1246 foreach (TypeParameter type_param in CurrentTypeParameters) {
1247 if (!type_param.Resolve (this)) {
1248 error = true;
1249 return null;
1253 for (int i = offset; i < gen_params.Length; i++)
1254 CurrentTypeParameters [i - offset].DefineConstraints ();
1256 current_type = new ConstructedType (Name, TypeParameters, Location);
1258 foreach (TypeParameter type_param in TypeParameters) {
1259 if (!type_param.DefineType (ec)) {
1260 error = true;
1261 return null;
1265 if (!CheckConstraints (ec)) {
1266 error = true;
1267 return null;
1271 if ((Kind == Kind.Struct) && TypeManager.value_type == null)
1272 throw new Exception ();
1274 TypeExpr[] iface_exprs = GetClassBases (out base_type, out error);
1275 if (error)
1276 return null;
1278 if (base_type == null) {
1279 if (Kind == Kind.Class){
1280 if (RootContext.StdLib)
1281 base_type = TypeManager.system_object_expr;
1282 else if (Name != "System.Object")
1283 base_type = TypeManager.system_object_expr;
1284 } else if (Kind == Kind.Struct){
1286 // If we are compiling our runtime,
1287 // and we are defining ValueType, then our
1288 // base is `System.Object'.
1290 if (!RootContext.StdLib && Name == "System.ValueType")
1291 base_type = TypeManager.system_object_expr;
1292 else if (Kind == Kind.Struct)
1293 base_type = TypeManager.system_valuetype_expr;
1297 if (base_type != null) {
1298 base_type = base_type.ResolveAsTypeTerminal (ec);
1299 if (base_type == null) {
1300 error = true;
1301 return null;
1304 ptype = base_type.Type;
1307 if (!CheckRecursiveDefinition ()) {
1308 error = true;
1309 return null;
1312 if (ptype != null)
1313 TypeBuilder.SetParent (ptype);
1316 // Structs with no fields need to have at least one byte.
1317 // The right thing would be to set the PackingSize in a DefineType
1318 // but there are no functions that allow interfaces *and* the size to
1319 // be specified.
1322 if ((Kind == Kind.Struct) && !have_nonstatic_fields){
1323 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
1324 FieldAttributes.Private);
1327 // add interfaces that were not added at type creation
1328 if (iface_exprs != null) {
1329 // FIXME: I think this should be ...ExpandInterfaces (Parent.EmitContext, ...).
1330 // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
1331 ifaces = TypeManager.ExpandInterfaces (ec, iface_exprs);
1332 if (ifaces == null) {
1333 error = true;
1334 return null;
1337 foreach (Type itype in ifaces)
1338 TypeBuilder.AddInterfaceImplementation (itype);
1340 if (!CheckGenericInterfaces (ifaces)) {
1341 error = true;
1342 return null;
1345 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1348 if (IsGeneric) {
1349 foreach (TypeParameter type_param in TypeParameters)
1350 if (!type_param.CheckDependencies (ec)) {
1351 error = true;
1352 return null;
1356 if (current_type != null) {
1357 current_type = current_type.ResolveAsTypeTerminal (ec);
1358 if (current_type == null) {
1359 error = true;
1360 return null;
1363 CurrentType = current_type.Type;
1367 // Finish the setup for the EmitContext
1369 ec.ContainerType = TypeBuilder;
1371 if ((base_type != null) && base_type.IsAttribute) {
1372 RootContext.RegisterAttribute (this);
1373 } else if (!(this is Iterator))
1374 RootContext.RegisterOrder (this);
1376 if (!DefineNestedTypes ()) {
1377 error = true;
1378 return null;
1381 return TypeBuilder;
1384 protected virtual bool CheckConstraints (EmitContext ec)
1386 return true;
1389 protected virtual bool DefineNestedTypes ()
1391 if (Interfaces != null) {
1392 foreach (TypeContainer iface in Interfaces)
1393 if (iface.DefineType () == null)
1394 return false;
1397 if (Types != null) {
1398 foreach (TypeContainer tc in Types)
1399 if (tc.DefineType () == null)
1400 return false;
1403 if (Delegates != null) {
1404 foreach (Delegate d in Delegates)
1405 if (d.DefineType () == null)
1406 return false;
1409 if (Enums != null) {
1410 foreach (Enum en in Enums)
1411 if (en.DefineType () == null)
1412 return false;
1415 if (Parts != null) {
1416 foreach (ClassPart part in Parts) {
1417 part.TypeBuilder = TypeBuilder;
1418 part.base_type = base_type;
1419 part.ec = new EmitContext (part, Mono.CSharp.Location.Null, null, null, ModFlags);
1423 return true;
1426 protected bool CheckRecursiveDefinition ()
1428 if (InTransit) {
1429 Report.Error (146, Location,
1430 "Class definition is circular: `{0}'",
1431 GetSignatureForError ());
1432 error = true;
1433 return false;
1436 InTransit = true;
1438 Type parent = ptype;
1439 if (parent != null) {
1440 if (parent.IsGenericInstance)
1441 parent = parent.GetGenericTypeDefinition ();
1443 TypeContainer ptc = TypeManager.LookupTypeContainer (parent);
1444 if ((ptc != null) && !ptc.CheckRecursiveDefinition ())
1445 return false;
1448 InTransit = false;
1449 return true;
1452 static void Error_KeywordNotAllowed (Location loc)
1454 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1457 /// <summary>
1458 /// Populates our TypeBuilder with fields and methods
1459 /// </summary>
1460 public override bool DefineMembers (TypeContainer container)
1462 if (members_defined)
1463 return members_defined_ok;
1465 members_defined_ok = DoDefineMembers ();
1466 members_defined = true;
1468 return members_defined_ok;
1471 protected virtual bool DoDefineMembers ()
1473 if (IsTopLevel) {
1474 if ((ModFlags & Modifiers.NEW) != 0)
1475 Error_KeywordNotAllowed (Location);
1476 } else {
1477 // HACK: missing implemenation
1478 // This is not fully functional. Better way how to handle this is to have recursive definition of containers
1479 // instead of flat as we have now.
1480 // Now we are not able to check inner attribute class because its parent had not been defined.
1482 // TODO: remove this if
1483 if (Parent.MemberCache != null) {
1484 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1485 if (conflict_symbol == null) {
1486 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1487 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1488 } else {
1489 if ((ModFlags & Modifiers.NEW) == 0) {
1490 Report.SymbolRelatedToPreviousError (conflict_symbol);
1491 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError ());
1497 DefineContainerMembers (constants);
1498 DefineContainerMembers (fields);
1500 if ((Kind == Kind.Class) && !(this is ClassPart)){
1501 if ((instance_constructors == null) &&
1502 !(this is StaticClass)) {
1503 if (default_constructor == null)
1504 DefineDefaultConstructor (false);
1507 if (initialized_static_fields != null &&
1508 default_static_constructor == null)
1509 DefineDefaultConstructor (true);
1512 if (Kind == Kind.Struct){
1514 // Structs can not have initialized instance
1515 // fields
1517 if (initialized_static_fields != null &&
1518 default_static_constructor == null)
1519 DefineDefaultConstructor (true);
1521 if (initialized_fields != null)
1522 ReportStructInitializedInstanceError ();
1525 Pending = GetPendingImplementations ();
1527 if (parts != null) {
1528 foreach (ClassPart part in parts) {
1529 if (!part.DefineMembers (this))
1530 return false;
1535 // Constructors are not in the defined_names array
1537 DefineContainerMembers (instance_constructors);
1539 if (default_static_constructor != null)
1540 default_static_constructor.Define ();
1542 DefineContainerMembers (properties);
1543 DefineContainerMembers (events);
1544 DefineContainerMembers (indexers);
1545 DefineContainerMembers (methods);
1546 DefineContainerMembers (operators);
1547 DefineContainerMembers (enums);
1548 DefineContainerMembers (delegates);
1550 if (CurrentType != null) {
1551 GenericType = CurrentType;
1553 ec.ContainerType = GenericType;
1557 #if CACHE
1558 if (!(this is ClassPart))
1559 member_cache = new MemberCache (this);
1560 #endif
1562 if (parts != null) {
1563 foreach (ClassPart part in parts)
1564 part.member_cache = member_cache;
1567 if (iterators != null) {
1568 foreach (Iterator iterator in iterators) {
1569 if (iterator.DefineType () == null)
1570 return false;
1573 foreach (Iterator iterator in iterators) {
1574 if (!iterator.DefineMembers (this))
1575 return false;
1579 return true;
1582 void ReportStructInitializedInstanceError ()
1584 string n = TypeBuilder.FullName;
1586 foreach (Field f in initialized_fields){
1587 Report.Error (
1588 573, Location,
1589 "`" + n + "." + f.Name + "': can not have " +
1590 "instance field initializers in structs");
1594 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1596 if (mcal != null)
1597 mcal.DefineContainerMembers ();
1600 public override bool Define ()
1602 if (parts != null) {
1603 foreach (ClassPart part in parts) {
1604 if (!part.Define ())
1605 return false;
1609 return true;
1612 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1614 return BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1617 /// <summary>
1618 /// This function is based by a delegate to the FindMembers routine
1619 /// </summary>
1620 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1622 return true;
1625 /// <summary>
1626 /// This filter is used by FindMembers, and we just keep
1627 /// a global for the filter to `AlwaysAccept'
1628 /// </summary>
1629 static MemberFilter accepting_filter;
1632 static TypeContainer ()
1634 accepting_filter = new MemberFilter (AlwaysAccept);
1637 public MethodInfo[] GetMethods ()
1639 ArrayList members = new ArrayList ();
1641 DefineMembers (null);
1643 if (methods != null) {
1644 int len = methods.Count;
1645 for (int i = 0; i < len; i++) {
1646 Method m = (Method) methods [i];
1648 members.Add (m.MethodBuilder);
1652 if (operators != null) {
1653 int len = operators.Count;
1654 for (int i = 0; i < len; i++) {
1655 Operator o = (Operator) operators [i];
1657 members.Add (o.OperatorMethodBuilder);
1661 if (properties != null) {
1662 int len = properties.Count;
1663 for (int i = 0; i < len; i++) {
1664 Property p = (Property) properties [i];
1666 if (p.GetBuilder != null)
1667 members.Add (p.GetBuilder);
1668 if (p.SetBuilder != null)
1669 members.Add (p.SetBuilder);
1673 if (indexers != null) {
1674 int len = indexers.Count;
1675 for (int i = 0; i < len; i++) {
1676 Indexer ix = (Indexer) indexers [i];
1678 if (ix.GetBuilder != null)
1679 members.Add (ix.GetBuilder);
1680 if (ix.SetBuilder != null)
1681 members.Add (ix.SetBuilder);
1685 if (events != null) {
1686 int len = events.Count;
1687 for (int i = 0; i < len; i++) {
1688 Event e = (Event) events [i];
1690 if (e.AddBuilder != null)
1691 members.Add (e.AddBuilder);
1692 if (e.RemoveBuilder != null)
1693 members.Add (e.RemoveBuilder);
1697 MethodInfo[] retMethods = new MethodInfo [members.Count];
1698 members.CopyTo (retMethods, 0);
1699 return retMethods;
1702 // Indicated whether container has StructLayout attribute set Explicit
1703 public virtual bool HasExplicitLayout {
1704 get {
1705 return false;
1709 /// <summary>
1710 /// This method returns the members of this type just like Type.FindMembers would
1711 /// Only, we need to use this for types which are _being_ defined because MS'
1712 /// implementation can't take care of that.
1713 /// </summary>
1715 // FIXME: return an empty static array instead of null, that cleans up
1716 // some code and is consistent with some coding conventions I just found
1717 // out existed ;-)
1720 // Notice that in various cases we check if our field is non-null,
1721 // something that would normally mean that there was a bug elsewhere.
1723 // The problem happens while we are defining p-invoke methods, as those
1724 // will trigger a FindMembers, but this happens before things are defined
1726 // Since the whole process is a no-op, it is fine to check for null here.
1728 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1729 MemberFilter filter, object criteria)
1731 ArrayList members = null;
1733 int modflags = 0;
1734 if ((bf & BindingFlags.Public) != 0)
1735 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1736 Modifiers.INTERNAL;
1737 if ((bf & BindingFlags.NonPublic) != 0)
1738 modflags |= Modifiers.PRIVATE;
1740 int static_mask = 0, static_flags = 0;
1741 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1742 case BindingFlags.Static:
1743 static_mask = static_flags = Modifiers.STATIC;
1744 break;
1746 case BindingFlags.Instance:
1747 static_mask = Modifiers.STATIC;
1748 static_flags = 0;
1749 break;
1751 default:
1752 static_mask = static_flags = 0;
1753 break;
1756 Timer.StartTimer (TimerType.TcFindMembers);
1758 if (filter == null)
1759 filter = accepting_filter;
1761 if ((mt & MemberTypes.Field) != 0) {
1762 if (fields != null) {
1763 int len = fields.Count;
1764 for (int i = 0; i < len; i++) {
1765 Field f = (Field) fields [i];
1767 if ((f.ModFlags & modflags) == 0)
1768 continue;
1769 if ((f.ModFlags & static_mask) != static_flags)
1770 continue;
1772 FieldBuilder fb = f.FieldBuilder;
1773 if (fb != null && filter (fb, criteria) == true) {
1774 if (members == null)
1775 members = new ArrayList ();
1777 members.Add (fb);
1782 if (constants != null) {
1783 int len = constants.Count;
1784 for (int i = 0; i < len; i++) {
1785 Const con = (Const) constants [i];
1787 if ((con.ModFlags & modflags) == 0)
1788 continue;
1789 if ((con.ModFlags & static_mask) != static_flags)
1790 continue;
1792 FieldBuilder fb = con.FieldBuilder;
1793 if (fb == null) {
1794 if (con.Define ())
1795 fb = con.FieldBuilder;
1797 if (fb != null && filter (fb, criteria) == true) {
1798 if (members == null)
1799 members = new ArrayList ();
1801 members.Add (fb);
1807 if ((mt & MemberTypes.Method) != 0) {
1808 if (methods != null) {
1809 int len = methods.Count;
1810 for (int i = 0; i < len; i++) {
1811 Method m = (Method) methods [i];
1813 if ((m.ModFlags & modflags) == 0)
1814 continue;
1815 if ((m.ModFlags & static_mask) != static_flags)
1816 continue;
1818 MethodBuilder mb = m.MethodBuilder;
1820 if (mb != null && filter (mb, criteria) == true) {
1821 if (members == null)
1822 members = new ArrayList ();
1824 members.Add (mb);
1829 if (operators != null) {
1830 int len = operators.Count;
1831 for (int i = 0; i < len; i++) {
1832 Operator o = (Operator) operators [i];
1834 if ((o.ModFlags & modflags) == 0)
1835 continue;
1836 if ((o.ModFlags & static_mask) != static_flags)
1837 continue;
1839 MethodBuilder ob = o.OperatorMethodBuilder;
1840 if (ob != null && filter (ob, criteria) == true) {
1841 if (members == null)
1842 members = new ArrayList ();
1844 members.Add (ob);
1849 if (properties != null) {
1850 int len = properties.Count;
1851 for (int i = 0; i < len; i++) {
1852 Property p = (Property) properties [i];
1854 if ((p.ModFlags & modflags) == 0)
1855 continue;
1856 if ((p.ModFlags & static_mask) != static_flags)
1857 continue;
1859 MethodBuilder b;
1861 b = p.GetBuilder;
1862 if (b != null && filter (b, criteria) == true) {
1863 if (members == null)
1864 members = new ArrayList ();
1866 members.Add (b);
1869 b = p.SetBuilder;
1870 if (b != null && filter (b, criteria) == true) {
1871 if (members == null)
1872 members = new ArrayList ();
1874 members.Add (b);
1879 if (indexers != null) {
1880 int len = indexers.Count;
1881 for (int i = 0; i < len; i++) {
1882 Indexer ix = (Indexer) indexers [i];
1884 if ((ix.ModFlags & modflags) == 0)
1885 continue;
1886 if ((ix.ModFlags & static_mask) != static_flags)
1887 continue;
1889 MethodBuilder b;
1891 b = ix.GetBuilder;
1892 if (b != null && filter (b, criteria) == true) {
1893 if (members == null)
1894 members = new ArrayList ();
1896 members.Add (b);
1899 b = ix.SetBuilder;
1900 if (b != null && filter (b, criteria) == true) {
1901 if (members == null)
1902 members = new ArrayList ();
1904 members.Add (b);
1910 if ((mt & MemberTypes.Event) != 0) {
1911 if (events != null) {
1912 int len = events.Count;
1913 for (int i = 0; i < len; i++) {
1914 Event e = (Event) events [i];
1916 if ((e.ModFlags & modflags) == 0)
1917 continue;
1918 if ((e.ModFlags & static_mask) != static_flags)
1919 continue;
1921 MemberInfo eb = e.EventBuilder;
1922 if (eb != null && filter (eb, criteria) == true) {
1923 if (members == null)
1924 members = new ArrayList ();
1926 members.Add (e.EventBuilder);
1932 if ((mt & MemberTypes.Property) != 0){
1933 if (properties != null) {
1934 int len = properties.Count;
1935 for (int i = 0; i < len; i++) {
1936 Property p = (Property) properties [i];
1938 if ((p.ModFlags & modflags) == 0)
1939 continue;
1940 if ((p.ModFlags & static_mask) != static_flags)
1941 continue;
1943 MemberInfo pb = p.PropertyBuilder;
1944 if (pb != null && filter (pb, criteria) == true) {
1945 if (members == null)
1946 members = new ArrayList ();
1948 members.Add (p.PropertyBuilder);
1953 if (indexers != null) {
1954 int len = indexers.Count;
1955 for (int i = 0; i < len; i++) {
1956 Indexer ix = (Indexer) indexers [i];
1958 if ((ix.ModFlags & modflags) == 0)
1959 continue;
1960 if ((ix.ModFlags & static_mask) != static_flags)
1961 continue;
1963 MemberInfo ib = ix.PropertyBuilder;
1964 if (ib != null && filter (ib, criteria) == true) {
1965 if (members == null)
1966 members = new ArrayList ();
1968 members.Add (ix.PropertyBuilder);
1974 if ((mt & MemberTypes.NestedType) != 0) {
1975 if (types != null) {
1976 int len = types.Count;
1977 for (int i = 0; i < len; i++) {
1978 TypeContainer t = (TypeContainer) types [i];
1980 if ((t.ModFlags & modflags) == 0)
1981 continue;
1983 TypeBuilder tb = t.TypeBuilder;
1984 if (tb == null)
1985 tb = t.DefineType ();
1987 if (tb != null && (filter (tb, criteria) == true)) {
1988 if (members == null)
1989 members = new ArrayList ();
1991 members.Add (tb);
1996 if (enums != null) {
1997 int len = enums.Count;
1998 for (int i = 0; i < len; i++) {
1999 Enum en = (Enum) enums [i];
2001 if ((en.ModFlags & modflags) == 0)
2002 continue;
2004 TypeBuilder tb = en.TypeBuilder;
2005 if (tb != null && (filter (tb, criteria) == true)) {
2006 if (members == null)
2007 members = new ArrayList ();
2009 members.Add (tb);
2014 if (delegates != null) {
2015 int len = delegates.Count;
2016 for (int i = 0; i < len; i++) {
2017 Delegate d = (Delegate) delegates [i];
2019 if ((d.ModFlags & modflags) == 0)
2020 continue;
2022 TypeBuilder tb = d.TypeBuilder;
2023 if (tb != null && (filter (tb, criteria) == true)) {
2024 if (members == null)
2025 members = new ArrayList ();
2027 members.Add (tb);
2032 if (interfaces != null) {
2033 int len = interfaces.Count;
2034 for (int i = 0; i < len; i++) {
2035 TypeContainer iface = (TypeContainer) interfaces [i];
2037 if ((iface.ModFlags & modflags) == 0)
2038 continue;
2040 TypeBuilder tb = iface.TypeBuilder;
2041 if (tb != null && (filter (tb, criteria) == true)) {
2042 if (members == null)
2043 members = new ArrayList ();
2045 members.Add (tb);
2051 if ((mt & MemberTypes.Constructor) != 0){
2052 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2053 int len = instance_constructors.Count;
2054 for (int i = 0; i < len; i++) {
2055 Constructor c = (Constructor) instance_constructors [i];
2057 ConstructorBuilder cb = c.ConstructorBuilder;
2058 if (cb != null && filter (cb, criteria) == true) {
2059 if (members == null)
2060 members = new ArrayList ();
2062 members.Add (cb);
2067 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2068 ConstructorBuilder cb =
2069 default_static_constructor.ConstructorBuilder;
2071 if (cb != null && filter (cb, criteria) == true) {
2072 if (members == null)
2073 members = new ArrayList ();
2075 members.Add (cb);
2081 // Lookup members in base if requested.
2083 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2084 if (TypeBuilder.BaseType != null) {
2085 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2086 if (list.Count > 0) {
2087 if (members == null)
2088 members = new ArrayList ();
2090 members.AddRange (list);
2096 Timer.StopTimer (TimerType.TcFindMembers);
2098 if (members == null)
2099 return MemberList.Empty;
2100 else
2101 return new MemberList (members);
2104 public override MemberCache MemberCache {
2105 get {
2106 return member_cache;
2110 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2111 MemberFilter filter, object criteria)
2113 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2115 if (ds != null)
2116 return ds.FindMembers (mt, bf, filter, criteria);
2117 else
2118 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2122 // FindMethods will look for methods not only in the type `t', but in
2123 // any interfaces implemented by the type.
2125 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
2126 MemberFilter filter, object criteria)
2128 return null;
2131 /// <summary>
2132 /// Emits the values for the constants
2133 /// </summary>
2134 public void EmitConstants ()
2136 if (constants != null)
2137 foreach (Const con in constants)
2138 con.Emit ();
2139 return;
2142 protected virtual void VerifyMembers (EmitContext ec)
2145 // Check for internal or private fields that were never assigned
2147 if (RootContext.WarningLevel >= 4) {
2148 if (fields != null){
2149 foreach (Field f in fields) {
2150 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2151 continue;
2153 if ((f.status & Field.Status.USED) == 0){
2154 Report.Warning (169, f.Location, "The private field '{0}' is never used", f.GetSignatureForError ());
2155 continue;
2159 // Only report 649 on level 4
2161 if (RootContext.WarningLevel < 4)
2162 continue;
2164 if ((f.status & Field.Status.ASSIGNED) != 0)
2165 continue;
2167 Report.Warning (649, f.Location, "Field '{0}' is never assigned to, and will always have its default value '{1}'", f.GetSignatureForError (), "");
2173 /// <summary>
2174 /// Emits the code, this step is performed after all
2175 /// the types, enumerations, constructors
2176 /// </summary>
2177 public void EmitType ()
2179 if (OptAttributes != null)
2180 OptAttributes.Emit (ec, this);
2182 Emit ();
2184 if (instance_constructors != null) {
2185 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsCompliaceRequired (this)) {
2186 bool has_compliant_args = false;
2188 foreach (Constructor c in instance_constructors) {
2189 c.Emit ();
2191 if (has_compliant_args)
2192 continue;
2194 has_compliant_args = c.HasCompliantArgs;
2196 if (!has_compliant_args)
2197 Report.Error (3015, Location, "'{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2198 } else {
2199 foreach (Constructor c in instance_constructors)
2200 c.Emit ();
2204 EmitConstants ();
2206 if (default_static_constructor != null)
2207 default_static_constructor.Emit ();
2209 if (methods != null)
2210 foreach (Method m in methods)
2211 m.Emit ();
2213 if (operators != null)
2214 foreach (Operator o in operators)
2215 o.Emit ();
2217 if (properties != null)
2218 foreach (Property p in properties)
2219 p.Emit ();
2221 if (indexers != null){
2222 indexers.Emit ();
2225 if (fields != null)
2226 foreach (Field f in fields)
2227 f.Emit ();
2229 if (events != null){
2230 foreach (Event e in Events)
2231 e.Emit ();
2234 if (delegates != null) {
2235 foreach (Delegate d in Delegates) {
2236 d.Emit ();
2240 if (enums != null) {
2241 foreach (Enum e in enums) {
2242 e.Emit ();
2246 if (parts != null) {
2247 foreach (ClassPart part in parts)
2248 part.EmitType ();
2251 if ((Pending != null) && !(this is ClassPart))
2252 if (Pending.VerifyPendingMethods ())
2253 return;
2255 VerifyMembers (ec);
2257 if (iterators != null)
2258 foreach (Iterator iterator in iterators)
2259 iterator.EmitType ();
2261 // if (types != null)
2262 // foreach (TypeContainer tc in types)
2263 // tc.Emit ();
2266 public override void CloseType ()
2268 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2269 return;
2271 try {
2272 caching_flags |= Flags.CloseTypeCreated;
2273 TypeBuilder.CreateType ();
2274 } catch (TypeLoadException){
2276 // This is fine, the code still created the type
2278 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2279 // Console.WriteLine (e.Message);
2280 } catch {
2281 Console.WriteLine ("In type: " + Name);
2282 throw;
2285 if (Enums != null)
2286 foreach (Enum en in Enums)
2287 en.CloseType ();
2289 if (Types != null){
2290 foreach (TypeContainer tc in Types)
2291 if (tc.Kind == Kind.Struct)
2292 tc.CloseType ();
2294 foreach (TypeContainer tc in Types)
2295 if (tc.Kind != Kind.Struct)
2296 tc.CloseType ();
2299 if (Delegates != null)
2300 foreach (Delegate d in Delegates)
2301 d.CloseType ();
2303 if (Iterators != null)
2304 foreach (Iterator i in Iterators)
2305 i.CloseType ();
2307 types = null;
2308 properties = null;
2309 enums = null;
2310 delegates = null;
2311 fields = null;
2312 initialized_fields = null;
2313 initialized_static_fields = null;
2314 constants = null;
2315 interfaces = null;
2316 methods = null;
2317 events = null;
2318 indexers = null;
2319 operators = null;
2320 iterators = null;
2321 ec = null;
2322 default_constructor = null;
2323 default_static_constructor = null;
2324 type_bases = null;
2325 OptAttributes = null;
2326 ifaces = null;
2327 base_cache = null;
2328 member_cache = null;
2331 // TODO: make it obsolete and use GetSignatureForError
2332 public string MakeName (string n)
2334 return "`" + Name + "." + n + "'";
2338 // Performs the validation on a Method's modifiers (properties have
2339 // the same properties).
2341 public bool MethodModifiersValid (MemberCore mc)
2343 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2344 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2345 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2346 bool ok = true;
2347 int flags = mc.ModFlags;
2350 // At most one of static, virtual or override
2352 if ((flags & Modifiers.STATIC) != 0){
2353 if ((flags & vao) != 0){
2354 Report.Error (112, mc.Location, "static method '{0}' can not be marked as virtual, abstract or override",
2355 GetSignatureForError ());
2356 ok = false;
2360 if (Kind == Kind.Struct){
2361 if ((flags & va) != 0){
2362 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2363 ok = false;
2367 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2368 Report.Error (113, mc.Location, "'{0}' marked as override cannot be marked as new or virtual", mc.GetSignatureForError ());
2369 ok = false;
2373 // If the declaration includes the abstract modifier, then the
2374 // declaration does not include static, virtual or extern
2376 if ((flags & Modifiers.ABSTRACT) != 0){
2377 if ((flags & Modifiers.EXTERN) != 0){
2378 Report.Error (
2379 180, mc.Location, "'{0}' can not be both abstract and extern", mc.GetSignatureForError ());
2380 ok = false;
2383 if ((flags & Modifiers.SEALED) != 0) {
2384 Report.Error (502, mc.Location, "'{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2385 ok = false;
2388 if ((flags & Modifiers.VIRTUAL) != 0){
2389 Report.Error (503, mc.Location, "'{0}' can not be both abstract and virtual", mc.GetSignatureForError ());
2390 ok = false;
2393 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2394 Report.Error (513, mc.Location, "'{0}' is abstract but its container class is not", mc.GetSignatureForError ());
2395 ok = false;
2399 if ((flags & Modifiers.PRIVATE) != 0){
2400 if ((flags & vao) != 0){
2401 Report.Error (621, mc.Location, "'{0}' virtual or abstract members can not be private", mc.GetSignatureForError ());
2402 ok = false;
2406 if ((flags & Modifiers.SEALED) != 0){
2407 if ((flags & Modifiers.OVERRIDE) == 0){
2408 Report.Error (238, mc.Location, "'{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2409 ok = false;
2413 return ok;
2416 public bool UserDefinedStaticConstructor {
2417 get {
2418 return default_static_constructor != null;
2422 public Constructor DefaultStaticConstructor {
2423 get { return default_static_constructor; }
2426 protected override bool VerifyClsCompliance (DeclSpace ds)
2428 if (!base.VerifyClsCompliance (ds))
2429 return false;
2431 VerifyClsName ();
2433 if (IsGeneric) {
2434 Report.Error (3024, Location, "'{0}': type parameters are not CLS-compliant",
2435 GetSignatureForError ());
2436 return false;
2439 Type base_type = TypeBuilder.BaseType;
2440 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2441 Report.Error (3009, Location, "'{0}': base type '{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2444 if (!Parent.IsClsCompliaceRequired (ds)) {
2445 Report.Error (3018, Location, "'{0}' cannot be marked as CLS-Compliant because it is a member of non CLS-Compliant type '{1}'",
2446 GetSignatureForError (), Parent.GetSignatureForError ());
2448 return true;
2452 /// <summary>
2453 /// Checks whether container name is CLS Compliant
2454 /// </summary>
2455 void VerifyClsName ()
2457 Hashtable base_members = base_cache == null ?
2458 new Hashtable () :
2459 base_cache.GetPublicMembers ();
2460 Hashtable this_members = new Hashtable ();
2462 foreach (DictionaryEntry entry in defined_names) {
2463 MemberCore mc = (MemberCore)entry.Value;
2464 if (!mc.IsClsCompliaceRequired (this))
2465 continue;
2467 string name = (string)entry.Key;
2468 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2470 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2471 object found = base_members [lcase];
2472 if (found == null) {
2473 found = this_members [lcase];
2474 if (found == null) {
2475 this_members.Add (lcase, mc);
2476 continue;
2480 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2481 continue;
2483 if (found is MemberInfo) {
2484 if (basename == ((MemberInfo)found).Name)
2485 continue;
2486 Report.SymbolRelatedToPreviousError ((MemberInfo)found);
2487 } else {
2488 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2490 Report.Error (3005, mc.Location, "Identifier '{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2495 /// <summary>
2496 /// Performs checks for an explicit interface implementation. First it
2497 /// checks whether the `interface_type' is a base inteface implementation.
2498 /// Then it checks whether `name' exists in the interface type.
2499 /// </summary>
2500 public virtual bool VerifyImplements (Type interface_type, string full,
2501 string name, Location loc)
2503 bool found = false;
2505 if (ifaces != null){
2506 foreach (Type t in ifaces){
2507 if (t == interface_type){
2508 found = true;
2509 break;
2514 if (!found){
2515 Report.Error (540, loc, "`{0}': containing class does not implement interface `{1}'",
2516 full, interface_type.FullName);
2517 return false;
2520 return true;
2523 protected override void VerifyObsoleteAttribute()
2525 CheckUsageOfObsoleteAttribute (TypeBuilder.BaseType);
2527 if (ifaces == null)
2528 return;
2530 foreach (Type iface in ifaces) {
2531 CheckUsageOfObsoleteAttribute (iface);
2536 // IMemberContainer
2539 string IMemberContainer.Name {
2540 get {
2541 return Name;
2545 Type IMemberContainer.Type {
2546 get {
2547 return TypeBuilder;
2551 MemberCache IMemberContainer.MemberCache {
2552 get {
2553 return member_cache;
2557 bool IMemberContainer.IsInterface {
2558 get {
2559 return Kind == Kind.Interface;
2563 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2565 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2567 if (GenericType != null)
2568 return TypeManager.FindMembers (GenericType, mt, new_bf,
2569 null, null);
2570 else
2571 return FindMembers (mt, new_bf, null, null);
2575 // Generates xml doc comments (if any), and if required,
2576 // handle warning report.
2578 internal override void GenerateDocComment (DeclSpace ds)
2580 DocUtil.GenerateTypeDocComment (this, ds);
2583 public override string DocCommentHeader {
2584 get { return "T:"; }
2587 public virtual MemberCache BaseCache {
2588 get {
2589 if (base_cache != null)
2590 return base_cache;
2591 if (TypeBuilder.BaseType != null)
2592 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2593 if (TypeBuilder.IsInterface)
2594 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2595 return base_cache;
2601 public class PartialContainer : TypeContainer {
2603 public readonly Namespace Namespace;
2604 public readonly int OriginalModFlags;
2605 public readonly int AllowedModifiers;
2606 public readonly TypeAttributes DefaultTypeAttributes;
2608 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2609 MemberName member_name, int mod_flags, Kind kind,
2610 Location loc)
2612 PartialContainer pc;
2613 string full_name = member_name.GetName (true);
2614 DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
2615 if (ds != null) {
2616 pc = ds as PartialContainer;
2618 if (pc == null) {
2619 Report.Error (
2620 260, ds.Location, "Missing partial modifier " +
2621 "on declaration of type `{0}'; another " +
2622 "partial implementation of this type exists",
2623 member_name.GetTypeName());
2625 Report.LocationOfPreviousError (loc);
2626 return null;
2629 if (pc.Kind != kind) {
2630 Report.Error (
2631 261, loc, "Partial declarations of `{0}' " +
2632 "must be all classes, all structs or " +
2633 "all interfaces", member_name.GetTypeName ());
2634 return null;
2637 if (pc.OriginalModFlags != mod_flags) {
2638 Report.Error (
2639 262, loc, "Partial declarations of `{0}' " +
2640 "have conflicting accessibility modifiers",
2641 member_name.GetTypeName ());
2642 return null;
2645 if (pc.IsGeneric) {
2646 if (pc.CountTypeParameters != member_name.CountTypeArguments) {
2647 Report.Error (
2648 264, loc, "Partial declarations of `{0}' " +
2649 "must have the same type parameter names in " +
2650 "the same order", member_name.GetTypeName ());
2651 return null;
2654 string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
2655 string[] names = member_name.TypeArguments.GetDeclarations ();
2657 for (int i = 0; i < pc.CountTypeParameters; i++) {
2658 if (pc_names [i] == names [i])
2659 continue;
2661 Report.Error (
2662 264, loc, "Partial declarations of `{0}' " +
2663 "must have the same type parameter names in " +
2664 "the same order", member_name.GetTypeName ());
2665 return null;
2669 return pc;
2672 pc = new PartialContainer (ns, parent, member_name, mod_flags, kind, loc);
2673 RootContext.Tree.RecordDecl (full_name, pc);
2674 parent.AddType (pc);
2675 pc.Register ();
2676 // This is needed to define our type parameters; we define the constraints later.
2677 pc.SetParameterInfo (null);
2678 return pc;
2681 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2682 MemberName name, int mod, Attributes attrs,
2683 Kind kind, Location loc)
2685 PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
2686 if (pc == null) {
2687 // An error occured; create a dummy container, but don't
2688 // register it.
2689 pc = new PartialContainer (ns, parent, name, mod, kind, loc);
2692 ClassPart part = new ClassPart (ns, pc, mod, attrs, kind, loc);
2693 pc.AddPart (part);
2694 return part;
2697 protected PartialContainer (NamespaceEntry ns, TypeContainer parent,
2698 MemberName name, int mod, Kind kind, Location l)
2699 : base (ns, parent, name, null, kind, l)
2701 this.Namespace = ns.NS;
2703 switch (kind) {
2704 case Kind.Class:
2705 AllowedModifiers = Class.AllowedModifiers;
2706 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2707 break;
2709 case Kind.Struct:
2710 AllowedModifiers = Struct.AllowedModifiers;
2711 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2712 break;
2714 case Kind.Interface:
2715 AllowedModifiers = Interface.AllowedModifiers;
2716 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2717 break;
2719 default:
2720 throw new InvalidOperationException ();
2723 int accmods;
2724 if (parent.Parent == null)
2725 accmods = Modifiers.INTERNAL;
2726 else
2727 accmods = Modifiers.PRIVATE;
2729 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2730 this.OriginalModFlags = mod;
2733 public override void Register ()
2735 if (Kind == Kind.Interface)
2736 Parent.AddInterface (this);
2737 else if (Kind == Kind.Class || Kind == Kind.Struct)
2738 Parent.AddClassOrStruct (this);
2739 else
2740 throw new InvalidOperationException ();
2743 public override PendingImplementation GetPendingImplementations ()
2745 return PendingImplementation.GetPendingImplementations (this);
2748 ArrayList constraints_lists;
2750 public void UpdateConstraints (ArrayList constraints_list)
2753 // This is called for each ClassPart in a partial generic type declaration.
2755 // If no constraints were specified for the part, just return.
2756 // Otherwise, if we're called with constraints for the first time, they become
2757 // the type's constraint. If we're called with constraints again, we just
2758 // store them somewhere so we can later check whether there are no conflicts.
2760 if (constraints_list == null)
2761 return;
2763 if (constraints_lists != null) {
2764 constraints_lists.Add (constraints_list);
2765 return;
2768 DoUpdateConstraints (null, constraints_list, false);
2770 constraints_lists = new ArrayList ();
2773 protected bool DoUpdateConstraints (EmitContext ec, ArrayList constraints_list, bool check)
2775 for (int i = 0; i < TypeParameters.Length; i++) {
2776 string name = TypeParameters [i].Name;
2778 Constraints constraints = null;
2779 if (constraints_list != null) {
2780 foreach (Constraints constraint in constraints_list) {
2781 if (constraint.TypeParameter == name) {
2782 constraints = constraint;
2783 break;
2788 if (!TypeParameters [i].UpdateConstraints (ec, constraints, check)) {
2789 Report.Error (265, Location, "Partial declarations of `{0}' have " +
2790 "inconsistent constraints for type parameter `{1}'.",
2791 MemberName.GetTypeName (), name);
2792 return false;
2796 return true;
2799 protected override bool CheckConstraints (EmitContext ec)
2801 if (constraints_lists == null)
2802 return true;
2805 // If constraints were specified in more than one part of a
2806 // partial generic type definition, they must be identical.
2808 // Note that we must resolve them and then compute the fully
2809 // resolved types since different parts may have different
2810 // `using' aliases. See gen-129.cs for an example.
2812 foreach (ArrayList constraints_list in constraints_lists) {
2813 if (!DoUpdateConstraints (ec, constraints_list, true))
2814 return false;
2817 return true;
2820 public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
2821 Location l)
2823 ClassPart part = new ClassPart (ns, this, mod, attrs, Kind, l);
2824 AddPart (part);
2825 return part;
2828 public override TypeAttributes TypeAttr {
2829 get {
2830 return base.TypeAttr | DefaultTypeAttributes;
2835 public class ClassPart : TypeContainer, IMemberContainer {
2836 public readonly PartialContainer PartialContainer;
2837 public readonly bool IsPartial;
2839 public ClassPart (NamespaceEntry ns, PartialContainer parent,
2840 int mod, Attributes attrs, Kind kind, Location l)
2841 : base (ns, parent.Parent, parent.MemberName, attrs, kind, l)
2843 this.PartialContainer = parent;
2844 this.IsPartial = true;
2846 int accmods;
2847 if (parent.Parent == null)
2848 accmods = Modifiers.INTERNAL;
2849 else
2850 accmods = Modifiers.PRIVATE;
2852 this.ModFlags = Modifiers.Check (
2853 parent.AllowedModifiers, mod, accmods, l);
2856 public override void Register ()
2860 public override PendingImplementation GetPendingImplementations ()
2862 return PartialContainer.Pending;
2865 public override bool VerifyImplements (Type interface_type, string full,
2866 string name, Location loc)
2868 return PartialContainer.VerifyImplements (
2869 interface_type, full, name, loc);
2872 public override void SetParameterInfo (ArrayList constraints_list)
2874 PartialContainer.UpdateConstraints (constraints_list);
2877 public override MemberCache BaseCache {
2878 get {
2879 return PartialContainer.BaseCache;
2884 public abstract class ClassOrStruct : TypeContainer {
2885 bool hasExplicitLayout = false;
2886 ListDictionary declarative_security;
2888 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2889 MemberName name, Attributes attrs, Kind kind,
2890 Location l)
2891 : base (ns, parent, name, attrs, kind, l)
2895 public override PendingImplementation GetPendingImplementations ()
2897 return PendingImplementation.GetPendingImplementations (this);
2900 public override bool HasExplicitLayout {
2901 get {
2902 return hasExplicitLayout;
2906 protected override void VerifyMembers (EmitContext ec)
2908 base.VerifyMembers (ec);
2910 if ((events != null) && (RootContext.WarningLevel >= 3)) {
2911 foreach (Event e in events){
2912 if (e.status == 0)
2913 Report.Warning (67, e.Location, "The event '{0}' is never used", e.GetSignatureForError ());
2918 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2920 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
2921 if (declarative_security == null)
2922 declarative_security = new ListDictionary ();
2924 a.ExtractSecurityPermissionSet (declarative_security);
2925 return;
2928 if (a.Type == TypeManager.struct_layout_attribute_type
2929 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2930 hasExplicitLayout = true;
2932 base.ApplyAttributeBuilder (a, cb);
2935 public override void Emit()
2937 base.Emit ();
2939 if (declarative_security != null) {
2940 foreach (DictionaryEntry de in declarative_security) {
2941 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
2946 public override void Register ()
2948 Parent.AddClassOrStruct (this);
2952 /// <summary>
2953 /// Class handles static classes declaration
2954 /// </summary>
2955 public sealed class StaticClass: Class {
2956 public StaticClass (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
2957 Attributes attrs, Location l)
2958 : base (ns, parent, name, mod, attrs, l)
2960 if (RootContext.Version == LanguageVersion.ISO_1) {
2961 Report.FeatureIsNotStandardized (l, "static classes");
2962 Environment.Exit (1);
2966 protected override int AllowedModifiersProp {
2967 get {
2968 return Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE |
2969 Modifiers.STATIC | Modifiers.UNSAFE;
2973 protected override void DefineContainerMembers (MemberCoreArrayList list)
2975 if (list == null)
2976 return;
2978 foreach (MemberCore m in list) {
2979 if (m is Operator) {
2980 Report.Error (715, m.Location, "'{0}': static classes cannot contain user-defined operators", m.GetSignatureForError (this));
2981 continue;
2984 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2985 continue;
2987 if (m is Constructor) {
2988 Report.Error (710, m.Location, "'{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2989 continue;
2992 if (m is Destructor) {
2993 Report.Error (711, m.Location, "'{0}': Static class cannot contain destructor", GetSignatureForError ());
2994 continue;
2996 Report.Error (708, m.Location, "'{0}': cannot declare instance members in a static class", m.GetSignatureForError (this));
2999 base.DefineContainerMembers (list);
3002 public override TypeBuilder DefineType()
3004 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
3005 Report.Error (441, Location, "'{0}': a class cannot be both static and sealed", GetSignatureForError ());
3006 return null;
3009 TypeBuilder tb = base.DefineType ();
3010 if (tb == null)
3011 return null;
3013 if ((ptype != null) && (ptype != TypeManager.object_type)) {
3014 Report.Error (
3015 713, Location,
3016 "Static class '{0}' cannot derive from type '{1}'. " +
3017 "Static classes must derive from object",
3018 GetSignatureForError (), ptype);
3019 return null;
3022 if (ifaces != null) {
3023 foreach (Type t in ifaces)
3024 Report.SymbolRelatedToPreviousError (t);
3025 Report.Error (
3026 714, Location,
3027 "'{0}': static classes cannot implement interfaces",
3028 GetSignatureForError ());
3030 return tb;
3033 public override TypeAttributes TypeAttr {
3034 get {
3035 return base.TypeAttr | TypeAttributes.Abstract | TypeAttributes.Sealed;
3040 public class Class : ClassOrStruct {
3041 // TODO: remove this and use only AllowedModifiersProp to fix partial classes bugs
3042 public const int AllowedModifiers =
3043 Modifiers.NEW |
3044 Modifiers.PUBLIC |
3045 Modifiers.PROTECTED |
3046 Modifiers.INTERNAL |
3047 Modifiers.PRIVATE |
3048 Modifiers.ABSTRACT |
3049 Modifiers.SEALED |
3050 Modifiers.UNSAFE;
3052 // Information in the case we are an attribute type
3053 AttributeUsageAttribute attribute_usage;
3055 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
3056 Attributes attrs, Location l)
3057 : base (ns, parent, name, attrs, Kind.Class, l)
3059 this.ModFlags = mod;
3060 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
3063 virtual protected int AllowedModifiersProp {
3064 get {
3065 return AllowedModifiers;
3069 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
3071 if (a.UsageAttribute != null) {
3072 if (ptype != TypeManager.attribute_type &&
3073 !ptype.IsSubclassOf (TypeManager.attribute_type) &&
3074 TypeBuilder.FullName != "System.Attribute") {
3075 Report.Error (641, a.Location, "Attribute '{0}' is only valid on classes derived from System.Attribute", a.Name);
3077 attribute_usage = a.UsageAttribute;
3080 base.ApplyAttributeBuilder (a, cb);
3083 public AttributeUsageAttribute AttributeUsage {
3084 get {
3085 return attribute_usage;
3089 public const TypeAttributes DefaultTypeAttributes =
3090 TypeAttributes.AutoLayout | TypeAttributes.Class;
3092 public override TypeBuilder DefineType()
3094 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
3095 Report.Error (418, Location, "'{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
3096 return null;
3099 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3100 ModFlags = Modifiers.Check (AllowedModifiersProp, ModFlags, accmods, Location);
3102 return base.DefineType ();
3106 // FIXME: How do we deal with the user specifying a different
3107 // layout?
3109 public override TypeAttributes TypeAttr {
3110 get {
3111 return base.TypeAttr | DefaultTypeAttributes;
3116 public class Struct : ClassOrStruct {
3117 // <summary>
3118 // Modifiers allowed in a struct declaration
3119 // </summary>
3120 public const int AllowedModifiers =
3121 Modifiers.NEW |
3122 Modifiers.PUBLIC |
3123 Modifiers.PROTECTED |
3124 Modifiers.INTERNAL |
3125 Modifiers.UNSAFE |
3126 Modifiers.PRIVATE;
3128 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
3129 int mod, Attributes attrs, Location l)
3130 : base (ns, parent, name, attrs, Kind.Struct, l)
3132 int accmods;
3134 if (parent.Parent == null)
3135 accmods = Modifiers.INTERNAL;
3136 else
3137 accmods = Modifiers.PRIVATE;
3139 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
3141 this.ModFlags |= Modifiers.SEALED;
3144 public const TypeAttributes DefaultTypeAttributes =
3145 TypeAttributes.SequentialLayout |
3146 TypeAttributes.Sealed |
3147 TypeAttributes.BeforeFieldInit;
3150 // FIXME: Allow the user to specify a different set of attributes
3151 // in some cases (Sealed for example is mandatory for a class,
3152 // but what SequentialLayout can be changed
3154 public override TypeAttributes TypeAttr {
3155 get {
3156 return base.TypeAttr | DefaultTypeAttributes;
3161 /// <summary>
3162 /// Interfaces
3163 /// </summary>
3164 public class Interface : TypeContainer, IMemberContainer {
3165 /// <summary>
3166 /// Modifiers allowed in a class declaration
3167 /// </summary>
3168 public const int AllowedModifiers =
3169 Modifiers.NEW |
3170 Modifiers.PUBLIC |
3171 Modifiers.PROTECTED |
3172 Modifiers.INTERNAL |
3173 Modifiers.UNSAFE |
3174 Modifiers.PRIVATE;
3176 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
3177 int mod, Attributes attrs, Location l)
3178 : base (ns, parent, name, attrs, Kind.Interface, l)
3180 int accmods;
3182 if (parent.Parent == null)
3183 accmods = Modifiers.INTERNAL;
3184 else
3185 accmods = Modifiers.PRIVATE;
3187 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
3190 public override void Register ()
3192 Parent.AddInterface (this);
3195 public override PendingImplementation GetPendingImplementations ()
3197 return null;
3200 public const TypeAttributes DefaultTypeAttributes =
3201 TypeAttributes.AutoLayout |
3202 TypeAttributes.Abstract |
3203 TypeAttributes.Interface;
3205 public override TypeAttributes TypeAttr {
3206 get {
3207 return base.TypeAttr | DefaultTypeAttributes;
3212 public abstract class MethodCore : MemberBase {
3213 public readonly Parameters Parameters;
3214 public readonly GenericMethod GenericMethod;
3215 public readonly DeclSpace ds;
3216 protected ToplevelBlock block;
3219 // Parameters, cached for semantic analysis.
3221 protected InternalParameters parameter_info;
3222 protected Type [] parameter_types;
3224 // Whether this is an operator method.
3225 public bool IsOperator;
3228 // The method we're overriding if this is an override method.
3230 protected MethodInfo base_method = null;
3232 static string[] attribute_targets = new string [] { "method", "return" };
3234 public MethodCore (TypeContainer parent, GenericMethod generic,
3235 Expression type, int mod, int allowed_mod, bool is_iface,
3236 MemberName name, Attributes attrs, Parameters parameters,
3237 Location loc)
3238 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
3239 attrs, loc)
3241 Parameters = parameters;
3242 IsInterface = is_iface;
3243 this.GenericMethod = generic;
3245 if (generic != null)
3246 ds = generic;
3247 else
3248 ds = parent;
3252 // Returns the System.Type array for the parameters of this method
3254 public Type [] ParameterTypes {
3255 get {
3256 return parameter_types;
3260 public InternalParameters ParameterInfo
3262 get {
3263 return parameter_info;
3267 public ToplevelBlock Block {
3268 get {
3269 return block;
3272 set {
3273 block = value;
3277 protected override bool CheckBase ()
3279 if (!base.CheckBase ())
3280 return false;
3282 // Check whether arguments were correct.
3283 if (!DoDefineParameters ())
3284 return false;
3286 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3287 return false;
3289 if (IsExplicitImpl)
3290 return true;
3292 // Is null for System.Object while compiling corlib and base interfaces
3293 if (Parent.BaseCache == null) {
3294 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3295 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
3297 return true;
3300 Type base_ret_type = null;
3301 base_method = FindOutBaseMethod (Parent, ref base_ret_type);
3303 // method is override
3304 if (base_method != null) {
3306 if (!CheckMethodAgainstBase ())
3307 return false;
3309 if ((ModFlags & Modifiers.NEW) == 0) {
3310 if (MemberType != TypeManager.TypeToCoreType (base_ret_type)) {
3311 Report.SymbolRelatedToPreviousError (base_method);
3312 Report.Error (508, Location, GetSignatureForError (Parent) + ": cannot " +
3313 "change return type when overriding inherited member");
3314 return false;
3316 } else {
3317 if (base_method.IsAbstract && !IsInterface) {
3318 Report.SymbolRelatedToPreviousError (base_method);
3319 Report.Error (533, Location, "'{0}' hides inherited abstract member", GetSignatureForError (Parent));
3320 return false;
3324 if (base_method.IsSpecialName && !(this is PropertyBase)) {
3325 Report.Error (561, Location, "'{0}': cannot override '{1}' because it is a special compiler-generated method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (base_method));
3326 return false;
3329 if (RootContext.WarningLevel > 2) {
3330 if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
3331 Parent.Methods.HasEquals = true;
3332 else if (Name == "GetHashCode" && parameter_types.Length == 0)
3333 Parent.Methods.HasGetHashCode = true;
3336 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3337 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3338 if (oa != null) {
3339 EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
3340 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
3341 Report.SymbolRelatedToPreviousError (base_method);
3342 Report.Warning (672, 1, Location, "Member '{0}' overrides obsolete member. Add the Obsolete attribute to '{0}'", GetSignatureForError (Parent));
3346 return true;
3349 MemberInfo conflict_symbol = Parent.FindBaseMemberWithSameName (Name, !(this is Property));
3350 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3351 if (conflict_symbol != null) {
3352 Report.SymbolRelatedToPreviousError (conflict_symbol);
3353 if (this is PropertyBase)
3354 Report.Error (544, Location, "'{0}': cannot override because '{1}' is not a property", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3355 else
3356 Report.Error (505, Location, "'{0}': cannot override because '{1}' is not a method", GetSignatureForError (Parent), TypeManager.GetFullNameSignature (conflict_symbol));
3357 } else
3358 Report.Error (115, Location, "'{0}': no suitable methods found to override", GetSignatureForError (Parent));
3359 return false;
3362 if (conflict_symbol == null) {
3363 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3364 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
3366 return true;
3369 if ((ModFlags & Modifiers.NEW) == 0) {
3370 if (this is Method && conflict_symbol is MethodBase)
3371 return true;
3373 Report.SymbolRelatedToPreviousError (conflict_symbol);
3374 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3377 return true;
3382 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3383 // that have been defined.
3385 // `name' is the user visible name for reporting errors (this is used to
3386 // provide the right name regarding method names and properties)
3388 bool CheckMethodAgainstBase ()
3390 bool ok = true;
3392 // TODO: replace with GetSignatureForError
3393 string name = base_method.DeclaringType.Name + "." + base_method.Name;
3395 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3396 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3397 Report.Error (
3398 506, Location, Parent.MakeName (Name) +
3399 ": cannot override inherited member `" +
3400 name + "' because it is not " +
3401 "virtual, abstract or override");
3402 ok = false;
3405 // Now we check that the overriden method is not final
3407 if (base_method.IsFinal) {
3408 // This happens when implementing interface methods.
3409 if (base_method.IsHideBySig && base_method.IsVirtual) {
3410 Report.Error (
3411 506, Location, Parent.MakeName (Name) +
3412 ": cannot override inherited member `" +
3413 name + "' because it is not " +
3414 "virtual, abstract or override");
3415 } else
3416 Report.Error (239, Location, Parent.MakeName (Name) + " : cannot " +
3417 "override inherited member `" + name +
3418 "' because it is sealed.");
3419 ok = false;
3422 // Check that the permissions are not being changed
3424 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3425 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3427 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3428 Error_CannotChangeAccessModifiers (Parent, base_method, name);
3429 ok = false;
3433 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3434 ModFlags |= Modifiers.NEW;
3435 Report.SymbolRelatedToPreviousError (base_method);
3436 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3437 if (RootContext.WarningLevel >= 2)
3438 Report.Warning (114, Location, "'{0}' hides inherited member '{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", GetSignatureForError (Parent), TypeManager.CSharpSignature (base_method));
3439 } else
3440 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
3443 return ok;
3446 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3448 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3450 // when overriding protected internal, the method can be declared
3451 // protected internal only within the same assembly
3454 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3455 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3457 // assemblies differ - report an error
3460 return false;
3461 } else if (thisp != base_classp) {
3463 // same assembly, but other attributes differ - report an error
3466 return false;
3468 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3470 // if it's not "protected internal", it must be "protected"
3473 return false;
3474 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3476 // protected within the same assembly - an error
3478 return false;
3479 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3480 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3482 // protected ok, but other attributes differ - report an error
3484 return false;
3486 return true;
3487 } else {
3488 return (thisp == base_classp);
3492 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo base_method, string name)
3495 // FIXME: report the old/new permissions?
3497 Report.Error (
3498 507, Location, parent.MakeName (Name) +
3499 ": can't change the access modifiers when overriding inherited " +
3500 "member `" + name + "'");
3503 protected static string Error722 {
3504 get {
3505 return "'{0}': static types cannot be used as return types";
3509 /// <summary>
3510 /// For custom member duplication search in a container
3511 /// </summary>
3512 protected abstract bool CheckForDuplications ();
3514 /// <summary>
3515 /// Gets base method and its return type
3516 /// </summary>
3517 protected abstract MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type);
3519 protected virtual bool DoDefineParameters ()
3521 EmitContext ec = ds.EmitContext;
3522 if (ec == null)
3523 throw new InternalErrorException ("DoDefineParameters invoked too early");
3525 bool old_unsafe = ec.InUnsafe;
3526 ec.InUnsafe = InUnsafe;
3527 // Check if arguments were correct
3528 parameter_types = Parameters.GetParameterInfo (ec);
3529 ec.InUnsafe = old_unsafe;
3531 if ((parameter_types == null) ||
3532 !CheckParameters (ds, parameter_types))
3533 return false;
3535 TypeParameter[] tparam = ds.IsGeneric ? ds.TypeParameters : null;
3536 parameter_info = new InternalParameters (parameter_types, Parameters, tparam);
3538 Parameter array_param = Parameters.ArrayParameter;
3539 if ((array_param != null) &&
3540 (!array_param.ParameterType.IsArray ||
3541 (array_param.ParameterType.GetArrayRank () != 1))) {
3542 Report.Error (225, Location, "params parameter has to be a single dimensional array");
3543 return false;
3546 return true;
3549 void error_425 (Type old, Type t, string name)
3551 Report.Error (425, Location,
3552 "The constraints of type parameter `{0}' " +
3553 "of method `{1}' must match the constraints for " +
3554 "type parameter `{2}' of method `{3}'",
3555 TypeManager.CSharpName (old), Name,
3556 TypeManager.CSharpName (t), name);
3559 protected override bool CheckGenericOverride (MethodInfo method, string name)
3561 ParameterData pd = Invocation.GetParameterData (method);
3563 for (int i = 0; i < ParameterTypes.Length; i++) {
3564 GenericConstraints ogc = pd.GenericConstraints (i);
3565 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
3567 if ((gc == null) && (ogc == null))
3568 continue;
3570 Type ot = pd.ParameterType (i);
3571 Type t = ParameterTypes [i];
3573 if (!((gc != null) && (ogc != null))) {
3574 error_425 (ot, t, name);
3575 return false;
3578 if ((gc.Attributes != ogc.Attributes) ||
3579 (gc.HasClassConstraint != ogc.HasClassConstraint)) {
3580 error_425 (ot, t, name);
3581 return false;
3584 if (ogc.HasClassConstraint &&
3585 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
3586 error_425 (ot, t, name);
3587 return false;
3590 Type[] oct = ogc.InterfaceConstraints;
3591 Type[] ct = gc.InterfaceConstraints;
3593 if (oct.Length != ct.Length) {
3594 error_425 (ot, t, name);
3595 return false;
3598 for (int j = 0; j < oct.Length; j++)
3599 if (!oct [j].Equals (ct [j])) {
3600 error_425 (ot, t, name);
3601 return false;
3605 return true;
3608 public override string[] ValidAttributeTargets {
3609 get {
3610 return attribute_targets;
3614 protected override bool VerifyClsCompliance (DeclSpace ds)
3616 if (!base.VerifyClsCompliance (ds)) {
3617 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
3618 Report.Error (3011, Location, "'{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3620 return false;
3623 if (Parameters.HasArglist) {
3624 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3627 if (!AttributeTester.IsClsCompliant (MemberType)) {
3628 if (this is PropertyBase)
3629 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3630 GetSignatureForError ());
3631 else
3632 Report.Error (3002, Location, "Return type of '{0}' is not CLS-compliant",
3633 GetSignatureForError ());
3636 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3638 return true;
3641 bool MayUnify (MethodCore first, MethodCore second)
3643 int a_type_params = 0;
3644 if (first.GenericMethod != null)
3645 a_type_params = first.GenericMethod.CountTypeParameters;
3647 int b_type_params = 0;
3648 if (second.GenericMethod != null)
3649 b_type_params = second.GenericMethod.CountTypeParameters;
3651 if (a_type_params != b_type_params)
3652 return false;
3654 Type[] class_infered, method_infered;
3655 if (Parent.CountTypeParameters > 0)
3656 class_infered = new Type [Parent.CountTypeParameters];
3657 else
3658 class_infered = null;
3660 if (a_type_params > 0)
3661 method_infered = new Type [a_type_params];
3662 else
3663 method_infered = null;
3665 return TypeManager.MayBecomeEqualGenericInstances (
3666 first.ParameterTypes, second.ParameterTypes, class_infered, method_infered);
3669 protected bool IsDuplicateImplementation (MethodCore method)
3671 if ((method == this) ||
3672 (method.MemberName.GetTypeName () != MemberName.GetTypeName ()))
3673 return false;
3675 Type[] param_types = method.ParameterTypes;
3676 if (param_types == null)
3677 return false;
3679 if (param_types.Length != ParameterTypes.Length)
3680 return false;
3682 bool equal = true;
3683 bool may_unify = MayUnify (this, method);
3685 for (int i = 0; i < param_types.Length; i++) {
3686 if (param_types [i] != ParameterTypes [i])
3687 equal = false;
3690 // TODO: make operator compatible with MethodCore to avoid this
3691 if (this is Operator && method is Operator) {
3692 if (MemberType != method.MemberType)
3693 equal = may_unify = false;
3696 if (equal) {
3698 // Try to report 663: method only differs on out/ref
3700 ParameterData info = ParameterInfo;
3701 ParameterData other_info = method.ParameterInfo;
3702 for (int i = 0; i < info.Count; i++){
3703 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3704 Report.Error (663, Location,
3705 "Overload method only differs " +
3706 "in parameter modifier");
3707 return false;
3711 Report.SymbolRelatedToPreviousError (method);
3712 Report.Error (111, Location, "Type '{0}' already defines a member called '{1}' with the same parameter types", Parent.Name, Name);
3713 return true;
3714 } else if (may_unify) {
3715 Report.Error (408, Location,
3716 "`{0}' cannot define overload members that " +
3717 "may unify for some type parameter substitutions",
3718 Parent.MemberName);
3719 return true;
3722 return false;
3726 // Returns a string that represents the signature for this
3727 // member which should be used in XML documentation.
3729 public override string GetDocCommentName (DeclSpace ds)
3731 return DocUtil.GetMethodDocCommentName (this, ds);
3735 // Raised (and passed an XmlElement that contains the comment)
3736 // when GenerateDocComment is writing documentation expectedly.
3738 // FIXME: with a few effort, it could be done with XmlReader,
3739 // that means removal of DOM use.
3741 internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
3743 DocUtil.OnMethodGenerateDocComment (this, ds, el);
3747 // Represents header string for documentation comment.
3749 public override string DocCommentHeader {
3750 get { return "M:"; }
3753 protected override void VerifyObsoleteAttribute()
3755 base.VerifyObsoleteAttribute ();
3757 if (parameter_types == null)
3758 return;
3760 foreach (Type type in parameter_types) {
3761 CheckUsageOfObsoleteAttribute (type);
3766 public class SourceMethod : ISourceMethod
3768 TypeContainer container;
3769 MethodBase builder;
3771 protected SourceMethod (TypeContainer container, MethodBase builder,
3772 ISourceFile file, Location start, Location end)
3774 this.container = container;
3775 this.builder = builder;
3777 CodeGen.SymbolWriter.OpenMethod (
3778 file, this, start.Row, 0, end.Row, 0);
3781 public string Name {
3782 get { return builder.Name; }
3785 public int NamespaceID {
3786 get { return container.NamespaceEntry.SymbolFileID; }
3789 public int Token {
3790 get {
3791 if (builder is MethodBuilder)
3792 return ((MethodBuilder) builder).GetToken ().Token;
3793 else if (builder is ConstructorBuilder)
3794 return ((ConstructorBuilder) builder).GetToken ().Token;
3795 else
3796 throw new NotSupportedException ();
3800 public void CloseMethod ()
3802 if (CodeGen.SymbolWriter != null)
3803 CodeGen.SymbolWriter.CloseMethod ();
3806 public static SourceMethod Create (TypeContainer parent,
3807 MethodBase builder, Block block)
3809 if (CodeGen.SymbolWriter == null)
3810 return null;
3811 if (block == null)
3812 return null;
3814 Location start_loc = block.StartLocation;
3815 if (Location.IsNull (start_loc))
3816 return null;
3818 Location end_loc = block.EndLocation;
3819 if (Location.IsNull (end_loc))
3820 return null;
3822 ISourceFile file = start_loc.SourceFile;
3823 if (file == null)
3824 return null;
3826 return new SourceMethod (
3827 parent, builder, file, start_loc, end_loc);
3831 public class Method : MethodCore, IIteratorContainer, IMethodData {
3832 public MethodBuilder MethodBuilder;
3833 public MethodData MethodData;
3834 ReturnParameter return_attributes;
3835 ListDictionary declarative_security;
3837 /// <summary>
3838 /// Modifiers allowed in a class declaration
3839 /// </summary>
3840 const int AllowedModifiers =
3841 Modifiers.NEW |
3842 Modifiers.PUBLIC |
3843 Modifiers.PROTECTED |
3844 Modifiers.INTERNAL |
3845 Modifiers.PRIVATE |
3846 Modifiers.STATIC |
3847 Modifiers.VIRTUAL |
3848 Modifiers.SEALED |
3849 Modifiers.OVERRIDE |
3850 Modifiers.ABSTRACT |
3851 Modifiers.UNSAFE |
3852 Modifiers.METHOD_YIELDS |
3853 Modifiers.EXTERN;
3855 const int AllowedInterfaceModifiers =
3856 Modifiers.NEW | Modifiers.UNSAFE;
3859 // return_type can be "null" for VOID values.
3861 public Method (TypeContainer parent, GenericMethod generic,
3862 Expression return_type, int mod, bool is_iface,
3863 MemberName name, Parameters parameters, Attributes attrs,
3864 Location l)
3865 : base (parent, generic, return_type, mod,
3866 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3867 is_iface, name, attrs, parameters, l)
3871 public override AttributeTargets AttributeTargets {
3872 get {
3873 return AttributeTargets.Method;
3877 public override string GetSignatureForError()
3879 if (MethodBuilder == null) {
3880 return GetSignatureForError (Parent);
3882 return TypeManager.CSharpSignature (MethodBuilder);
3885 /// <summary>
3886 /// Use this method when MethodBuilder is null
3887 /// </summary>
3888 public override string GetSignatureForError (TypeContainer tc)
3890 // TODO: get params from somewhere
3891 if (parameter_info == null)
3892 return base.GetSignatureForError (tc);
3894 // TODO: move to parameters
3895 System.Text.StringBuilder args = new System.Text.StringBuilder ();
3896 if (parameter_info.Parameters.FixedParameters != null) {
3897 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
3898 Parameter p = parameter_info.Parameters.FixedParameters [i];
3899 args.Append (p.GetSignatureForError ());
3901 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
3902 args.Append (',');
3906 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
3909 void DuplicateEntryPoint (MethodInfo b, Location location)
3911 Report.Error (
3912 17, location,
3913 "Program `" + CodeGen.FileName +
3914 "' has more than one entry point defined: `" +
3915 TypeManager.CSharpSignature(b) + "'");
3918 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3920 if (b.ReturnType != TypeManager.void_type &&
3921 b.ReturnType != TypeManager.int32_type)
3922 return false;
3924 if (pinfo.Count == 0)
3925 return true;
3927 if (pinfo.Count > 1)
3928 return false;
3930 Type t = pinfo.ParameterType(0);
3931 if (t.IsArray &&
3932 (t.GetArrayRank() == 1) &&
3933 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3934 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3935 return true;
3936 else
3937 return false;
3940 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3942 if (a.Target == AttributeTargets.ReturnValue) {
3943 if (return_attributes == null)
3944 return_attributes = new ReturnParameter (MethodBuilder, Location);
3946 return_attributes.ApplyAttributeBuilder (a, cb);
3947 return;
3950 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3951 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3954 if (a.Type == TypeManager.dllimport_type) {
3955 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3956 if ((ModFlags & extern_static) != extern_static) {
3957 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
3960 return;
3963 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3964 if (declarative_security == null)
3965 declarative_security = new ListDictionary ();
3966 a.ExtractSecurityPermissionSet (declarative_security);
3967 return;
3970 if (a.Type == TypeManager.conditional_attribute_type) {
3971 if (IsOperator || IsExplicitImpl) {
3972 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
3973 return;
3976 if (ReturnType != TypeManager.void_type) {
3977 Report.Error (578, Location, "Conditional not valid on '{0}' because its return new ErrorData ( type is not void", GetSignatureForError ());
3978 return;
3981 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3982 Report.Error (243, Location, "Conditional not valid on '{0}' because it is an override method", GetSignatureForError ());
3983 return;
3986 if (IsInterface) {
3987 Report.Error (582, Location, "Conditional not valid on interface members");
3988 return;
3991 if (MethodData.IsImplementing) {
3992 Report.Error (629, Location, "Conditional member '{0}' cannot implement interface member", GetSignatureForError ());
3993 return;
3996 for (int i = 0; i < parameter_info.Count; ++i) {
3997 if ((parameter_info.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
3998 Report.Error (685, Location, "Conditional method '{0}' cannot have an out parameter", GetSignatureForError ());
3999 return;
4004 MethodBuilder.SetCustomAttribute (cb);
4007 protected override bool CheckForDuplications ()
4009 ArrayList ar = Parent.Methods;
4010 if (ar != null) {
4011 int arLen = ar.Count;
4013 for (int i = 0; i < arLen; i++) {
4014 Method m = (Method) ar [i];
4015 if (IsDuplicateImplementation (m))
4016 return false;
4020 ar = Parent.Properties;
4021 if (ar != null) {
4022 for (int i = 0; i < ar.Count; ++i) {
4023 PropertyBase pb = (PropertyBase) ar [i];
4024 if (pb.AreAccessorsDuplicateImplementation (this))
4025 return false;
4029 ar = Parent.Indexers;
4030 if (ar != null) {
4031 for (int i = 0; i < ar.Count; ++i) {
4032 PropertyBase pb = (PropertyBase) ar [i];
4033 if (pb.AreAccessorsDuplicateImplementation (this))
4034 return false;
4038 ar = Parent.Events;
4039 if (ar != null) {
4040 for (int i = 0; i < ar.Count; ++i) {
4041 Event ev = (Event) ar [i];
4042 if (ev.AreAccessorsDuplicateImplementation (this))
4043 return false;
4047 return true;
4051 // Creates the type
4053 public override bool Define ()
4055 if (!DoDefineBase ())
4056 return false;
4058 MethodBuilder mb = null;
4059 if (GenericMethod != null) {
4060 string mname = MemberName.GetMethodName ();
4061 mb = Parent.TypeBuilder.DefineGenericMethod (mname, flags);
4062 if (!GenericMethod.Define (mb, ReturnType))
4063 return false;
4066 if (!DoDefine (ds))
4067 return false;
4069 if (!CheckBase ())
4070 return false;
4072 if (IsOperator)
4073 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
4075 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
4076 this, mb, GenericMethod, base_method);
4078 if (!MethodData.Define (Parent))
4079 return false;
4082 // Setup iterator if we are one
4084 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4085 Iterator iterator = new Iterator (
4086 Parent, Name, MemberType, ParameterTypes,
4087 ParameterInfo, ModFlags, block, Location);
4089 if (!iterator.DefineIterator ())
4090 return false;
4092 block = iterator.Block;
4095 MethodBuilder = MethodData.MethodBuilder;
4098 // This is used to track the Entry Point,
4100 if (Name == "Main" &&
4101 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
4102 (RootContext.MainClass == null ||
4103 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4104 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
4105 if (RootContext.EntryPoint == null) {
4106 if (Parent.IsGeneric){
4107 Report.Error (-201, Location,
4108 "Entry point can not be defined in a generic class");
4111 RootContext.EntryPoint = MethodBuilder;
4112 RootContext.EntryPointLocation = Location;
4113 } else {
4114 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4115 DuplicateEntryPoint (MethodBuilder, Location);
4117 } else {
4118 if (RootContext.WarningLevel >= 4)
4119 Report.Warning (28, Location, "'{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder) );
4123 if (MemberType.IsAbstract && MemberType.IsSealed) {
4124 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4125 return false;
4128 return true;
4132 // Emits the code
4134 public override void Emit ()
4136 MethodData.Emit (Parent, this);
4137 base.Emit ();
4139 if (declarative_security != null) {
4140 foreach (DictionaryEntry de in declarative_security) {
4141 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4145 Block = null;
4146 MethodData = null;
4149 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4151 MethodInfo mi = (MethodInfo) container.BaseCache.FindMemberToOverride (
4152 container.TypeBuilder, Name, ParameterTypes, false);
4154 if (mi == null)
4155 return null;
4157 base_ret_type = mi.ReturnType;
4158 return mi;
4161 public override bool MarkForDuplicationCheck ()
4163 caching_flags |= Flags.TestMethodDuplication;
4164 return true;
4167 protected override bool VerifyClsCompliance(DeclSpace ds)
4169 if (!base.VerifyClsCompliance (ds))
4170 return false;
4172 if (parameter_types.Length > 0) {
4173 ArrayList al = (ArrayList)ds.MemberCache.Members [Name];
4174 if (al.Count > 1)
4175 ds.MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4178 return true;
4182 void IIteratorContainer.SetYields ()
4184 ModFlags |= Modifiers.METHOD_YIELDS;
4187 #region IMethodData Members
4189 public CallingConventions CallingConventions {
4190 get {
4191 CallingConventions cc = Parameters.GetCallingConvention ();
4192 if (Parameters.HasArglist)
4193 block.HasVarargs = true;
4195 if (!IsInterface)
4196 if ((ModFlags & Modifiers.STATIC) == 0)
4197 cc |= CallingConventions.HasThis;
4199 // FIXME: How is `ExplicitThis' used in C#?
4201 return cc;
4205 public Type ReturnType {
4206 get {
4207 return MemberType;
4211 public MemberName MethodName {
4212 get {
4213 return MemberName;
4217 public new Location Location {
4218 get {
4219 return base.Location;
4223 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4225 return new EmitContext (
4226 tc, ds, Location, ig, ReturnType, ModFlags, false);
4229 public ObsoleteAttribute GetObsoleteAttribute ()
4231 return GetObsoleteAttribute (ds);
4234 /// <summary>
4235 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4236 /// </summary>
4237 public bool IsExcluded (EmitContext ec)
4239 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4240 return (caching_flags & Flags.Excluded) != 0;
4242 caching_flags &= ~Flags.Excluded_Undetected;
4244 if (base_method == null) {
4245 if (OptAttributes == null)
4246 return false;
4248 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
4250 if (attrs == null)
4251 return false;
4253 foreach (Attribute a in attrs) {
4254 string condition = a.GetConditionalAttributeValue (Parent.EmitContext);
4255 if (RootContext.AllDefines.Contains (condition))
4256 return false;
4259 caching_flags |= Flags.Excluded;
4260 return true;
4263 IMethodData md = TypeManager.GetMethod (base_method);
4264 if (md == null) {
4265 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
4266 caching_flags |= Flags.Excluded;
4267 return true;
4269 return false;
4272 if (md.IsExcluded (ec)) {
4273 caching_flags |= Flags.Excluded;
4274 return true;
4276 return false;
4279 GenericMethod IMethodData.GenericMethod {
4280 get {
4281 return GenericMethod;
4285 #endregion
4288 public abstract class ConstructorInitializer {
4289 ArrayList argument_list;
4290 protected ConstructorInfo base_constructor;
4291 Parameters parameters;
4292 Location loc;
4294 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
4295 Location loc)
4297 this.argument_list = argument_list;
4298 this.parameters = parameters;
4299 this.loc = loc;
4302 public ArrayList Arguments {
4303 get {
4304 return argument_list;
4308 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
4310 Expression base_constructor_group;
4311 Type t;
4313 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
4315 if (argument_list != null){
4316 foreach (Argument a in argument_list){
4317 if (!a.Resolve (ec, loc))
4318 return false;
4321 ec.CurrentBlock = null;
4323 if (this is ConstructorBaseInitializer) {
4324 if (ec.ContainerType.BaseType == null)
4325 return true;
4327 t = ec.ContainerType.BaseType;
4328 if (ec.ContainerType.IsValueType) {
4329 Report.Error (522, loc,
4330 "structs cannot call base class constructors");
4331 return false;
4333 } else
4334 t = ec.ContainerType;
4336 base_constructor_group = Expression.MemberLookup (
4337 ec, t, ".ctor", MemberTypes.Constructor,
4338 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4339 loc);
4341 if (base_constructor_group == null){
4342 base_constructor_group = Expression.MemberLookup (
4343 ec, t, ".ctor", MemberTypes.Constructor,
4344 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4345 loc);
4347 if (base_constructor_group != null)
4348 Report.Error (
4349 112, loc, "`{0}.{1}' is inaccessible due to " +
4350 "its protection level", t.FullName, t.Name);
4351 else
4352 Report.Error (
4353 1501, loc, "Can not find a constructor for " +
4354 "this argument list");
4355 return false;
4358 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
4359 ec, (MethodGroupExpr) base_constructor_group, argument_list,
4360 false, loc);
4362 if (base_constructor == null){
4363 Report.Error (1501, loc,
4364 "Can not find a constructor for this argument list");
4365 return false;
4368 if (base_constructor == caller_builder){
4369 Report.Error (516, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
4370 return false;
4373 return true;
4376 public void Emit (EmitContext ec)
4378 if (base_constructor != null){
4379 ec.Mark (loc, false);
4380 if (ec.IsStatic)
4381 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4382 else
4383 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4387 /// <summary>
4388 /// Method search for base ctor. (We do not cache it).
4389 /// </summary>
4390 Constructor GetOverloadedConstructor (TypeContainer tc)
4392 if (tc.InstanceConstructors == null)
4393 return null;
4395 foreach (Constructor c in tc.InstanceConstructors) {
4396 if (Arguments == null) {
4397 if (c.ParameterTypes.Length == 0)
4398 return c;
4400 continue;
4403 bool ok = true;
4405 int count = c.ParameterInfo.Count;
4406 if ((count > 0) &&
4407 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
4408 for (int i = 0; i < count-1; i++)
4409 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
4410 ok = false;
4411 break;
4413 } else {
4414 if (c.ParameterTypes.Length != Arguments.Count)
4415 continue;
4417 for (int i = 0; i < Arguments.Count; ++i)
4418 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
4419 ok = false;
4420 break;
4424 if (!ok)
4425 continue;
4427 return c;
4430 return null;
4433 //TODO: implement caching when it will be necessary
4434 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
4436 Constructor ctor = GetOverloadedConstructor (tc);
4437 if (ctor == null)
4438 return;
4440 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
4441 if (oa == null)
4442 return;
4444 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
4448 public class ConstructorBaseInitializer : ConstructorInitializer {
4449 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
4450 base (argument_list, pars, l)
4454 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
4455 if (base_constructor == null)
4456 return;
4458 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.TypeBuilder.BaseType);
4459 if (type_ds == null) {
4460 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (base_constructor);
4462 if (oa != null)
4463 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (base_constructor), loc);
4465 return;
4468 base.CheckObsoleteAttribute (type_ds, loc);
4473 public class ConstructorThisInitializer : ConstructorInitializer {
4474 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
4475 base (argument_list, pars, l)
4480 public class Constructor : MethodCore, IMethodData {
4481 public ConstructorBuilder ConstructorBuilder;
4482 public ConstructorInitializer Initializer;
4483 ListDictionary declarative_security;
4485 // <summary>
4486 // Modifiers allowed for a constructor.
4487 // </summary>
4488 public const int AllowedModifiers =
4489 Modifiers.PUBLIC |
4490 Modifiers.PROTECTED |
4491 Modifiers.INTERNAL |
4492 Modifiers.STATIC |
4493 Modifiers.UNSAFE |
4494 Modifiers.EXTERN |
4495 Modifiers.PRIVATE;
4497 bool has_compliant_args = false;
4499 // The spec claims that static is not permitted, but
4500 // my very own code has static constructors.
4502 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
4503 ConstructorInitializer init, Location l)
4504 : base (ds, null, null, mod, AllowedModifiers, false,
4505 new MemberName (name), null, args, l)
4507 Initializer = init;
4510 public override string GetSignatureForError()
4512 if (ConstructorBuilder == null)
4513 return GetSignatureForError (Parent);
4515 return TypeManager.CSharpSignature (ConstructorBuilder);
4518 public bool HasCompliantArgs {
4519 get {
4520 return has_compliant_args;
4524 public override AttributeTargets AttributeTargets {
4525 get {
4526 return AttributeTargets.Constructor;
4532 // Returns true if this is a default constructor
4534 public bool IsDefault ()
4536 if ((ModFlags & Modifiers.STATIC) != 0)
4537 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4538 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
4540 else
4541 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4542 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
4543 (Initializer is ConstructorBaseInitializer) &&
4544 (Initializer.Arguments == null);
4547 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4549 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4550 if (declarative_security == null) {
4551 declarative_security = new ListDictionary ();
4553 a.ExtractSecurityPermissionSet (declarative_security);
4554 return;
4557 ConstructorBuilder.SetCustomAttribute (cb);
4560 protected override bool CheckForDuplications ()
4562 ArrayList ar = Parent.InstanceConstructors;
4563 if (ar != null) {
4564 int arLen = ar.Count;
4566 for (int i = 0; i < arLen; i++) {
4567 Constructor m = (Constructor) ar [i];
4568 if (IsDuplicateImplementation (m))
4569 return false;
4572 return true;
4575 protected override bool CheckBase ()
4577 // Check whether arguments were correct.
4578 if (!DoDefineParameters ())
4579 return false;
4581 // TODO: skip the rest for generated ctor
4582 if ((ModFlags & Modifiers.STATIC) != 0)
4583 return true;
4585 if (!CheckForDuplications ())
4586 return false;
4588 if (Parent.Kind == Kind.Struct) {
4589 if (ParameterTypes.Length == 0) {
4590 Report.Error (568, Location,
4591 "Structs can not contain explicit parameterless " +
4592 "constructors");
4593 return false;
4596 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4597 Report.Error (666, Location, "Protected member in struct declaration");
4598 return false;
4602 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4603 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
4606 return true;
4610 // Creates the ConstructorBuilder
4612 public override bool Define ()
4614 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4615 MethodAttributes.SpecialName);
4617 if ((ModFlags & Modifiers.STATIC) != 0){
4618 ca |= MethodAttributes.Static | MethodAttributes.Private;
4619 } else {
4620 ca |= MethodAttributes.HideBySig;
4622 if ((ModFlags & Modifiers.PUBLIC) != 0)
4623 ca |= MethodAttributes.Public;
4624 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4625 if ((ModFlags & Modifiers.INTERNAL) != 0)
4626 ca |= MethodAttributes.FamORAssem;
4627 else
4628 ca |= MethodAttributes.Family;
4629 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4630 ca |= MethodAttributes.Assembly;
4631 else if (IsDefault ())
4632 ca |= MethodAttributes.Public;
4633 else
4634 ca |= MethodAttributes.Private;
4637 // Check if arguments were correct.
4638 if (!CheckBase ())
4639 return false;
4641 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4642 ca, CallingConventions,
4643 ParameterTypes);
4645 if ((ModFlags & Modifiers.UNSAFE) != 0)
4646 ConstructorBuilder.InitLocals = false;
4648 TypeManager.AddMethod (ConstructorBuilder, this);
4651 // HACK because System.Reflection.Emit is lame
4653 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
4655 return true;
4659 // Emits the code
4661 public override void Emit ()
4663 EmitContext ec = CreateEmitContext (null, null);
4666 // extern methods have no bodies
4668 if ((ModFlags & Modifiers.EXTERN) != 0) {
4669 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
4670 Report.Error (
4671 179, Location, "External constructor `" +
4672 TypeManager.CSharpSignature (ConstructorBuilder) +
4673 "' can not have a body");
4674 return;
4676 } else if (block == null) {
4677 Report.Error (
4678 501, Location, "Constructor `" +
4679 TypeManager.CSharpSignature (ConstructorBuilder) +
4680 "' must declare a body since it is not marked extern");
4681 return;
4684 if ((ModFlags & Modifiers.STATIC) == 0){
4685 if (Parent.Kind == Kind.Class && Initializer == null)
4686 Initializer = new ConstructorBaseInitializer (
4687 null, Parameters.EmptyReadOnlyParameters, Location);
4691 // Spec mandates that Initializers will not have
4692 // `this' access
4694 ec.IsStatic = true;
4695 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
4696 return;
4697 ec.IsStatic = false;
4700 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
4702 SourceMethod source = SourceMethod.Create (
4703 Parent, ConstructorBuilder, block);
4706 // Classes can have base initializers and instance field initializers.
4708 if (Parent.Kind == Kind.Class){
4709 if ((ModFlags & Modifiers.STATIC) == 0){
4712 // If we use a "this (...)" constructor initializer, then
4713 // do not emit field initializers, they are initialized in the other constructor
4715 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4716 Parent.EmitFieldInitializers (ec);
4719 if (Initializer != null) {
4720 if (GetObsoleteAttribute (Parent) == null && Parent.GetObsoleteAttribute (Parent.Parent) == null)
4721 Initializer.CheckObsoleteAttribute (Parent, Location);
4722 else
4723 ec.TestObsoleteMethodUsage = false;
4724 Initializer.Emit (ec);
4727 if ((ModFlags & Modifiers.STATIC) != 0)
4728 Parent.EmitFieldInitializers (ec);
4730 if (OptAttributes != null)
4731 OptAttributes.Emit (ec, this);
4733 // If this is a non-static `struct' constructor and doesn't have any
4734 // initializer, it must initialize all of the struct's fields.
4735 if ((Parent.Kind == Kind.Struct) &&
4736 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4737 Block.AddThisVariable (Parent, Location);
4739 ec.EmitTopBlock (block, ParameterInfo, Location);
4741 if (source != null)
4742 source.CloseMethod ();
4744 base.Emit ();
4746 if (declarative_security != null) {
4747 foreach (DictionaryEntry de in declarative_security) {
4748 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4752 block = null;
4755 // Is never override
4756 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4758 return null;
4761 protected override bool VerifyClsCompliance (DeclSpace ds)
4763 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4764 return false;
4767 if (parameter_types.Length > 0) {
4768 ArrayList al = (ArrayList)ds.MemberCache.Members [".ctor"];
4769 if (al.Count > 3)
4770 ds.MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4772 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4773 foreach (Type param in parameter_types) {
4774 if (param.IsArray) {
4775 return true;
4780 has_compliant_args = true;
4781 return true;
4784 #region IMethodData Members
4786 public System.Reflection.CallingConventions CallingConventions {
4787 get {
4788 CallingConventions cc = Parameters.GetCallingConvention ();
4790 if (Parent.Kind == Kind.Class)
4791 if ((ModFlags & Modifiers.STATIC) == 0)
4792 cc |= CallingConventions.HasThis;
4794 // FIXME: How is `ExplicitThis' used in C#?
4796 return cc;
4800 public new Location Location {
4801 get {
4802 return base.Location;
4806 public MemberName MethodName {
4807 get {
4808 return MemberName;
4812 public Type ReturnType {
4813 get {
4814 return MemberType;
4818 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4820 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4821 return new EmitContext (Parent, Location, ig_, null, ModFlags, true);
4824 public ObsoleteAttribute GetObsoleteAttribute ()
4826 return null;
4829 public bool IsExcluded(EmitContext ec)
4831 return false;
4834 GenericMethod IMethodData.GenericMethod {
4835 get {
4836 return null;
4840 #endregion
4843 /// <summary>
4844 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4845 /// </summary>
4846 public interface IMethodData
4848 CallingConventions CallingConventions { get; }
4849 Location Location { get; }
4850 MemberName MethodName { get; }
4851 Type[] ParameterTypes { get; }
4852 Type ReturnType { get; }
4853 GenericMethod GenericMethod { get; }
4855 Attributes OptAttributes { get; }
4856 ToplevelBlock Block { get; }
4858 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4859 ObsoleteAttribute GetObsoleteAttribute ();
4860 string GetSignatureForError (TypeContainer tc);
4861 bool IsExcluded (EmitContext ec);
4862 bool IsClsCompliaceRequired (DeclSpace ds);
4866 // Encapsulates most of the Method's state
4868 public class MethodData {
4870 readonly IMethodData method;
4873 // The return type of this method
4875 public readonly GenericMethod GenericMethod;
4876 public readonly InternalParameters ParameterInfo;
4879 // Are we implementing an interface ?
4881 public bool IsImplementing = false;
4884 // Protected data.
4886 protected MemberBase member;
4887 protected int modifiers;
4888 protected MethodAttributes flags;
4889 protected Type declaring_type;
4890 protected MethodInfo parent_method;
4892 EmitContext ec;
4894 MethodBuilder builder = null;
4895 public MethodBuilder MethodBuilder {
4896 get {
4897 return builder;
4901 public Type DeclaringType {
4902 get {
4903 return declaring_type;
4907 public MethodData (MemberBase member, InternalParameters parameters,
4908 int modifiers, MethodAttributes flags, IMethodData method)
4910 this.member = member;
4911 this.ParameterInfo = parameters;
4912 this.modifiers = modifiers;
4913 this.flags = flags;
4915 this.method = method;
4918 public MethodData (MemberBase member, InternalParameters parameters,
4919 int modifiers, MethodAttributes flags,
4920 IMethodData method, MethodBuilder builder,
4921 GenericMethod generic, MethodInfo parent_method)
4922 : this (member, parameters, modifiers, flags, method)
4924 this.builder = builder;
4925 this.GenericMethod = generic;
4926 this.parent_method = parent_method;
4929 static string RemoveArity (string name)
4931 int start = 0;
4932 StringBuilder sb = new StringBuilder ();
4933 while (start < name.Length) {
4934 int pos = name.IndexOf ('`', start);
4935 if (pos < 0) {
4936 sb.Append (name.Substring (start));
4937 break;
4940 sb.Append (name.Substring (start, pos-start));
4942 pos++;
4943 while ((pos < name.Length) && Char.IsNumber (name [pos]))
4944 pos++;
4946 start = pos;
4949 return sb.ToString ();
4952 public bool Define (TypeContainer container)
4954 MethodInfo implementing = null;
4956 string prefix;
4957 if (member.IsExplicitImpl)
4958 prefix = member.InterfaceType.FullName + ".";
4959 else
4960 prefix = "";
4962 string name = method.MethodName.Basename;
4963 string method_name = prefix + name;
4965 Type[] ParameterTypes = method.ParameterTypes;
4967 if (container.Pending != null){
4968 if (member is Indexer)
4969 implementing = container.Pending.IsInterfaceIndexer (
4970 member.InterfaceType, method.ReturnType, ParameterTypes);
4971 else
4972 implementing = container.Pending.IsInterfaceMethod (
4973 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4975 if (member.InterfaceType != null){
4976 if (implementing == null){
4977 Report.Error (539, method.Location,
4978 "'{0}' in explicit interface declaration is not a member of interface", member.GetSignatureForError () );
4979 return false;
4985 // For implicit implementations, make sure we are public, for
4986 // explicit implementations, make sure we are private.
4988 if (implementing != null){
4990 // Setting null inside this block will trigger a more
4991 // verbose error reporting for missing interface implementations
4993 // The "candidate" function has been flagged already
4994 // but it wont get cleared
4996 if (member.IsExplicitImpl){
4997 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4998 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4999 implementing = null;
5001 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
5002 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
5004 // If this is an interface method implementation,
5005 // check for public accessibility
5007 implementing = null;
5008 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5009 // We may never be private.
5010 implementing = null;
5011 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5013 // We may be protected if we're overriding something.
5015 implementing = null;
5020 // Static is not allowed
5022 if ((modifiers & Modifiers.STATIC) != 0){
5023 implementing = null;
5024 Modifiers.Error_InvalidModifier (method.Location, "static");
5029 // If implementing is still valid, set flags
5031 if (implementing != null){
5033 // When implementing interface methods, set NewSlot
5034 // unless, we are overwriting a method.
5036 if (implementing.DeclaringType.IsInterface){
5037 if ((modifiers & Modifiers.OVERRIDE) == 0)
5038 flags |= MethodAttributes.NewSlot;
5040 flags |=
5041 MethodAttributes.Virtual |
5042 MethodAttributes.HideBySig;
5044 // Set Final unless we're virtual, abstract or already overriding a method.
5045 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5046 flags |= MethodAttributes.Final;
5048 IsImplementing = true;
5051 EmitContext ec = method.CreateEmitContext (container, null);
5053 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
5055 if (builder == null)
5056 return false;
5058 if (container.CurrentType != null)
5059 declaring_type = container.CurrentType;
5060 else
5061 declaring_type = container.TypeBuilder;
5063 if ((modifiers & Modifiers.UNSAFE) != 0)
5064 builder.InitLocals = false;
5066 if (IsImplementing){
5068 // clear the pending implemntation flag
5070 if (member is Indexer) {
5071 container.Pending.ImplementIndexer (
5072 member.InterfaceType, builder, method.ReturnType,
5073 ParameterTypes, member.IsExplicitImpl);
5074 } else
5075 container.Pending.ImplementMethod (
5076 member.InterfaceType, name, method.ReturnType,
5077 ParameterTypes, member.IsExplicitImpl);
5079 if (member.IsExplicitImpl)
5080 container.TypeBuilder.DefineMethodOverride (
5081 builder, implementing);
5085 TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes);
5086 TypeManager.AddMethod (builder, method);
5088 if (GenericMethod != null) {
5089 bool is_override = member.IsExplicitImpl |
5090 ((modifiers & Modifiers.OVERRIDE) != 0);
5092 if (implementing != null)
5093 parent_method = implementing;
5095 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5096 return false;
5099 return true;
5102 /// <summary>
5103 /// Create the MethodBuilder for the method
5104 /// </summary>
5105 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
5107 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
5109 if ((modifiers & extern_static) == extern_static) {
5111 if (method.OptAttributes != null) {
5112 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
5113 if (dllimport_attribute != null) {
5114 flags |= MethodAttributes.PinvokeImpl;
5115 builder = dllimport_attribute.DefinePInvokeMethod (
5116 ec, container.TypeBuilder, method_name, flags,
5117 method.ReturnType, ParameterTypes);
5119 return;
5123 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
5124 // We are more strict than Microsoft and report CS0626 like error
5125 if (method.OptAttributes == null ||
5126 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
5127 Report.Error (626, method.Location, "Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation", method.GetSignatureForError (container));
5128 return;
5132 if (builder == null)
5133 builder = container.TypeBuilder.DefineMethod (
5134 method_name, flags, method.CallingConventions,
5135 method.ReturnType, ParameterTypes);
5136 else
5137 builder.SetGenericMethodSignature (
5138 flags, method.CallingConventions,
5139 method.ReturnType, ParameterTypes);
5143 // Emits the code
5145 public void Emit (TypeContainer container, Attributable kind)
5147 EmitContext ec;
5148 if ((flags & MethodAttributes.PinvokeImpl) == 0)
5149 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
5150 else
5151 ec = method.CreateEmitContext (container, null);
5153 if (method.GetObsoleteAttribute () != null || container.GetObsoleteAttribute (container.Parent) != null)
5154 ec.TestObsoleteMethodUsage = false;
5156 Location loc = method.Location;
5157 Attributes OptAttributes = method.OptAttributes;
5159 if (OptAttributes != null)
5160 OptAttributes.Emit (ec, kind);
5162 if (member is MethodCore)
5163 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
5165 ToplevelBlock block = method.Block;
5168 // abstract or extern methods have no bodies
5170 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
5171 if (block == null)
5172 return;
5175 // abstract or extern methods have no bodies.
5177 if ((modifiers & Modifiers.ABSTRACT) != 0)
5178 Report.Error (
5179 500, method.Location, "Abstract method `" +
5180 TypeManager.CSharpSignature (builder) +
5181 "' can not have a body");
5183 if ((modifiers & Modifiers.EXTERN) != 0)
5184 Report.Error (
5185 179, method.Location, "External method `" +
5186 TypeManager.CSharpSignature (builder) +
5187 "' can not have a body");
5189 return;
5193 // Methods must have a body unless they're extern or abstract
5195 if (block == null) {
5196 Report.Error (
5197 501, method.Location, "Method `" +
5198 TypeManager.CSharpSignature (builder) +
5199 "' must declare a body since it is not marked " +
5200 "abstract or extern");
5201 return;
5204 SourceMethod source = SourceMethod.Create (
5205 container, MethodBuilder, method.Block);
5208 // Handle destructors specially
5210 // FIXME: This code generates buggy code
5212 if (member is Destructor)
5213 EmitDestructor (ec, block);
5214 else
5215 ec.EmitTopBlock (block, ParameterInfo, loc);
5217 if (source != null)
5218 source.CloseMethod ();
5221 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5223 ILGenerator ig = ec.ig;
5225 Label finish = ig.DefineLabel ();
5227 block.SetDestructor ();
5229 ig.BeginExceptionBlock ();
5230 ec.ReturnLabel = finish;
5231 ec.HasReturnLabel = true;
5232 ec.EmitTopBlock (block, null, method.Location);
5234 // ig.MarkLabel (finish);
5235 ig.BeginFinallyBlock ();
5237 if (ec.ContainerType.BaseType != null) {
5238 Expression member_lookup = Expression.MemberLookup (
5239 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5240 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5242 if (member_lookup != null){
5243 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5245 ig.Emit (OpCodes.Ldarg_0);
5246 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5250 ig.EndExceptionBlock ();
5251 //ig.MarkLabel (ec.ReturnLabel);
5252 ig.Emit (OpCodes.Ret);
5256 public class Destructor : Method {
5258 public Destructor (TypeContainer ds, Expression return_type, int mod, string name,
5259 Parameters parameters, Attributes attrs, Location l)
5260 : base (ds, null, return_type, mod, false, new MemberName (name),
5261 parameters, attrs, l)
5264 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5266 if (a.Type == TypeManager.conditional_attribute_type) {
5267 Report.Error (577, Location, "Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation", GetSignatureForError ());
5268 return;
5271 base.ApplyAttributeBuilder (a, cb);
5275 abstract public class MemberBase : MemberCore {
5276 public Expression Type;
5278 public MethodAttributes flags;
5280 protected readonly int explicit_mod_flags;
5283 // The "short" name of this property / indexer / event. This is the
5284 // name without the explicit interface.
5286 public string ShortName;
5289 // The type of this property / indexer / event
5291 public Type MemberType;
5294 // If true, this is an explicit interface implementation
5296 public bool IsExplicitImpl = false;
5299 // The name of the interface we are explicitly implementing
5301 public MemberName ExplicitInterfaceName = null;
5304 // Whether this is an interface member.
5306 public bool IsInterface;
5309 // If true, the interface type we are explicitly implementing
5311 public Type InterfaceType = null;
5314 // The constructor is only exposed to our children
5316 protected MemberBase (TypeContainer parent, Expression type, int mod,
5317 int allowed_mod, int def_mod, MemberName name,
5318 Attributes attrs, Location loc)
5319 : base (parent, name, attrs, loc)
5321 explicit_mod_flags = mod;
5322 Type = type;
5323 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
5325 // Check for explicit interface implementation
5326 if (MemberName.Left != null) {
5327 ExplicitInterfaceName = MemberName.Left;
5328 ShortName = MemberName.Name;
5329 IsExplicitImpl = true;
5330 } else
5331 ShortName = Name;
5334 protected virtual bool CheckBase ()
5336 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.Kind == Kind.Struct) {
5337 Report.Error (666, Location, "Protected member in struct declaration");
5338 return false;
5341 if ((RootContext.WarningLevel >= 4) &&
5342 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5343 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5344 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5345 Report.Warning (628, Location, "'{0}': new protected member declared in sealed class", GetSignatureForError (Parent));
5348 return true;
5351 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
5353 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
5355 bool error = false;
5357 foreach (Type partype in parameters){
5358 if (partype == TypeManager.void_type) {
5359 Report.Error (
5360 1547, Location, "Keyword 'void' cannot " +
5361 "be used in this context");
5362 return false;
5365 if (partype.IsPointer){
5366 if (!UnsafeOK (ds))
5367 error = true;
5368 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
5369 error = true;
5372 if (ds.AsAccessible (partype, ModFlags))
5373 continue;
5375 if (this is Indexer)
5376 Report.Error (55, Location,
5377 "Inconsistent accessibility: parameter type `" +
5378 TypeManager.CSharpName (partype) + "' is less " +
5379 "accessible than indexer `" + Name + "'");
5380 else if ((this is Method) && ((Method) this).IsOperator)
5381 Report.Error (57, Location,
5382 "Inconsistent accessibility: parameter type `" +
5383 TypeManager.CSharpName (partype) + "' is less " +
5384 "accessible than operator `" + Name + "'");
5385 else
5386 Report.Error (51, Location,
5387 "Inconsistent accessibility: parameter type `" +
5388 TypeManager.CSharpName (partype) + "' is less " +
5389 "accessible than method `" + Name + "'");
5390 error = true;
5393 return !error;
5396 protected virtual bool DoDefineBase ()
5398 EmitContext ec = Parent.EmitContext;
5399 if (ec == null)
5400 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5402 if (Name == null)
5403 throw new InternalErrorException ();
5405 if (IsInterface) {
5406 ModFlags = Modifiers.PUBLIC |
5407 Modifiers.ABSTRACT |
5408 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
5410 flags = MethodAttributes.Public |
5411 MethodAttributes.Abstract |
5412 MethodAttributes.HideBySig |
5413 MethodAttributes.NewSlot |
5414 MethodAttributes.Virtual;
5415 } else {
5416 if (!Parent.MethodModifiersValid (this))
5417 return false;
5419 flags = Modifiers.MethodAttr (ModFlags);
5422 return true;
5425 protected virtual bool DoDefine (DeclSpace decl)
5427 EmitContext ec = decl.EmitContext;
5428 if (ec == null)
5429 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5431 ec.InUnsafe = InUnsafe;
5433 // Lookup Type, verify validity
5434 bool old_unsafe = ec.InUnsafe;
5435 ec.InUnsafe = InUnsafe;
5436 TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
5437 ec.InUnsafe = old_unsafe;
5439 if (texpr == null)
5440 return false;
5442 MemberType = texpr.Type;
5444 if ((Parent.ModFlags & Modifiers.SEALED) != 0){
5445 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
5446 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
5447 return false;
5451 // verify accessibility
5452 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5453 Report.SymbolRelatedToPreviousError (MemberType);
5454 if (this is Property)
5455 Report.Error (53, Location,
5456 "Inconsistent accessibility: property type `" +
5457 TypeManager.CSharpName (MemberType) + "' is less " +
5458 "accessible than property `" + GetSignatureForError () + "'");
5459 else if (this is Indexer)
5460 Report.Error (54, Location,
5461 "Inconsistent accessibility: indexer return type `" +
5462 TypeManager.CSharpName (MemberType) + "' is less " +
5463 "accessible than indexer `" + Name + "'");
5464 else if (this is MethodCore) {
5465 if (this is Operator)
5466 Report.Error (56, Location,
5467 "Inconsistent accessibility: return type `" +
5468 TypeManager.CSharpName (MemberType) + "' is less " +
5469 "accessible than operator `" + Name + "'");
5470 else
5471 Report.Error (50, Location,
5472 "Inconsistent accessibility: return type `" +
5473 TypeManager.CSharpName (MemberType) + "' is less " +
5474 "accessible than method `" + Name + "'");
5475 } else {
5476 Report.Error (52, Location,
5477 "Inconsistent accessibility: field type `" +
5478 TypeManager.CSharpName (MemberType) + "' is less " +
5479 "accessible than field `" + Name + "'");
5481 return false;
5484 if (MemberType.IsPointer && !UnsafeOK (Parent))
5485 return false;
5487 if (IsExplicitImpl) {
5488 Expression expr = ExplicitInterfaceName.GetTypeExpression (Location);
5489 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (ec);
5490 if (iface_texpr == null)
5491 return false;
5493 InterfaceType = iface_texpr.Type;
5495 if (!InterfaceType.IsInterface) {
5496 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5497 return false;
5500 if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
5501 return false;
5503 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5506 return true;
5509 /// <summary>
5510 /// The name of the member can be changed during definition (see IndexerName attribute)
5511 /// </summary>
5512 protected virtual void UpdateMemberName ()
5514 MemberName.Name = ShortName;
5517 public override string GetSignatureForError (TypeContainer tc)
5519 return String.Concat (tc.Name, '.', base.GetSignatureForError (tc));
5522 protected bool IsTypePermitted ()
5524 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5525 Report.Error (610, Location, "Field or property cannot be of type '{0}'", TypeManager.CSharpName (MemberType));
5526 return false;
5528 return true;
5531 protected override bool VerifyClsCompliance(DeclSpace ds)
5533 if (base.VerifyClsCompliance (ds)) {
5534 return true;
5537 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
5538 Report.Error (3010, Location, "'{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
5540 return false;
5543 protected override void VerifyObsoleteAttribute()
5545 CheckUsageOfObsoleteAttribute (MemberType);
5550 // Fields and Events both generate FieldBuilders, we use this to share
5551 // their common bits. This is also used to flag usage of the field
5553 abstract public class FieldBase : MemberBase {
5554 public FieldBuilder FieldBuilder;
5555 public Status status;
5557 [Flags]
5558 public enum Status : byte {
5559 ASSIGNED = 1,
5560 USED = 2,
5561 HAS_OFFSET = 4 // Used by FieldMember.
5564 static string[] attribute_targets = new string [] { "field" };
5566 /// <summary>
5567 /// Symbol with same name in base class/struct
5568 /// </summary>
5569 public MemberInfo conflict_symbol;
5572 // The constructor is only exposed to our children
5574 protected FieldBase (TypeContainer parent, Expression type, int mod,
5575 int allowed_mod, MemberName name, object init,
5576 Attributes attrs, Location loc)
5577 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
5578 name, attrs, loc)
5580 this.init = init;
5583 public override AttributeTargets AttributeTargets {
5584 get {
5585 return AttributeTargets.Field;
5589 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5591 if (a.Type == TypeManager.marshal_as_attr_type) {
5592 UnmanagedMarshal marshal = a.GetMarshal (this);
5593 if (marshal != null) {
5594 FieldBuilder.SetMarshal (marshal);
5596 return;
5599 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5600 a.Error_InvalidSecurityParent ();
5601 return;
5604 FieldBuilder.SetCustomAttribute (cb);
5608 // Whether this field has an initializer.
5610 public bool HasInitializer {
5611 get {
5612 return init != null;
5616 protected readonly Object init;
5617 // Private.
5618 Expression init_expr;
5619 bool init_expr_initialized = false;
5621 protected override bool CheckGenericOverride (MethodInfo method, string name)
5623 return true;
5627 // Resolves and returns the field initializer.
5629 public Expression GetInitializerExpression (EmitContext ec)
5631 if (init_expr_initialized)
5632 return init_expr;
5634 Expression e;
5635 if (init is Expression)
5636 e = (Expression) init;
5637 else
5638 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
5640 ec.IsFieldInitializer = true;
5641 e = e.DoResolve (ec);
5642 ec.IsFieldInitializer = false;
5644 init_expr = e;
5645 init_expr_initialized = true;
5647 return init_expr;
5650 protected override bool CheckBase ()
5652 if (!base.CheckBase ())
5653 return false;
5655 // TODO: Implement
5656 if (IsInterface)
5657 return true;
5659 conflict_symbol = Parent.FindBaseMemberWithSameName (Name, false);
5660 if (conflict_symbol == null) {
5661 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5662 Report.Warning (109, Location, "The member '{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError (Parent));
5664 return true;
5667 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5668 Report.SymbolRelatedToPreviousError (conflict_symbol);
5669 Report.Warning (108, Location, "The keyword new is required on '{0}' because it hides inherited member", GetSignatureForError (Parent));
5672 return true;
5675 protected override bool DoDefine (DeclSpace ds)
5677 if (!base.DoDefine (ds))
5678 return false;
5680 if (MemberType == TypeManager.void_type) {
5681 Report.Error (1547, Location,
5682 "Keyword 'void' cannot be used in this context");
5683 return false;
5685 return true;
5688 public override string GetSignatureForError ()
5690 if (FieldBuilder == null) {
5691 return base.GetSignatureForError (Parent);
5693 return TypeManager.GetFullNameSignature (FieldBuilder);
5696 public override string[] ValidAttributeTargets {
5697 get {
5698 return attribute_targets;
5702 protected override bool VerifyClsCompliance (DeclSpace ds)
5704 if (!base.VerifyClsCompliance (ds))
5705 return false;
5707 if (FieldBuilder == null) {
5708 return true;
5711 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
5712 Report.Error (3003, Location, "Type of '{0}' is not CLS-compliant", GetSignatureForError ());
5714 return true;
5718 public void SetAssigned ()
5720 status |= Status.ASSIGNED;
5724 public abstract class FieldMember: FieldBase
5728 protected FieldMember (TypeContainer parent, Expression type, int mod,
5729 int allowed_mod, MemberName name, object init, Attributes attrs, Location loc)
5730 : base (parent, type, mod, allowed_mod, name, init, attrs, loc)
5734 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5736 if (a.Type == TypeManager.field_offset_attribute_type)
5738 status |= Status.HAS_OFFSET;
5740 if (!Parent.HasExplicitLayout) {
5741 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5742 return;
5745 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5746 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5747 return;
5750 base.ApplyAttributeBuilder (a, cb);
5754 public override bool Define()
5756 EmitContext ec = Parent.EmitContext;
5757 if (ec == null)
5758 throw new InternalErrorException ("FieldMember.Define called too early");
5760 bool old_unsafe = ec.InUnsafe;
5761 ec.InUnsafe = InUnsafe;
5762 TypeExpr texpr = Type.ResolveAsTypeTerminal (ec);
5763 ec.InUnsafe = old_unsafe;
5764 if (texpr == null)
5765 return false;
5767 MemberType = texpr.Type;
5769 ec.InUnsafe = old_unsafe;
5771 if (MemberType == TypeManager.void_type) {
5772 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5773 return false;
5776 if (!CheckBase ())
5777 return false;
5779 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5780 Report.Error (52, Location,
5781 "Inconsistent accessibility: field type `" +
5782 TypeManager.CSharpName (MemberType) + "' is less " +
5783 "accessible than field `" + Name + "'");
5784 return false;
5787 if (!IsTypePermitted ())
5788 return false;
5790 if (MemberType.IsPointer && !UnsafeOK (Parent))
5791 return false;
5793 return true;
5796 public override void Emit ()
5798 if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
5799 Report.Error (625, Location, "'{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5802 base.Emit ();
5806 // Represents header string for documentation comment.
5808 public override string DocCommentHeader {
5809 get { return "F:"; }
5814 // The Field class is used to represents class/struct fields during parsing.
5816 public class Field : FieldMember {
5817 // <summary>
5818 // Modifiers allowed in a class declaration
5819 // </summary>
5820 const int AllowedModifiers =
5821 Modifiers.NEW |
5822 Modifiers.PUBLIC |
5823 Modifiers.PROTECTED |
5824 Modifiers.INTERNAL |
5825 Modifiers.PRIVATE |
5826 Modifiers.STATIC |
5827 Modifiers.VOLATILE |
5828 Modifiers.UNSAFE |
5829 Modifiers.READONLY;
5831 public Field (TypeContainer parent, Expression type, int mod, string name,
5832 Object expr_or_array_init, Attributes attrs, Location loc)
5833 : base (parent, type, mod, AllowedModifiers, new MemberName (name),
5834 expr_or_array_init, attrs, loc)
5838 public override bool Define ()
5840 if (!base.Define ())
5841 return false;
5843 if (RootContext.WarningLevel > 1){
5844 Type ptype = Parent.TypeBuilder.BaseType;
5846 // ptype is only null for System.Object while compiling corlib.
5847 if (ptype != null){
5848 TypeContainer.FindMembers (
5849 ptype, MemberTypes.Method,
5850 BindingFlags.Public |
5851 BindingFlags.Static | BindingFlags.Instance,
5852 System.Type.FilterName, Name);
5856 if ((ModFlags & Modifiers.VOLATILE) != 0){
5857 if (!MemberType.IsClass){
5858 Type vt = MemberType;
5860 if (TypeManager.IsEnumType (vt))
5861 vt = TypeManager.EnumToUnderlying (MemberType);
5863 if (!((vt == TypeManager.bool_type) ||
5864 (vt == TypeManager.sbyte_type) ||
5865 (vt == TypeManager.byte_type) ||
5866 (vt == TypeManager.short_type) ||
5867 (vt == TypeManager.ushort_type) ||
5868 (vt == TypeManager.int32_type) ||
5869 (vt == TypeManager.uint32_type) ||
5870 (vt == TypeManager.char_type) ||
5871 (vt == TypeManager.float_type) ||
5872 (!vt.IsValueType))){
5873 Report.Error (
5874 677, Location, Parent.MakeName (Name) +
5875 " A volatile field can not be of type `" +
5876 TypeManager.CSharpName (vt) + "'");
5877 return false;
5881 if ((ModFlags & Modifiers.READONLY) != 0){
5882 Report.Error (
5883 678, Location,
5884 "A field can not be both volatile and readonly");
5885 return false;
5889 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5891 if (Parent.Kind == Kind.Struct &&
5892 ((fa & FieldAttributes.Static) == 0) &&
5893 MemberType == Parent.TypeBuilder &&
5894 !TypeManager.IsBuiltinType (MemberType)){
5895 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
5896 "' causes a cycle in the structure layout");
5897 return false;
5900 try {
5901 FieldBuilder = Parent.TypeBuilder.DefineField (
5902 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5904 TypeManager.RegisterFieldBase (FieldBuilder, this);
5906 catch (ArgumentException) {
5907 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5908 return false;
5911 return true;
5914 public override void Emit ()
5916 if (OptAttributes != null) {
5917 EmitContext ec = new EmitContext (
5918 Parent, Location, null, FieldBuilder.FieldType,
5919 ModFlags);
5920 OptAttributes.Emit (ec, this);
5923 base.Emit ();
5928 // `set' and `get' accessors are represented with an Accessor.
5930 public class Accessor {
5932 // Null if the accessor is empty, or a Block if not
5934 public const int AllowedModifiers =
5935 Modifiers.PUBLIC |
5936 Modifiers.PROTECTED |
5937 Modifiers.INTERNAL |
5938 Modifiers.PRIVATE;
5940 public ToplevelBlock Block;
5941 public Attributes Attributes;
5942 public Location Location;
5943 public int ModFlags;
5945 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
5947 Block = b;
5948 Attributes = attrs;
5949 Location = loc;
5950 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
5955 // Ooouh Martin, templates are missing here.
5956 // When it will be possible move here a lot of child code and template method type.
5957 public abstract class AbstractPropertyEventMethod: MemberCore, IMethodData {
5958 protected MethodData method_data;
5959 protected ToplevelBlock block;
5960 protected ListDictionary declarative_security;
5962 // The accessor are created event if they are not wanted.
5963 // But we need them because their names are reserved.
5964 // Field says whether accessor will be emited or not
5965 public readonly bool IsDummy;
5967 protected readonly string prefix;
5969 ReturnParameter return_attributes;
5971 public AbstractPropertyEventMethod (MemberBase member, string prefix)
5972 : base (null, SetupName (prefix, member), null, member.Location)
5974 this.prefix = prefix;
5975 IsDummy = true;
5978 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
5979 string prefix)
5980 : base (null, SetupName (prefix, member),
5981 accessor.Attributes, accessor.Location)
5983 this.prefix = prefix;
5984 this.block = accessor.Block;
5987 static MemberName SetupName (string prefix, MemberBase member)
5989 MemberName name = member.MemberName.Clone ();
5990 name.Name = prefix + member.ShortName;
5991 return name;
5994 public void UpdateName (MemberBase member)
5996 MemberName.Name = prefix + member.ShortName;
5999 #region IMethodData Members
6001 public ToplevelBlock Block {
6002 get {
6003 return block;
6006 set {
6007 block = value;
6011 public CallingConventions CallingConventions {
6012 get {
6013 return CallingConventions.Standard;
6017 public bool IsExcluded (EmitContext ec)
6019 return false;
6022 GenericMethod IMethodData.GenericMethod {
6023 get {
6024 return null;
6028 public MemberName MethodName {
6029 get {
6030 return MemberName;
6034 public abstract ObsoleteAttribute GetObsoleteAttribute ();
6035 public abstract Type[] ParameterTypes { get; }
6036 public abstract Type ReturnType { get; }
6037 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
6039 #endregion
6041 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
6043 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
6044 a.Type == TypeManager.conditional_attribute_type) {
6045 Report.Error (1667, a.Location, "'{0}' is not valid on property or event accessors. It is valid on {1} declarations only", TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6046 return;
6049 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
6050 if (declarative_security == null)
6051 declarative_security = new ListDictionary ();
6052 a.ExtractSecurityPermissionSet (declarative_security);
6053 return;
6056 if (a.Target == AttributeTargets.Method) {
6057 method_data.MethodBuilder.SetCustomAttribute (cb);
6058 return;
6061 if (a.Target == AttributeTargets.ReturnValue) {
6062 if (return_attributes == null)
6063 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6065 return_attributes.ApplyAttributeBuilder (a, cb);
6066 return;
6069 ApplyToExtraTarget (a, cb);
6072 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
6074 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
6077 public override bool Define()
6079 throw new NotSupportedException ();
6082 public virtual void Emit (TypeContainer container)
6084 method_data.Emit (container, this);
6086 if (declarative_security != null) {
6087 foreach (DictionaryEntry de in declarative_security) {
6088 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6092 block = null;
6095 public override bool IsClsCompliaceRequired(DeclSpace ds)
6097 return false;
6100 public bool IsDuplicateImplementation (MethodCore method)
6102 if (Name != method.Name)
6103 return false;
6105 Type[] param_types = method.ParameterTypes;
6107 if (param_types.Length != ParameterTypes.Length)
6108 return false;
6110 for (int i = 0; i < param_types.Length; i++)
6111 if (param_types [i] != ParameterTypes [i])
6112 return false;
6114 Report.SymbolRelatedToPreviousError (method);
6115 Report.Error (111, Location, "Type '{0}' already defines a member called '{1}' with " +
6116 "the same parameter types", Parent.Name, Name);
6117 return true;
6120 public new Location Location {
6121 get {
6122 return base.Location;
6127 // Represents header string for documentation comment.
6129 public override string DocCommentHeader {
6130 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6133 protected override void VerifyObsoleteAttribute()
6140 // Properties and Indexers both generate PropertyBuilders, we use this to share
6141 // their common bits.
6143 abstract public class PropertyBase : MethodCore {
6145 public class GetMethod: PropertyMethod
6147 static string[] attribute_targets = new string [] { "method", "return" };
6148 Parameters parameters;
6150 public GetMethod (MethodCore method):
6151 base (method, "get_")
6155 public GetMethod (MethodCore method, Accessor accessor):
6156 base (method, accessor, "get_")
6160 public GetMethod (MethodCore method, Parameters parameters):
6161 base (method, "get_")
6163 this.parameters = parameters;
6166 public GetMethod (MethodCore method, Accessor accessor, Parameters parameters):
6167 base (method, accessor, "get_")
6169 this.parameters = parameters;
6172 protected virtual InternalParameters GetParameterInfo (EmitContext ec)
6174 if (parameters == null) {
6175 Parameter [] parms = new Parameter [1];
6176 parms [0] = new Parameter (method.Type, "Screwed", Parameter.Modifier.NONE, null);
6177 parameters = new Parameters (parms, null, method.Location);
6180 Type [] types = parameters.GetParameterInfo (ec);
6181 return new InternalParameters (types, parameters);
6184 public override MethodBuilder Define(TypeContainer container)
6186 base.Define (container);
6188 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
6190 if (!method_data.Define (container))
6191 return null;
6193 return method_data.MethodBuilder;
6196 public override string GetSignatureForError (TypeContainer tc)
6198 return String.Concat (base.GetSignatureForError (tc), ".get");
6201 public override Type ReturnType {
6202 get {
6203 return method.MemberType;
6207 public override string[] ValidAttributeTargets {
6208 get {
6209 return attribute_targets;
6214 public class SetMethod: PropertyMethod {
6216 static string[] attribute_targets = new string [] { "method", "param", "return" };
6217 ImplicitParameter param_attr;
6219 Parameters parameters;
6221 public SetMethod (MethodCore method):
6222 base (method, "set_")
6226 public SetMethod (MethodCore method, Accessor accessor):
6227 base (method, accessor, "set_")
6231 public SetMethod (MethodCore method, Parameters parameters):
6232 base (method, "set_")
6234 this.parameters = parameters;
6237 public SetMethod (MethodCore method, Accessor accessor, Parameters parameters):
6238 base (method, accessor, "set_")
6240 this.parameters = parameters;
6242 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6244 if (a.Target == AttributeTargets.Parameter) {
6245 if (param_attr == null)
6246 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6248 param_attr.ApplyAttributeBuilder (a, cb);
6249 return;
6252 base.ApplyAttributeBuilder (a, cb);
6255 protected virtual InternalParameters GetParameterInfo (EmitContext ec)
6258 if (parameters == null) {
6259 Parameter [] parms = new Parameter [1];
6260 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
6261 parameters = new Parameters (parms, null, method.Location);
6264 bool old_unsafe = ec.InUnsafe;
6265 ec.InUnsafe = InUnsafe;
6266 Type [] types = parameters.GetParameterInfo (ec);
6267 ec.InUnsafe = old_unsafe;
6269 return new InternalParameters (types, parameters);
6272 public override MethodBuilder Define (TypeContainer container)
6274 if (container.EmitContext == null)
6275 throw new InternalErrorException ("SetMethod.Define called too early");
6277 base.Define (container);
6279 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
6281 if (!method_data.Define (container))
6282 return null;
6284 return method_data.MethodBuilder;
6287 public override string GetSignatureForError (TypeContainer tc)
6289 return String.Concat (base.GetSignatureForError (tc), ".set");
6292 public override Type[] ParameterTypes {
6293 get {
6294 return new Type[] { method.MemberType };
6298 public override Type ReturnType {
6299 get {
6300 return TypeManager.void_type;
6304 public override string[] ValidAttributeTargets {
6305 get {
6306 return attribute_targets;
6311 static string[] attribute_targets = new string [] { "property" };
6313 public abstract class PropertyMethod: AbstractPropertyEventMethod {
6314 protected readonly MethodCore method;
6315 protected MethodAttributes flags;
6317 public PropertyMethod (MethodCore method, string prefix)
6318 : base (method, prefix)
6320 this.method = method;
6321 Parent = method.Parent;
6324 public PropertyMethod (MethodCore method, Accessor accessor, string prefix)
6325 : base (method, accessor, prefix)
6327 this.method = method;
6328 Parent = method.Parent;
6329 this.ModFlags = accessor.ModFlags;
6331 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6332 Report.FeatureIsNotStandardized (Location, "accessor modifiers");
6333 Environment.Exit (1);
6337 public override AttributeTargets AttributeTargets {
6338 get {
6339 return AttributeTargets.Method;
6343 public override bool IsClsCompliaceRequired(DeclSpace ds)
6345 return method.IsClsCompliaceRequired (ds);
6348 public InternalParameters ParameterInfo
6350 get {
6351 return method_data.ParameterInfo;
6355 public virtual MethodBuilder Define (TypeContainer container)
6358 // Check for custom access modifier
6360 if (ModFlags == 0) {
6361 ModFlags = method.ModFlags;
6362 flags = method.flags;
6363 } else {
6364 CheckModifiers (container, ModFlags);
6365 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6366 flags = Modifiers.MethodAttr (ModFlags);
6367 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6370 return null;
6374 public override Type[] ParameterTypes {
6375 get {
6376 return TypeManager.NoTypes;
6380 public override EmitContext CreateEmitContext (TypeContainer tc,
6381 ILGenerator ig)
6383 return new EmitContext (
6384 tc, method.ds, method.Location, ig, ReturnType,
6385 method.ModFlags, false);
6388 public override ObsoleteAttribute GetObsoleteAttribute ()
6390 return method.GetObsoleteAttribute (method.ds);
6393 public override string GetSignatureForError (TypeContainer tc)
6395 return String.Concat (tc.Name, '.', method.Name);
6398 void CheckModifiers (TypeContainer container, int modflags)
6400 int flags = 0;
6401 int mflags = method.ModFlags & Modifiers.Accessibility;
6403 if ((mflags & Modifiers.PUBLIC) != 0) {
6404 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6406 else if ((mflags & Modifiers.PROTECTED) != 0) {
6407 if ((mflags & Modifiers.INTERNAL) != 0)
6408 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6410 flags |= Modifiers.PRIVATE;
6412 else if ((mflags & Modifiers.INTERNAL) != 0)
6413 flags |= Modifiers.PRIVATE;
6415 if ((mflags == modflags) || (modflags & (~flags)) != 0)
6416 Report.Error (273, Location, "{0}: accessibility modifier must be more restrictive than the property or indexer",
6417 GetSignatureForError (container));
6420 public override bool MarkForDuplicationCheck ()
6422 caching_flags |= Flags.TestMethodDuplication;
6423 return true;
6427 public PropertyMethod Get, Set;
6428 public PropertyBuilder PropertyBuilder;
6429 public MethodBuilder GetBuilder, SetBuilder;
6431 protected EmitContext ec;
6433 public PropertyBase (TypeContainer parent, Expression type, int mod_flags,
6434 int allowed_mod, bool is_iface, MemberName name,
6435 Parameters parameters, Attributes attrs,
6436 Location loc)
6437 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
6438 attrs, parameters, loc)
6442 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6444 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6445 a.Error_InvalidSecurityParent ();
6446 return;
6449 PropertyBuilder.SetCustomAttribute (cb);
6452 public override AttributeTargets AttributeTargets {
6453 get {
6454 return AttributeTargets.Property;
6458 public override bool Define ()
6460 if (!DoDefine (Parent))
6461 return false;
6463 if (!IsTypePermitted ())
6464 return false;
6466 return true;
6469 protected override bool DoDefine (DeclSpace ds)
6471 if (!base.DoDefine (ds))
6472 return false;
6475 // Accessors modifiers check
6477 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6478 Report.Error (274, Location, "'{0}': cannot specify accessibility modifiers for both accessors of the property or indexer.",
6479 GetSignatureForError ());
6480 return false;
6483 if ((Get.IsDummy || Set.IsDummy)
6484 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6485 Report.Error (276, Location,
6486 "'{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor.",
6487 GetSignatureForError ());
6488 return false;
6491 if (MemberType.IsAbstract && MemberType.IsSealed) {
6492 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6493 return false;
6496 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
6497 return true;
6500 public override string GetSignatureForError()
6502 if (PropertyBuilder == null)
6503 return GetSignatureForError (Parent);
6505 return TypeManager.CSharpSignature (PropertyBuilder, false);
6508 protected override bool CheckForDuplications ()
6510 ArrayList ar = Parent.Indexers;
6511 if (ar != null) {
6512 int arLen = ar.Count;
6514 for (int i = 0; i < arLen; i++) {
6515 Indexer m = (Indexer) ar [i];
6516 if (IsDuplicateImplementation (m))
6517 return false;
6521 ar = Parent.Properties;
6522 if (ar != null) {
6523 int arLen = ar.Count;
6525 for (int i = 0; i < arLen; i++) {
6526 Property m = (Property) ar [i];
6527 if (IsDuplicateImplementation (m))
6528 return false;
6532 return true;
6535 // TODO: rename to Resolve......
6536 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
6538 PropertyInfo base_property = container.BaseCache.FindMemberToOverride (
6539 container.TypeBuilder, Name, ParameterTypes, true) as PropertyInfo;
6541 if (base_property == null)
6542 return null;
6544 base_ret_type = base_property.PropertyType;
6545 MethodInfo get_accessor = base_property.GetGetMethod (true);
6546 MethodInfo set_accessor = base_property.GetSetMethod (true);
6547 MethodAttributes get_accessor_access, set_accessor_access;
6549 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6550 if (Get != null && !Get.IsDummy && get_accessor == null) {
6551 Report.SymbolRelatedToPreviousError (base_property);
6552 Report.Error (545, Location, "'{0}': cannot override because '{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6555 if (Set != null && !Set.IsDummy && set_accessor == null) {
6556 Report.SymbolRelatedToPreviousError (base_property);
6557 Report.Error (546, Location, "'{0}': cannot override because '{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6562 // Check base class accessors access
6564 get_accessor_access = set_accessor_access = 0;
6565 if ((ModFlags & Modifiers.NEW) == 0) {
6566 if (get_accessor != null) {
6567 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6568 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6570 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6571 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6572 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6575 if (set_accessor != null) {
6576 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6577 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6579 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6580 Report.Error (507, Location, "'{0}' can't change the access modifiers when overriding inherited member '{1}'",
6581 GetSignatureForError (container), TypeManager.GetFullNameSignature (base_property));
6586 // Get the less restrictive access
6588 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6591 public override void Emit ()
6594 // The PropertyBuilder can be null for explicit implementations, in that
6595 // case, we do not actually emit the ".property", so there is nowhere to
6596 // put the attribute
6598 if (PropertyBuilder != null && OptAttributes != null)
6599 OptAttributes.Emit (ec, this);
6601 if (!Get.IsDummy)
6602 Get.Emit (Parent);
6604 if (!Set.IsDummy)
6605 Set.Emit (Parent);
6607 base.Emit ();
6610 /// <summary>
6611 /// Tests whether accessors are not in collision with some method (CS0111)
6612 /// </summary>
6613 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6615 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6618 protected override void UpdateMemberName ()
6620 base.UpdateMemberName ();
6622 Get.UpdateName (this);
6623 Set.UpdateName (this);
6626 protected override bool VerifyClsCompliance (DeclSpace ds)
6628 if (!base.VerifyClsCompliance (ds))
6629 return false;
6631 if ((Get.ModFlags != ModFlags && !Get.IsDummy) || (Set.ModFlags != ModFlags && !Set.IsDummy)) {
6632 Report.Error (3025, Get.ModFlags != ModFlags ? Get.Location : Set.Location,
6633 "CLS-compliant accessors must have the same accessibility as their property");
6635 return true;
6638 public override string[] ValidAttributeTargets {
6639 get {
6640 return attribute_targets;
6645 // Represents header string for documentation comment.
6647 public override string DocCommentHeader {
6648 get { return "P:"; }
6652 public class Property : PropertyBase, IIteratorContainer {
6653 const int AllowedModifiers =
6654 Modifiers.NEW |
6655 Modifiers.PUBLIC |
6656 Modifiers.PROTECTED |
6657 Modifiers.INTERNAL |
6658 Modifiers.PRIVATE |
6659 Modifiers.STATIC |
6660 Modifiers.SEALED |
6661 Modifiers.OVERRIDE |
6662 Modifiers.ABSTRACT |
6663 Modifiers.UNSAFE |
6664 Modifiers.EXTERN |
6665 Modifiers.METHOD_YIELDS |
6666 Modifiers.VIRTUAL;
6668 const int AllowedInterfaceModifiers =
6669 Modifiers.NEW;
6671 public Property (TypeContainer parent, Expression type, int mod_flags,
6672 bool is_iface, MemberName name, Attributes attrs,
6673 Accessor get_block, Accessor set_block, Location loc)
6674 : base (parent, type, mod_flags,
6675 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6676 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6677 loc)
6679 if (get_block == null)
6680 Get = new GetMethod (this);
6681 else
6682 Get = new GetMethod (this, get_block);
6684 if (set_block == null)
6685 Set = new SetMethod (this);
6686 else
6687 Set = new SetMethod (this, set_block);
6690 public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
6691 MemberName name, Attributes attrs, Parameters get_params, Accessor get_block,
6692 Parameters set_params, Accessor set_block, Location loc)
6693 : base (ds, type, mod,
6694 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6695 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6696 loc)
6698 if (get_block == null)
6699 Get = new GetMethod (this, get_params);
6700 else
6701 Get = new GetMethod (this, get_block, get_params);
6703 if (set_block == null)
6704 Set = new SetMethod (this, set_params);
6705 else
6706 Set = new SetMethod (this, set_block, set_params);
6709 public override bool Define ()
6711 if (!DoDefineBase ())
6712 return false;
6714 if (!base.Define ())
6715 return false;
6717 if (!CheckBase ())
6718 return false;
6720 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6722 if (!Get.IsDummy) {
6724 GetBuilder = Get.Define (Parent);
6725 if (GetBuilder == null)
6726 return false;
6729 // Setup iterator if we are one
6731 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
6732 Iterator iterator = new Iterator (
6733 Parent, "get", MemberType,
6734 TypeManager.NoTypes, Get.ParameterInfo,
6735 ModFlags, Get.Block, Location);
6737 if (!iterator.DefineIterator ())
6738 return false;
6739 Get.Block = iterator.Block;
6743 if (!Set.IsDummy) {
6744 SetBuilder = Set.Define (Parent);
6745 if (SetBuilder == null)
6746 return false;
6748 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
6751 // FIXME - PropertyAttributes.HasDefault ?
6753 PropertyAttributes prop_attr = PropertyAttributes.None;
6754 if (!IsInterface)
6755 prop_attr |= PropertyAttributes.RTSpecialName |
6756 PropertyAttributes.SpecialName;
6758 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6759 Name, prop_attr, MemberType, null);
6761 if (!Get.IsDummy)
6762 PropertyBuilder.SetGetMethod (GetBuilder);
6764 if (!Set.IsDummy)
6765 PropertyBuilder.SetSetMethod (SetBuilder);
6767 TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
6768 return true;
6771 public void SetYields ()
6773 ModFlags |= Modifiers.METHOD_YIELDS;
6777 /// </summary>
6778 /// Gigantic workaround for lameness in SRE follows :
6779 /// This class derives from EventInfo and attempts to basically
6780 /// wrap around the EventBuilder so that FindMembers can quickly
6781 /// return this in it search for members
6782 /// </summary>
6783 public class MyEventBuilder : EventInfo {
6786 // We use this to "point" to our Builder which is
6787 // not really a MemberInfo
6789 EventBuilder MyBuilder;
6792 // We "catch" and wrap these methods
6794 MethodInfo raise, remove, add;
6796 EventAttributes attributes;
6797 Type declaring_type, reflected_type, event_type;
6798 string name;
6800 Event my_event;
6802 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6804 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6806 // And now store the values in our own fields.
6808 declaring_type = type_builder;
6810 reflected_type = type_builder;
6812 attributes = event_attr;
6813 this.name = name;
6814 my_event = ev;
6815 this.event_type = event_type;
6819 // Methods that you have to override. Note that you only need
6820 // to "implement" the variants that take the argument (those are
6821 // the "abstract" methods, the others (GetAddMethod()) are
6822 // regular.
6824 public override MethodInfo GetAddMethod (bool nonPublic)
6826 return add;
6829 public override MethodInfo GetRemoveMethod (bool nonPublic)
6831 return remove;
6834 public override MethodInfo GetRaiseMethod (bool nonPublic)
6836 return raise;
6840 // These methods make "MyEventInfo" look like a Builder
6842 public void SetRaiseMethod (MethodBuilder raiseMethod)
6844 raise = raiseMethod;
6845 MyBuilder.SetRaiseMethod (raiseMethod);
6848 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6850 remove = removeMethod;
6851 MyBuilder.SetRemoveOnMethod (removeMethod);
6854 public void SetAddOnMethod (MethodBuilder addMethod)
6856 add = addMethod;
6857 MyBuilder.SetAddOnMethod (addMethod);
6860 public void SetCustomAttribute (CustomAttributeBuilder cb)
6862 MyBuilder.SetCustomAttribute (cb);
6865 public override object [] GetCustomAttributes (bool inherit)
6867 // FIXME : There's nothing which can be seemingly done here because
6868 // we have no way of getting at the custom attribute objects of the
6869 // EventBuilder !
6870 return null;
6873 public override object [] GetCustomAttributes (Type t, bool inherit)
6875 // FIXME : Same here !
6876 return null;
6879 public override bool IsDefined (Type t, bool b)
6881 return true;
6884 public override EventAttributes Attributes {
6885 get {
6886 return attributes;
6890 public override string Name {
6891 get {
6892 return name;
6896 public override Type DeclaringType {
6897 get {
6898 return declaring_type;
6902 public override Type ReflectedType {
6903 get {
6904 return reflected_type;
6908 public Type EventType {
6909 get {
6910 return event_type;
6914 public void SetUsed ()
6916 if (my_event != null)
6917 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
6921 /// <summary>
6922 /// For case when event is declared like property (with add and remove accessors).
6923 /// </summary>
6924 public class EventProperty: Event {
6926 static string[] attribute_targets = new string [] { "event", "property" };
6928 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
6929 bool is_iface, MemberName name, Object init,
6930 Attributes attrs, Accessor add, Accessor remove,
6931 Location loc)
6932 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6934 Add = new AddDelegateMethod (this, add);
6935 Remove = new RemoveDelegateMethod (this, remove);
6937 // For this event syntax we don't report error CS0067
6938 // because it is hard to do it.
6939 SetAssigned ();
6942 public override string[] ValidAttributeTargets {
6943 get {
6944 return attribute_targets;
6949 /// <summary>
6950 /// Event is declared like field.
6951 /// </summary>
6952 public class EventField: Event {
6954 static string[] attribute_targets = new string [] { "event", "field", "method" };
6955 static string[] attribute_targets_interface = new string[] { "event", "method" };
6957 public EventField (TypeContainer parent, Expression type, int mod_flags,
6958 bool is_iface, MemberName name, Object init,
6959 Attributes attrs, Location loc)
6960 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6962 Add = new AddDelegateMethod (this);
6963 Remove = new RemoveDelegateMethod (this);
6966 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6968 if (a.Target == AttributeTargets.Field) {
6969 FieldBuilder.SetCustomAttribute (cb);
6970 return;
6973 if (a.Target == AttributeTargets.Method) {
6974 Add.ApplyAttributeBuilder (a, cb);
6975 Remove.ApplyAttributeBuilder (a, cb);
6976 return;
6979 base.ApplyAttributeBuilder (a, cb);
6982 public override string[] ValidAttributeTargets {
6983 get {
6984 return IsInterface ? attribute_targets_interface : attribute_targets;
6989 public abstract class Event : FieldBase {
6991 protected sealed class AddDelegateMethod: DelegateMethod
6994 public AddDelegateMethod (Event method):
6995 base (method, "add_")
6999 public AddDelegateMethod (Event method, Accessor accessor):
7000 base (method, accessor, "add_")
7004 protected override MethodInfo DelegateMethodInfo {
7005 get {
7006 return TypeManager.delegate_combine_delegate_delegate;
7012 protected sealed class RemoveDelegateMethod: DelegateMethod
7014 public RemoveDelegateMethod (Event method):
7015 base (method, "remove_")
7019 public RemoveDelegateMethod (Event method, Accessor accessor):
7020 base (method, accessor, "remove_")
7024 protected override MethodInfo DelegateMethodInfo {
7025 get {
7026 return TypeManager.delegate_remove_delegate_delegate;
7032 public abstract class DelegateMethod: AbstractPropertyEventMethod
7034 protected readonly Event method;
7035 ImplicitParameter param_attr;
7037 static string[] attribute_targets = new string [] { "method", "param", "return" };
7039 public DelegateMethod (Event method, string prefix)
7040 : base (method, prefix)
7042 this.method = method;
7045 public DelegateMethod (Event method, Accessor accessor, string prefix)
7046 : base (method, accessor, prefix)
7048 this.method = method;
7051 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
7053 if (a.Target == AttributeTargets.Parameter) {
7054 if (param_attr == null)
7055 param_attr = new ImplicitParameter (method_data.MethodBuilder);
7057 param_attr.ApplyAttributeBuilder (a, cb);
7058 return;
7061 base.ApplyAttributeBuilder (a, cb);
7064 public override AttributeTargets AttributeTargets {
7065 get {
7066 return AttributeTargets.Method;
7070 public override bool IsClsCompliaceRequired(DeclSpace ds)
7072 return method.IsClsCompliaceRequired (ds);
7075 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
7077 method_data = new MethodData (method, ip, method.ModFlags,
7078 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7080 if (!method_data.Define (container))
7081 return null;
7083 MethodBuilder mb = method_data.MethodBuilder;
7084 mb.DefineParameter (1, ParameterAttributes.None, "value");
7085 return mb;
7089 public override void Emit (TypeContainer tc)
7091 if (block != null) {
7092 base.Emit (tc);
7093 return;
7096 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
7097 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
7099 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
7100 if ((method.ModFlags & Modifiers.STATIC) != 0) {
7101 ig.Emit (OpCodes.Ldsfld, field_info);
7102 ig.Emit (OpCodes.Ldarg_0);
7103 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7104 ig.Emit (OpCodes.Castclass, method.MemberType);
7105 ig.Emit (OpCodes.Stsfld, field_info);
7106 } else {
7107 ig.Emit (OpCodes.Ldarg_0);
7108 ig.Emit (OpCodes.Ldarg_0);
7109 ig.Emit (OpCodes.Ldfld, field_info);
7110 ig.Emit (OpCodes.Ldarg_1);
7111 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7112 ig.Emit (OpCodes.Castclass, method.MemberType);
7113 ig.Emit (OpCodes.Stfld, field_info);
7115 ig.Emit (OpCodes.Ret);
7118 protected abstract MethodInfo DelegateMethodInfo { get; }
7120 public override Type[] ParameterTypes {
7121 get {
7122 return new Type[] { method.MemberType };
7126 public override Type ReturnType {
7127 get {
7128 return TypeManager.void_type;
7132 public override EmitContext CreateEmitContext (TypeContainer tc,
7133 ILGenerator ig)
7135 return new EmitContext (
7136 tc, method.Parent, Location, ig, ReturnType,
7137 method.ModFlags, false);
7140 public override string GetSignatureForError (TypeContainer tc)
7142 return String.Concat (tc.Name, '.', method.Name);
7145 public override ObsoleteAttribute GetObsoleteAttribute ()
7147 return method.GetObsoleteAttribute (method.Parent);
7150 public override string[] ValidAttributeTargets {
7151 get {
7152 return attribute_targets;
7158 const int AllowedModifiers =
7159 Modifiers.NEW |
7160 Modifiers.PUBLIC |
7161 Modifiers.PROTECTED |
7162 Modifiers.INTERNAL |
7163 Modifiers.PRIVATE |
7164 Modifiers.STATIC |
7165 Modifiers.VIRTUAL |
7166 Modifiers.SEALED |
7167 Modifiers.OVERRIDE |
7168 Modifiers.UNSAFE |
7169 Modifiers.ABSTRACT;
7171 const int AllowedInterfaceModifiers =
7172 Modifiers.NEW;
7174 public DelegateMethod Add, Remove;
7175 public MyEventBuilder EventBuilder;
7176 public MethodBuilder AddBuilder, RemoveBuilder;
7178 MethodData AddData, RemoveData;
7180 public Event (TypeContainer parent, Expression type, int mod_flags,
7181 bool is_iface, MemberName name, Object init, Attributes attrs,
7182 Location loc)
7183 : base (parent, type, mod_flags,
7184 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7185 name, init, attrs, loc)
7187 IsInterface = is_iface;
7190 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7192 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7193 a.Error_InvalidSecurityParent ();
7194 return;
7197 EventBuilder.SetCustomAttribute (cb);
7200 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7202 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7205 public override AttributeTargets AttributeTargets {
7206 get {
7207 return AttributeTargets.Event;
7211 public override bool Define ()
7213 EventAttributes e_attr;
7214 e_attr = EventAttributes.None;
7216 if (!DoDefineBase ())
7217 return false;
7219 if (!DoDefine (Parent))
7220 return false;
7222 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
7223 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
7224 "': abstract event can not have an initializer");
7225 return false;
7228 if (!TypeManager.IsDelegateType (MemberType)) {
7229 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
7230 "' : event must be of a delegate type");
7231 return false;
7234 EmitContext ec = Parent.EmitContext;
7235 if (ec == null)
7236 throw new InternalErrorException ("Event.Define called too early?");
7237 bool old_unsafe = ec.InUnsafe;
7238 ec.InUnsafe = InUnsafe;
7240 Parameter [] parms = new Parameter [1];
7241 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
7242 Parameters parameters = new Parameters (parms, null, Location);
7243 Type [] types = parameters.GetParameterInfo (ec);
7244 InternalParameters ip = new InternalParameters (types, parameters);
7246 ec.InUnsafe = old_unsafe;
7248 if (!CheckBase ())
7249 return false;
7252 // Now define the accessors
7255 AddBuilder = Add.Define (Parent, ip);
7256 if (AddBuilder == null)
7257 return false;
7259 RemoveBuilder = Remove.Define (Parent, ip);
7260 if (RemoveBuilder == null)
7261 return false;
7263 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
7265 if (Add.Block == null && Remove.Block == null && !IsInterface) {
7266 FieldBuilder = Parent.TypeBuilder.DefineField (
7267 Name, MemberType,
7268 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7269 TypeManager.RegisterPrivateFieldOfEvent (
7270 (EventInfo) EventBuilder, FieldBuilder);
7271 TypeManager.RegisterFieldBase (FieldBuilder, this);
7274 EventBuilder.SetAddOnMethod (AddBuilder);
7275 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7277 TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
7278 return true;
7281 protected override bool CheckBase ()
7283 if (!base.CheckBase ())
7284 return false;
7286 if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
7287 if (!(conflict_symbol is EventInfo)) {
7288 Report.SymbolRelatedToPreviousError (conflict_symbol);
7289 Report.Error (72, Location, "Event '{0}' can override only event", GetSignatureForError (Parent));
7290 return false;
7294 return true;
7297 public override void Emit ()
7299 if (OptAttributes != null) {
7300 EmitContext ec = new EmitContext (
7301 Parent, Location, null, MemberType, ModFlags);
7302 OptAttributes.Emit (ec, this);
7305 if (!IsInterface) {
7306 Add.Emit (Parent);
7307 Remove.Emit (Parent);
7310 base.Emit ();
7313 public override string GetSignatureForError ()
7315 if (EventBuilder == null)
7316 return base.GetSignatureForError (Parent);
7318 return TypeManager.GetFullNameSignature (EventBuilder);
7322 // Represents header string for documentation comment.
7324 public override string DocCommentHeader {
7325 get { return "E:"; }
7330 public class Indexer : PropertyBase {
7332 class GetIndexerMethod: GetMethod
7334 public GetIndexerMethod (MethodCore method):
7335 base (method)
7339 public GetIndexerMethod (MethodCore method, Accessor accessor):
7340 base (method, accessor)
7344 public override Type[] ParameterTypes {
7345 get {
7346 return method.ParameterTypes;
7351 class SetIndexerMethod: SetMethod
7353 readonly Parameters parameters;
7355 public SetIndexerMethod (MethodCore method):
7356 base (method)
7360 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
7361 base (method, accessor)
7363 this.parameters = parameters;
7366 public override Type[] ParameterTypes {
7367 get {
7368 int top = method.ParameterTypes.Length;
7369 Type [] set_pars = new Type [top + 1];
7370 method.ParameterTypes.CopyTo (set_pars, 0);
7371 set_pars [top] = method.MemberType;
7372 return set_pars;
7376 protected override InternalParameters GetParameterInfo (EmitContext ec)
7378 Parameter [] fixed_parms = parameters.FixedParameters;
7380 if (fixed_parms == null){
7381 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
7382 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7383 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7385 // Here is the problem: the `value' parameter has
7386 // to come *after* the array parameter in the declaration
7387 // like this:
7388 // X (object [] x, Type value)
7389 // .param [0]
7391 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7392 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7396 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
7398 fixed_parms.CopyTo (tmp, 0);
7399 tmp [fixed_parms.Length] = new Parameter (
7400 method.Type, "value", Parameter.Modifier.NONE, null);
7402 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
7403 Type [] types = set_formal_params.GetParameterInfo (ec);
7405 return new InternalParameters (types, set_formal_params);
7409 const int AllowedModifiers =
7410 Modifiers.NEW |
7411 Modifiers.PUBLIC |
7412 Modifiers.PROTECTED |
7413 Modifiers.INTERNAL |
7414 Modifiers.PRIVATE |
7415 Modifiers.VIRTUAL |
7416 Modifiers.SEALED |
7417 Modifiers.OVERRIDE |
7418 Modifiers.UNSAFE |
7419 Modifiers.EXTERN |
7420 Modifiers.ABSTRACT;
7422 const int AllowedInterfaceModifiers =
7423 Modifiers.NEW;
7426 // Are we implementing an interface ?
7428 public Indexer (TypeContainer parent, Expression type, MemberName name, int mod,
7429 bool is_iface, Parameters parameters, Attributes attrs,
7430 Accessor get_block, Accessor set_block, Location loc)
7431 : base (parent, type, mod,
7432 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7433 is_iface, name, parameters, attrs, loc)
7435 if (get_block == null)
7436 Get = new GetIndexerMethod (this);
7437 else
7438 Get = new GetIndexerMethod (this, get_block);
7440 if (set_block == null)
7441 Set = new SetIndexerMethod (this);
7442 else
7443 Set = new SetIndexerMethod (this, parameters, set_block);
7446 public override bool Define ()
7448 PropertyAttributes prop_attr =
7449 PropertyAttributes.RTSpecialName |
7450 PropertyAttributes.SpecialName;
7452 if (!DoDefineBase ())
7453 return false;
7455 if (!base.Define ())
7456 return false;
7458 if (MemberType == TypeManager.void_type) {
7459 Report.Error (620, Location, "Indexers cannot have void type");
7460 return false;
7463 if (OptAttributes != null) {
7464 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
7465 if (indexer_attr != null) {
7466 // Remove the attribute from the list because it is not emitted
7467 OptAttributes.Attrs.Remove (indexer_attr);
7469 ShortName = indexer_attr.GetIndexerAttributeValue (ec);
7471 if (IsExplicitImpl) {
7472 Report.Error (415, indexer_attr.Location,
7473 "The 'IndexerName' attribute is valid only on an" +
7474 "indexer that is not an explicit interface member declaration");
7475 return false;
7478 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7479 Report.Error (609, indexer_attr.Location,
7480 "Cannot set the 'IndexerName' attribute on an indexer marked override");
7481 return false;
7484 // if (!Tokenizer.IsValidIdentifier (ShortName)) {
7485 // Report.Error (633, indexer_attr.Location,
7486 // "The argument to the 'IndexerName' attribute must be a valid identifier");
7487 // return false;
7488 // }
7490 UpdateMemberName ();
7494 if (InterfaceType != null) {
7495 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7496 if (base_IndexerName != Name)
7497 ShortName = base_IndexerName;
7498 UpdateMemberName ();
7501 if (!Parent.AddToMemberContainer (this) ||
7502 !Parent.AddToMemberContainer (Get) || !Parent.AddToMemberContainer (Set))
7503 return false;
7505 if (!CheckBase ())
7506 return false;
7508 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7509 if (!Get.IsDummy){
7510 GetBuilder = Get.Define (Parent);
7511 if (GetBuilder == null)
7512 return false;
7515 if (!Set.IsDummy){
7516 SetBuilder = Set.Define (Parent);
7517 if (SetBuilder == null)
7518 return false;
7522 // Now name the parameters
7524 Parameter [] p = Parameters.FixedParameters;
7525 if (p != null) {
7526 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7527 Report.Error (631, Location, "ref and out are not valid in this context");
7528 return false;
7531 int i;
7533 for (i = 0; i < p.Length; ++i) {
7534 if (!Get.IsDummy)
7535 GetBuilder.DefineParameter (
7536 i + 1, p [i].Attributes, p [i].Name);
7538 if (!Set.IsDummy)
7539 SetBuilder.DefineParameter (
7540 i + 1, p [i].Attributes, p [i].Name);
7543 if (!Set.IsDummy)
7544 SetBuilder.DefineParameter (
7545 i + 1, ParameterAttributes.None, "value");
7547 if (i != ParameterTypes.Length) {
7548 Parameter array_param = Parameters.ArrayParameter;
7550 SetBuilder.DefineParameter (
7551 i + 1, array_param.Attributes, array_param.Name);
7555 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7556 Name, prop_attr, MemberType, ParameterTypes);
7558 if (!Get.IsDummy)
7559 PropertyBuilder.SetGetMethod (GetBuilder);
7561 if (!Set.IsDummy)
7562 PropertyBuilder.SetSetMethod (SetBuilder);
7564 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
7566 return true;
7569 public override string GetSignatureForError ()
7571 if (PropertyBuilder == null)
7572 return GetSignatureForError (Parent);
7574 return TypeManager.CSharpSignature (PropertyBuilder, true);
7577 public override string GetSignatureForError(TypeContainer tc)
7579 return String.Concat (tc.Name, ".this[", Parameters.FixedParameters [0].TypeName.ToString (), ']');
7582 public override bool MarkForDuplicationCheck ()
7584 caching_flags |= Flags.TestMethodDuplication;
7585 return true;
7590 public class Operator : MethodCore, IIteratorContainer {
7592 const int AllowedModifiers =
7593 Modifiers.PUBLIC |
7594 Modifiers.UNSAFE |
7595 Modifiers.EXTERN |
7596 Modifiers.STATIC;
7598 public enum OpType : byte {
7600 // Unary operators
7601 LogicalNot,
7602 OnesComplement,
7603 Increment,
7604 Decrement,
7605 True,
7606 False,
7608 // Unary and Binary operators
7609 Addition,
7610 Subtraction,
7612 UnaryPlus,
7613 UnaryNegation,
7615 // Binary operators
7616 Multiply,
7617 Division,
7618 Modulus,
7619 BitwiseAnd,
7620 BitwiseOr,
7621 ExclusiveOr,
7622 LeftShift,
7623 RightShift,
7624 Equality,
7625 Inequality,
7626 GreaterThan,
7627 LessThan,
7628 GreaterThanOrEqual,
7629 LessThanOrEqual,
7631 // Implicit and Explicit
7632 Implicit,
7633 Explicit
7636 public readonly OpType OperatorType;
7637 public MethodBuilder OperatorMethodBuilder;
7639 public Method OperatorMethod;
7641 static string[] attribute_targets = new string [] { "method", "return" };
7643 public Operator (TypeContainer parent, OpType type, Expression ret_type,
7644 int mod_flags, Parameters parameters,
7645 ToplevelBlock block, Attributes attrs, Location loc)
7646 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7647 new MemberName ("op_" + type), attrs, parameters, loc)
7649 OperatorType = type;
7650 Block = block;
7653 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7655 OperatorMethod.ApplyAttributeBuilder (a, cb);
7658 public override AttributeTargets AttributeTargets {
7659 get {
7660 return AttributeTargets.Method;
7664 protected override bool CheckGenericOverride (MethodInfo method, string name)
7666 return true;
7669 protected override bool CheckForDuplications()
7671 ArrayList ar = Parent.Operators;
7672 if (ar != null) {
7673 int arLen = ar.Count;
7675 for (int i = 0; i < arLen; i++) {
7676 Operator o = (Operator) ar [i];
7677 if (IsDuplicateImplementation (o))
7678 return false;
7682 ar = Parent.Methods;
7683 if (ar != null) {
7684 int arLen = ar.Count;
7686 for (int i = 0; i < arLen; i++) {
7687 Method m = (Method) ar [i];
7688 if (IsDuplicateImplementation (m))
7689 return false;
7693 return true;
7696 public override bool Define ()
7698 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7699 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7700 Report.Error (558, Location, "User defined operators '{0}' must be declared static and public", GetSignatureForError (Parent));
7701 return false;
7704 if (!DoDefine (ds))
7705 return false;
7707 if (MemberType == TypeManager.void_type) {
7708 Report.Error (590, Location, "User-defined operators cannot return void");
7709 return false;
7712 OperatorMethod = new Method (
7713 Parent, null, Type, ModFlags, false, MemberName,
7714 Parameters, OptAttributes, Location);
7716 OperatorMethod.Block = Block;
7717 OperatorMethod.IsOperator = true;
7718 OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7719 OperatorMethod.Define ();
7721 if (OperatorMethod.MethodBuilder == null)
7722 return false;
7724 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7726 parameter_types = OperatorMethod.ParameterTypes;
7727 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
7728 Type return_type = OperatorMethod.ReturnType;
7729 Type first_arg_type = parameter_types [0];
7731 if (!CheckBase ())
7732 return false;
7734 // Rules for conversion operators
7736 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7737 if (first_arg_type == return_type && first_arg_type == declaring_type){
7738 Report.Error (
7739 555, Location,
7740 "User-defined conversion cannot take an object of the " +
7741 "enclosing type and convert to an object of the enclosing" +
7742 " type");
7743 return false;
7746 if (first_arg_type != declaring_type && return_type != declaring_type){
7747 Report.Error (
7748 556, Location,
7749 "User-defined conversion must convert to or from the " +
7750 "enclosing type");
7751 return false;
7754 if (first_arg_type == TypeManager.object_type ||
7755 return_type == TypeManager.object_type){
7756 Report.Error (
7757 -8, Location,
7758 "User-defined conversion cannot convert to or from " +
7759 "object type");
7760 return false;
7763 if (first_arg_type.IsInterface || return_type.IsInterface){
7764 Report.Error (
7765 552, Location,
7766 "User-defined conversion cannot convert to or from an " +
7767 "interface type");
7768 return false;
7771 if (first_arg_type.IsSubclassOf (return_type)
7772 || return_type.IsSubclassOf (first_arg_type)){
7773 if (declaring_type.IsSubclassOf (return_type)) {
7774 Report.Error (553, Location, "'{0}' : user defined conversion to/from base class", GetSignatureForError ());
7775 return false;
7777 Report.Error (554, Location, "'{0}' : user defined conversion to/from derived class", GetSignatureForError ());
7778 return false;
7780 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7781 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7782 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");
7783 return false;
7785 } else if (Parameters.FixedParameters.Length == 1) {
7786 // Checks for Unary operators
7788 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7789 if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7790 Report.Error (448, Location,
7791 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7792 return false;
7794 if (first_arg_type != declaring_type){
7795 Report.Error (
7796 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7797 return false;
7801 if (first_arg_type != declaring_type){
7802 Report.Error (
7803 562, Location,
7804 "The parameter of a unary operator must be the " +
7805 "containing type");
7806 return false;
7809 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7810 if (return_type != TypeManager.bool_type){
7811 Report.Error (
7812 215, Location,
7813 "The return type of operator True or False " +
7814 "must be bool");
7815 return false;
7819 } else {
7820 // Checks for Binary operators
7822 if (first_arg_type != declaring_type &&
7823 parameter_types [1] != declaring_type){
7824 Report.Error (
7825 563, Location,
7826 "One of the parameters of a binary operator must " +
7827 "be the containing type");
7828 return false;
7832 return true;
7835 public override void Emit ()
7838 // abstract or extern methods have no bodies
7840 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7841 return;
7843 OperatorMethod.Emit ();
7844 Block = null;
7847 // Operator cannot be override
7848 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
7850 return null;
7853 public static string GetName (OpType ot)
7855 switch (ot){
7856 case OpType.LogicalNot:
7857 return "!";
7858 case OpType.OnesComplement:
7859 return "~";
7860 case OpType.Increment:
7861 return "++";
7862 case OpType.Decrement:
7863 return "--";
7864 case OpType.True:
7865 return "true";
7866 case OpType.False:
7867 return "false";
7868 case OpType.Addition:
7869 return "+";
7870 case OpType.Subtraction:
7871 return "-";
7872 case OpType.UnaryPlus:
7873 return "+";
7874 case OpType.UnaryNegation:
7875 return "-";
7876 case OpType.Multiply:
7877 return "*";
7878 case OpType.Division:
7879 return "/";
7880 case OpType.Modulus:
7881 return "%";
7882 case OpType.BitwiseAnd:
7883 return "&";
7884 case OpType.BitwiseOr:
7885 return "|";
7886 case OpType.ExclusiveOr:
7887 return "^";
7888 case OpType.LeftShift:
7889 return "<<";
7890 case OpType.RightShift:
7891 return ">>";
7892 case OpType.Equality:
7893 return "==";
7894 case OpType.Inequality:
7895 return "!=";
7896 case OpType.GreaterThan:
7897 return ">";
7898 case OpType.LessThan:
7899 return "<";
7900 case OpType.GreaterThanOrEqual:
7901 return ">=";
7902 case OpType.LessThanOrEqual:
7903 return "<=";
7904 case OpType.Implicit:
7905 return "implicit";
7906 case OpType.Explicit:
7907 return "explicit";
7908 default: return "";
7912 public override string GetSignatureForError (TypeContainer tc)
7914 StringBuilder sb = new StringBuilder ();
7915 sb.AppendFormat ("{0}.operator {1} {2}({3}", tc.Name, GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type),
7916 Parameters.FixedParameters [0].GetSignatureForError ());
7918 if (Parameters.FixedParameters.Length > 1) {
7919 sb.Append (",");
7920 sb.Append (Parameters.FixedParameters [1].GetSignatureForError ());
7922 sb.Append (")");
7923 return sb.ToString ();
7926 public override string GetSignatureForError ()
7928 return ToString ();
7931 public override bool MarkForDuplicationCheck ()
7933 caching_flags |= Flags.TestMethodDuplication;
7934 return true;
7937 public override string ToString ()
7939 if (OperatorMethod == null)
7940 return Name;
7942 Type return_type = OperatorMethod.ReturnType;
7943 Type [] param_types = OperatorMethod.ParameterTypes;
7945 if (Parameters.FixedParameters.Length == 1)
7946 return String.Format (
7947 "{0} operator {1}({2})",
7948 TypeManager.CSharpName (return_type),
7949 GetName (OperatorType),
7950 param_types [0]);
7951 else
7952 return String.Format (
7953 "{0} operator {1}({2}, {3})",
7954 TypeManager.CSharpName (return_type),
7955 GetName (OperatorType),
7956 param_types [0], param_types [1]);
7959 public override string[] ValidAttributeTargets {
7960 get {
7961 return attribute_targets;
7965 public void SetYields ()
7967 ModFlags |= Modifiers.METHOD_YIELDS;
7972 // This is used to compare method signatures
7974 struct MethodSignature {
7975 public string Name;
7976 public Type RetType;
7977 public Type [] Parameters;
7979 /// <summary>
7980 /// This delegate is used to extract methods which have the
7981 /// same signature as the argument
7982 /// </summary>
7983 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7985 public MethodSignature (string name, Type ret_type, Type [] parameters)
7987 Name = name;
7988 RetType = ret_type;
7990 if (parameters == null)
7991 Parameters = TypeManager.NoTypes;
7992 else
7993 Parameters = parameters;
7996 public override string ToString ()
7998 string pars = "";
7999 if (Parameters.Length != 0){
8000 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8001 for (int i = 0; i < Parameters.Length; i++){
8002 sb.Append (Parameters [i]);
8003 if (i+1 < Parameters.Length)
8004 sb.Append (", ");
8006 pars = sb.ToString ();
8009 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8012 public override int GetHashCode ()
8014 return Name.GetHashCode ();
8017 public override bool Equals (Object o)
8019 MethodSignature other = (MethodSignature) o;
8021 if (other.Name != Name)
8022 return false;
8024 if (other.RetType != RetType)
8025 return false;
8027 if (Parameters == null){
8028 if (other.Parameters == null)
8029 return true;
8030 return false;
8033 if (other.Parameters == null)
8034 return false;
8036 int c = Parameters.Length;
8037 if (other.Parameters.Length != c)
8038 return false;
8040 for (int i = 0; i < c; i++)
8041 if (other.Parameters [i] != Parameters [i])
8042 return false;
8044 return true;
8047 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8049 MethodSignature sig = (MethodSignature) filter_criteria;
8051 if (m.Name != sig.Name)
8052 return false;
8054 Type ReturnType;
8055 MethodInfo mi = m as MethodInfo;
8056 PropertyInfo pi = m as PropertyInfo;
8058 if (mi != null)
8059 ReturnType = mi.ReturnType;
8060 else if (pi != null)
8061 ReturnType = pi.PropertyType;
8062 else
8063 return false;
8066 // we use sig.RetType == null to mean `do not check the
8067 // method return value.
8069 if (sig.RetType != null)
8070 if (ReturnType != sig.RetType)
8071 return false;
8073 Type [] args;
8074 if (mi != null)
8075 args = TypeManager.GetArgumentTypes (mi);
8076 else
8077 args = TypeManager.GetArgumentTypes (pi);
8078 Type [] sigp = sig.Parameters;
8080 if (args.Length != sigp.Length)
8081 return false;
8083 for (int i = args.Length; i > 0; ){
8084 i--;
8085 if (args [i] != sigp [i])
8086 return false;
8088 return true;