2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 public bool UserDefinedStaticConstructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 bool members_defined;
117 bool members_defined_ok;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
128 // The parent member container and our member cache
129 IMemberContainer parent_container;
130 MemberCache member_cache;
133 // The indexer name for this class
135 public string IndexerName;
139 public TypeContainer ():
140 this (null, null, "", null, new Location (-1)) {
143 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Attributes attrs, Location l)
144 : base (ns, parent, name, attrs, l)
146 types = new ArrayList ();
148 base_class_name = null;
151 public AdditionResult AddConstant (Const constant)
154 string basename = constant.Name;
155 string fullname = Name + "." + basename;
157 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
160 if (constants == null)
161 constants = new ArrayList ();
163 constants.Add (constant);
164 DefineName (fullname, constant);
166 return AdditionResult.Success;
169 public AdditionResult AddEnum (Mono.CSharp.Enum e)
173 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
177 enums = new ArrayList ();
180 DefineName (e.Name, e);
182 return AdditionResult.Success;
185 public AdditionResult AddClass (Class c)
188 string name = c.Basename;
190 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
193 DefineName (c.Name, c);
196 return AdditionResult.Success;
199 public AdditionResult AddStruct (Struct s)
202 string name = s.Basename;
204 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
207 DefineName (s.Name, s);
210 return AdditionResult.Success;
213 public AdditionResult AddDelegate (Delegate d)
216 string name = d.Basename;
218 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
221 if (delegates == null)
222 delegates = new ArrayList ();
224 DefineName (d.Name, d);
227 return AdditionResult.Success;
230 public AdditionResult AddMethod (Method method)
232 string basename = method.Name;
233 string fullname = Name + "." + basename;
235 Object value = defined_names [fullname];
237 if (value != null && (!(value is Method)))
238 return AdditionResult.NameExists;
240 if (basename == Basename)
241 return AdditionResult.EnclosingClash;
244 methods = new ArrayList ();
246 if (method.Name.IndexOf ('.') != -1)
247 methods.Insert (0, method);
249 methods.Add (method);
252 DefineName (fullname, method);
254 return AdditionResult.Success;
257 public AdditionResult AddConstructor (Constructor c)
259 if (c.Name != Basename)
260 return AdditionResult.NotAConstructor;
262 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
265 UserDefinedStaticConstructor = true;
266 if (default_static_constructor != null)
267 return AdditionResult.MethodExists;
269 default_static_constructor = c;
272 if (default_constructor != null)
273 return AdditionResult.MethodExists;
274 default_constructor = c;
277 if (instance_constructors == null)
278 instance_constructors = new ArrayList ();
280 instance_constructors.Add (c);
283 return AdditionResult.Success;
286 public AdditionResult AddInterface (Interface iface)
289 string name = iface.Basename;
291 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
294 if (interfaces == null)
295 interfaces = new ArrayList ();
296 interfaces.Add (iface);
297 DefineName (iface.Name, iface);
299 return AdditionResult.Success;
302 public AdditionResult AddField (Field field)
305 string basename = field.Name;
306 string fullname = Name + "." + basename;
308 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
312 fields = new ArrayList ();
316 if (field.HasInitializer){
317 if ((field.ModFlags & Modifiers.STATIC) != 0){
318 if (initialized_static_fields == null)
319 initialized_static_fields = new ArrayList ();
321 initialized_static_fields.Add (field);
324 if (initialized_fields == null)
325 initialized_fields = new ArrayList ();
327 initialized_fields.Add (field);
331 if ((field.ModFlags & Modifiers.STATIC) == 0)
332 have_nonstatic_fields = true;
334 DefineName (fullname, field);
335 return AdditionResult.Success;
338 public AdditionResult AddProperty (Property prop)
342 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
345 if (prop.Get != null) {
346 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
350 if (prop.Set != null) {
351 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
355 if (properties == null)
356 properties = new ArrayList ();
358 if (prop.Name.IndexOf ('.') != -1)
359 properties.Insert (0, prop);
361 properties.Add (prop);
363 return AdditionResult.Success;
366 AdditionResult AddProperty (Property prop, string basename)
369 string fullname = Name + "." + basename;
371 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
374 DefineName (fullname, prop);
376 return AdditionResult.Success;
379 public AdditionResult AddEvent (Event e)
382 string basename = e.Name;
383 string fullname = Name + "." + basename;
385 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
389 events = new ArrayList ();
392 DefineName (fullname, e);
394 return AdditionResult.Success;
397 public void AddIndexer (Indexer i)
399 if (indexers == null)
400 indexers = new ArrayList ();
402 if (i.InterfaceType != null)
403 indexers.Insert (0, i);
408 public AdditionResult AddOperator (Operator op)
410 if (operators == null)
411 operators = new ArrayList ();
415 string basename = op.Name;
416 string fullname = Name + "." + basename;
417 if (!defined_names.Contains (fullname))
419 DefineName (fullname, op);
421 return AdditionResult.Success;
424 public void RegisterOrder (Interface iface)
426 if (interface_order == null)
427 interface_order = new ArrayList ();
429 interface_order.Add (iface);
432 public ArrayList Types {
438 public ArrayList Methods {
444 public ArrayList Constants {
450 public ArrayList Interfaces {
458 return base_class_name;
462 public ArrayList Bases {
472 public ArrayList Fields {
482 public ArrayList InstanceConstructors {
484 return instance_constructors;
488 public ArrayList Properties {
494 public ArrayList Events {
500 public ArrayList Enums {
506 public ArrayList Indexers {
512 public ArrayList Operators {
518 public ArrayList Delegates {
524 public virtual TypeAttributes TypeAttr {
526 return Modifiers.TypeAttr (ModFlags, this);
531 // Emits the instance field initializers
533 public bool EmitFieldInitializers (EmitContext ec)
536 Expression instance_expr;
539 fields = initialized_static_fields;
540 instance_expr = null;
542 fields = initialized_fields;
543 instance_expr = new This (Location.Null).Resolve (ec);
549 foreach (Field f in fields){
550 Expression e = f.GetInitializerExpression (ec);
554 Location l = f.Location;
555 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
556 fe.InstanceExpression = instance_expr;
557 ExpressionStatement a = new Assign (fe, e, l);
559 a = a.ResolveStatement (ec);
563 a.EmitStatement (ec);
570 // Defines the default constructors
572 void DefineDefaultConstructor (bool is_static)
576 // The default constructor is public
577 // If the class is abstract, the default constructor is protected
578 // The default static constructor is private
580 int mods = Modifiers.PUBLIC;
582 mods = Modifiers.STATIC | Modifiers.PRIVATE;
583 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
584 mods = Modifiers.PROTECTED;
586 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
587 new ConstructorBaseInitializer (
588 null, Parameters.EmptyReadOnlyParameters,
594 c.Block = new ToplevelBlock (null, Location);
598 public void ReportStructInitializedInstanceError ()
600 string n = TypeBuilder.FullName;
602 foreach (Field f in initialized_fields){
605 "`" + n + "." + f.Name + "': can not have " +
606 "instance field initializers in structs");
611 /// The pending methods that need to be implemented (interfaces or abstract methods)
613 public PendingImplementation Pending;
616 /// This function computes the Base class and also the
617 /// list of interfaces that the class or struct @c implements.
619 /// The return value is an array (might be null) of
620 /// interfaces implemented (as Types).
622 /// The @parent argument is set to the parent object or null
623 /// if this is `System.Object'.
625 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
626 out TypeExpr parent, out bool error)
628 ArrayList bases = Bases;
634 if (is_class || is_iface)
637 parent = TypeManager.system_valuetype_expr;
641 if (RootContext.StdLib)
642 parent = TypeManager.system_object_expr;
643 else if (Name != "System.Object")
644 parent = TypeManager.system_object_expr;
647 // If we are compiling our runtime,
648 // and we are defining ValueType, then our
649 // parent is `System.Object'.
651 if (!RootContext.StdLib && Name == "System.ValueType")
652 parent = TypeManager.system_object_expr;
659 // Bases should be null if there are no bases at all
664 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
671 if (name is TypeParameterExpr){
674 "Type parameter `{0}' can not be used as a " +
675 "base class or interface", name.Name);
680 if (IsGeneric && name.IsAttribute){
683 "A generic type cannot derive from `{0}' " +
684 "because it is an attribute class", name.Name);
693 parent = TypeManager.system_object_expr;
699 if (name.IsValueType)
700 detail = " (a class can not inherit from a struct/enum)";
702 Report.Error (509, "class `"+ Name +
703 "': Cannot inherit from sealed class `"+
704 name.Name + "'" + detail);
709 if (!parent.CanInheritFrom ()){
710 Report.Error (644, Location,
711 "`{0}' cannot inherit from special class `{1}'",
717 if (!parent.AsAccessible (this, ModFlags))
718 Report.Error (60, Location,
719 "Inconsistent accessibility: base class `" +
720 name.Name + "' is less accessible than class `" +
728 base_class_name = parent.Name;
730 TypeExpr [] ifaces = new TypeExpr [count-start];
732 for (i = start, j = 0; i < count; i++, j++){
733 Expression name = (Expression) bases [i];
734 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
736 if (resolved == null)
739 bases [i] = resolved;
741 if (is_class == false && !resolved.IsInterface){
742 Report.Error (527, "In Struct `" + Name + "', type `"+
743 name +"' is not an interface");
748 if (resolved.IsClass) {
750 Report.Error (527, "In Class `" + Name + "', type `"+
751 name+"' is not an interface");
757 for (int x = 0; x < j; x++) {
758 if (resolved.Equals (ifaces [x])) {
759 Report.Error (528, "`" + name + "' is already listed in interface list");
766 !resolved.AsAccessible (Parent, ModFlags))
767 Report.Error (61, Location,
768 "Inconsistent accessibility: base interface `" +
769 name + "' is less accessible than interface `" +
772 ifaces [j] = resolved;
775 return TypeManager.ExpandInterfaces (ifaces);
778 bool CheckGenericInterfaces (Type[] ifaces)
780 ArrayList already_checked = new ArrayList ();
782 for (int i = 0; i < ifaces.Length; i++) {
783 Type iface = ifaces [i];
784 foreach (Type t in already_checked) {
788 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
793 "`{0}' cannot implement both `{1}' and `{2}' " +
794 "because they may unify for some type " +
795 "parameter substitutions",
796 TypeManager.GetFullName (TypeBuilder),
801 already_checked.Add (iface);
810 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
812 public override TypeBuilder DefineType ()
815 bool is_class, is_iface;
817 if (TypeBuilder != null)
824 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
831 if (this is Interface) {
842 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
844 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
850 foreach (TypeParameter type_param in TypeParameters)
851 if (!type_param.Resolve (this)) {
857 if (!is_class && TypeManager.value_type == null)
858 throw new Exception ();
860 TypeAttributes type_attributes = TypeAttr;
863 ConstructedType constructed = parent as ConstructedType;
864 if ((constructed == null) && (parent != null))
865 ptype = parent.ResolveType (ec);
870 if (TypeManager.NamespaceClash (Name, Location)) {
875 ModuleBuilder builder = CodeGen.Module.Builder;
876 TypeBuilder = builder.DefineType (
877 Name, type_attributes, ptype, null);
880 TypeBuilder builder = Parent.DefineType ();
881 if (builder == null) {
886 TypeBuilder = builder.DefineNestedType (
887 Basename, type_attributes, ptype, null);
890 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
893 CurrentType = new ConstructedType (
894 Name, TypeParameters, Location);
896 foreach (TypeParameter type_param in TypeParameters)
897 type_param.Define (TypeBuilder);
900 if (constructed != null) {
901 ptype = constructed.ResolveType (ec);
907 TypeBuilder.SetParent (ptype);
911 foreach (TypeParameter type_param in TypeParameters)
912 if (!type_param.DefineType (ec, TypeBuilder))
920 // Structs with no fields need to have at least one byte.
921 // The right thing would be to set the PackingSize in a DefineType
922 // but there are no functions that allow interfaces *and* the size to
926 if (!is_class && !is_iface && !have_nonstatic_fields){
927 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
928 FieldAttributes.Private);
931 // add interfaces that were not added at type creation
932 if (ifaces != null) {
933 Type[] itypes = new Type [ifaces.Length];
934 for (int i = 0; i < ifaces.Length; i++) {
935 itypes [i] = ifaces [i].ResolveType (ec);
936 if (itypes [i] == null)
943 if (!CheckGenericInterfaces (itypes)) {
948 for (int i = 0; i < ifaces.Length; i++)
949 TypeBuilder.AddInterfaceImplementation (itypes [i]);
953 // Finish the setup for the EmitContext
955 ec.ContainerType = TypeBuilder;
957 if ((parent != null) && parent.IsAttribute) {
958 RootContext.RegisterAttribute (this);
959 TypeManager.RegisterAttrType (TypeBuilder, this);
961 RootContext.RegisterOrder (this);
963 if (Interfaces != null) {
964 foreach (Interface iface in Interfaces)
965 if (iface.DefineType () == null) {
972 foreach (TypeContainer tc in Types)
973 if (tc.DefineType () == null) {
979 if (Delegates != null) {
980 foreach (Delegate d in Delegates)
981 if (d.DefineType () == null) {
988 foreach (Enum en in Enums)
989 if (en.DefineType () == null) {
1001 /// Defines the MemberCore objects that are in the `list' Arraylist
1003 /// The `defined_names' array contains a list of members defined in
1006 static ArrayList remove_list = new ArrayList ();
1007 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1011 remove_list.Clear ();
1013 foreach (MemberCore mc in list){
1015 if (defined_names != null)
1016 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1021 if (RootContext.WarningLevel >= 4){
1022 if ((mc.ModFlags & Modifiers.NEW) != 0)
1023 Warning_KeywordNewNotRequired (mc.Location, mc);
1025 } else if (mc is MethodCore)
1026 ((MethodCore) mc).OverridesSomething = true;
1028 if (!mc.Define (this)){
1029 remove_list.Add (mc);
1036 MemberInfo match = defined_names [idx];
1038 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1042 // If we are both methods, let the method resolution emit warnings
1044 if (match is MethodBase && mc is MethodCore)
1047 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1049 if (!(match is EventInfo)) {
1050 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1054 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1058 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1062 foreach (object o in remove_list)
1065 remove_list.Clear ();
1069 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1070 // class is consisten. Either it is `Item' or it is the name defined by all the
1071 // indexers with the `IndexerName' attribute.
1073 // Turns out that the IndexerNameAttribute is applied to each indexer,
1074 // but it is never emitted, instead a DefaultName attribute is attached
1077 void DefineIndexers ()
1079 string class_indexer_name = null;
1082 // If there's both an explicit and an implicit interface implementation, the
1083 // explicit one actually implements the interface while the other one is just
1084 // a normal indexer. See bug #37714.
1087 ArrayList list = new ArrayList ();
1088 foreach (Indexer i in Indexers){
1089 if (i.MemberName.Left != null)
1092 foreach (Indexer i in Indexers){
1093 if (i.MemberName.Left == null)
1097 foreach (Indexer i in list){
1102 name = i.IndexerName;
1104 if (i.InterfaceType != null)
1107 if (class_indexer_name == null){
1108 class_indexer_name = name;
1112 if (name == class_indexer_name)
1116 668, "Two indexers have different names, " +
1117 " you should use the same name for all your indexers");
1119 if (class_indexer_name == null)
1120 class_indexer_name = "Item";
1121 IndexerName = class_indexer_name;
1124 static void Error_KeywordNotAllowed (Location loc)
1126 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1130 /// Populates our TypeBuilder with fields and methods
1132 public override bool DefineMembers (TypeContainer container)
1134 if (members_defined)
1135 return members_defined_ok;
1137 members_defined_ok = DoDefineMembers ();
1138 members_defined = true;
1140 return members_defined_ok;
1143 bool DoDefineMembers ()
1145 MemberInfo [] defined_names = null;
1148 // We need to be able to use the member cache while we are checking/defining
1151 if (TypeBuilder.BaseType != null)
1152 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1155 if (interface_order != null){
1156 foreach (Interface iface in interface_order)
1157 if ((iface.ModFlags & Modifiers.NEW) == 0)
1158 iface.DefineMembers (this);
1160 Error_KeywordNotAllowed (iface.Location);
1163 if (RootContext.WarningLevel > 1){
1167 // This code throws an exception in the comparer
1168 // I guess the string is not an object?
1170 ptype = TypeBuilder.BaseType;
1172 defined_names = (MemberInfo []) FindMembers (
1173 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1174 BindingFlags.Public | BindingFlags.Instance |
1175 BindingFlags.Static, null, null);
1177 Array.Sort (defined_names, mif_compare);
1181 Class pclass = Parent as Class;
1182 if (pclass != null) {
1183 string pname = null;
1185 Type t = pclass.TypeBuilder.BaseType;
1186 while ((t != null) && (ptype == null)) {
1187 pname = t.FullName + "." + Basename;
1188 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1192 if ((ModFlags & Modifiers.NEW) != 0) {
1194 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1195 "inherited member. The keyword new is not required.");
1196 } else if (ptype != null) {
1197 Report.Warning (108, Location, "The keyword new is required on `" +
1198 Name + "' because it hides inherited member '" +
1201 } else if ((ModFlags & Modifiers.NEW) != 0)
1202 Error_KeywordNotAllowed (Location);
1204 if (constants != null)
1205 DefineMembers (constants, defined_names);
1208 DefineMembers (fields, defined_names);
1211 if (instance_constructors == null){
1212 if (default_constructor == null)
1213 DefineDefaultConstructor (false);
1216 if (initialized_static_fields != null &&
1217 default_static_constructor == null)
1218 DefineDefaultConstructor (true);
1221 if (this is Struct){
1223 // Structs can not have initialized instance
1226 if (initialized_static_fields != null &&
1227 default_static_constructor == null)
1228 DefineDefaultConstructor (true);
1230 if (initialized_fields != null)
1231 ReportStructInitializedInstanceError ();
1234 if (!(this is Interface))
1235 Pending = PendingImplementation.GetPendingImplementations (this);
1238 // Constructors are not in the defined_names array
1240 if (instance_constructors != null)
1241 DefineMembers (instance_constructors, null);
1243 if (default_static_constructor != null)
1244 default_static_constructor.Define (this);
1246 if (methods != null)
1247 DefineMembers (methods, defined_names);
1249 if (properties != null)
1250 DefineMembers (properties, defined_names);
1253 DefineMembers (events, defined_names);
1255 if (indexers != null) {
1258 IndexerName = "Item";
1260 if (operators != null){
1261 DefineMembers (operators, null);
1263 CheckPairedOperators ();
1267 DefineMembers (enums, defined_names);
1269 if (delegates != null)
1270 DefineMembers (delegates, defined_names);
1272 if (CurrentType != null) {
1273 GenericType = CurrentType.ResolveType (ec);
1275 ec.ContainerType = GenericType;
1280 member_cache = new MemberCache (this);
1287 public override bool Define (TypeContainer container)
1289 if (interface_order != null){
1290 foreach (Interface iface in interface_order)
1291 if ((iface.ModFlags & Modifiers.NEW) == 0)
1292 iface.Define (this);
1299 /// This function is based by a delegate to the FindMembers routine
1301 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1307 /// This filter is used by FindMembers, and we just keep
1308 /// a global for the filter to `AlwaysAccept'
1310 static MemberFilter accepting_filter;
1314 /// A member comparission method based on name only
1316 static IComparer mif_compare;
1318 static TypeContainer ()
1320 accepting_filter = new MemberFilter (AlwaysAccept);
1321 mif_compare = new MemberInfoCompare ();
1324 public MethodInfo[] GetMethods ()
1326 ArrayList members = new ArrayList ();
1328 DefineMembers (null);
1330 if (methods != null) {
1331 int len = methods.Count;
1332 for (int i = 0; i < len; i++) {
1333 Method m = (Method) methods [i];
1335 members.Add (m.MethodBuilder);
1339 if (operators != null) {
1340 int len = operators.Count;
1341 for (int i = 0; i < len; i++) {
1342 Operator o = (Operator) operators [i];
1344 members.Add (o.OperatorMethodBuilder);
1348 if (properties != null) {
1349 int len = properties.Count;
1350 for (int i = 0; i < len; i++) {
1351 Property p = (Property) properties [i];
1353 if (p.GetBuilder != null)
1354 members.Add (p.GetBuilder);
1355 if (p.SetBuilder != null)
1356 members.Add (p.SetBuilder);
1360 if (indexers != null) {
1361 int len = indexers.Count;
1362 for (int i = 0; i < len; i++) {
1363 Indexer ix = (Indexer) indexers [i];
1365 if (ix.GetBuilder != null)
1366 members.Add (ix.GetBuilder);
1367 if (ix.SetBuilder != null)
1368 members.Add (ix.SetBuilder);
1372 if (events != null) {
1373 int len = events.Count;
1374 for (int i = 0; i < len; i++) {
1375 Event e = (Event) events [i];
1377 if (e.AddBuilder != null)
1378 members.Add (e.AddBuilder);
1379 if (e.RemoveBuilder != null)
1380 members.Add (e.RemoveBuilder);
1384 MethodInfo[] methods = new MethodInfo [members.Count];
1385 members.CopyTo (methods, 0);
1390 /// This method returns the members of this type just like Type.FindMembers would
1391 /// Only, we need to use this for types which are _being_ defined because MS'
1392 /// implementation can't take care of that.
1395 // FIXME: return an empty static array instead of null, that cleans up
1396 // some code and is consistent with some coding conventions I just found
1400 // Notice that in various cases we check if our field is non-null,
1401 // something that would normally mean that there was a bug elsewhere.
1403 // The problem happens while we are defining p-invoke methods, as those
1404 // will trigger a FindMembers, but this happens before things are defined
1406 // Since the whole process is a no-op, it is fine to check for null here.
1408 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1409 MemberFilter filter, object criteria)
1411 ArrayList members = null;
1414 if ((bf & BindingFlags.Public) != 0)
1415 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1417 if ((bf & BindingFlags.NonPublic) != 0)
1418 modflags |= Modifiers.PRIVATE;
1420 int static_mask = 0, static_flags = 0;
1421 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1422 case BindingFlags.Static:
1423 static_mask = static_flags = Modifiers.STATIC;
1426 case BindingFlags.Instance:
1427 static_mask = Modifiers.STATIC;
1432 static_mask = static_flags = 0;
1436 Timer.StartTimer (TimerType.TcFindMembers);
1439 filter = accepting_filter;
1441 if ((mt & MemberTypes.Field) != 0) {
1442 if (fields != null) {
1443 int len = fields.Count;
1444 for (int i = 0; i < len; i++) {
1445 Field f = (Field) fields [i];
1447 if ((f.ModFlags & modflags) == 0)
1449 if ((f.ModFlags & static_mask) != static_flags)
1452 FieldBuilder fb = f.FieldBuilder;
1453 if (fb != null && filter (fb, criteria) == true) {
1454 if (members == null)
1455 members = new ArrayList ();
1462 if (constants != null) {
1463 int len = constants.Count;
1464 for (int i = 0; i < len; i++) {
1465 Const con = (Const) constants [i];
1467 if ((con.ModFlags & modflags) == 0)
1469 if ((con.ModFlags & static_mask) != static_flags)
1472 FieldBuilder fb = con.FieldBuilder;
1473 if (fb != null && filter (fb, criteria) == true) {
1474 if (members == null)
1475 members = new ArrayList ();
1483 if ((mt & MemberTypes.Method) != 0) {
1484 if (methods != null) {
1485 int len = methods.Count;
1486 for (int i = 0; i < len; i++) {
1487 Method m = (Method) methods [i];
1489 if ((m.ModFlags & modflags) == 0)
1491 if ((m.ModFlags & static_mask) != static_flags)
1494 MethodBuilder mb = m.MethodBuilder;
1496 if (mb != null && filter (mb, criteria) == true) {
1497 if (members == null)
1498 members = new ArrayList ();
1505 if (operators != null) {
1506 int len = operators.Count;
1507 for (int i = 0; i < len; i++) {
1508 Operator o = (Operator) operators [i];
1510 if ((o.ModFlags & modflags) == 0)
1512 if ((o.ModFlags & static_mask) != static_flags)
1515 MethodBuilder ob = o.OperatorMethodBuilder;
1516 if (ob != null && filter (ob, criteria) == true) {
1517 if (members == null)
1518 members = new ArrayList ();
1525 if (properties != null) {
1526 int len = properties.Count;
1527 for (int i = 0; i < len; i++) {
1528 Property p = (Property) properties [i];
1530 if ((p.ModFlags & modflags) == 0)
1532 if ((p.ModFlags & static_mask) != static_flags)
1538 if (b != null && filter (b, criteria) == true) {
1539 if (members == null)
1540 members = new ArrayList ();
1546 if (b != null && filter (b, criteria) == true) {
1547 if (members == null)
1548 members = new ArrayList ();
1555 if (indexers != null) {
1556 int len = indexers.Count;
1557 for (int i = 0; i < len; i++) {
1558 Indexer ix = (Indexer) indexers [i];
1560 if ((ix.ModFlags & modflags) == 0)
1562 if ((ix.ModFlags & static_mask) != static_flags)
1568 if (b != null && filter (b, criteria) == true) {
1569 if (members == null)
1570 members = new ArrayList ();
1576 if (b != null && filter (b, criteria) == true) {
1577 if (members == null)
1578 members = new ArrayList ();
1586 if ((mt & MemberTypes.Event) != 0) {
1587 if (events != null) {
1588 int len = events.Count;
1589 for (int i = 0; i < len; i++) {
1590 Event e = (Event) events [i];
1592 if ((e.ModFlags & modflags) == 0)
1594 if ((e.ModFlags & static_mask) != static_flags)
1597 MemberInfo eb = e.EventBuilder;
1598 if (eb != null && filter (eb, criteria) == true) {
1599 if (members == null)
1600 members = new ArrayList ();
1602 members.Add (e.EventBuilder);
1608 if ((mt & MemberTypes.Property) != 0){
1609 if (properties != null) {
1610 int len = properties.Count;
1611 for (int i = 0; i < len; i++) {
1612 Property p = (Property) properties [i];
1614 if ((p.ModFlags & modflags) == 0)
1616 if ((p.ModFlags & static_mask) != static_flags)
1619 MemberInfo pb = p.PropertyBuilder;
1620 if (pb != null && filter (pb, criteria) == true) {
1621 if (members == null)
1622 members = new ArrayList ();
1624 members.Add (p.PropertyBuilder);
1629 if (indexers != null) {
1630 int len = indexers.Count;
1631 for (int i = 0; i < len; i++) {
1632 Indexer ix = (Indexer) indexers [i];
1634 if ((ix.ModFlags & modflags) == 0)
1636 if ((ix.ModFlags & static_mask) != static_flags)
1639 MemberInfo ib = ix.PropertyBuilder;
1640 if (ib != null && filter (ib, criteria) == true) {
1641 if (members == null)
1642 members = new ArrayList ();
1644 members.Add (ix.PropertyBuilder);
1650 if ((mt & MemberTypes.NestedType) != 0) {
1651 if (types != null) {
1652 int len = types.Count;
1653 for (int i = 0; i < len; i++) {
1654 TypeContainer t = (TypeContainer) types [i];
1656 if ((t.ModFlags & modflags) == 0)
1659 TypeBuilder tb = t.TypeBuilder;
1660 if (tb != null && (filter (tb, criteria) == true)) {
1661 if (members == null)
1662 members = new ArrayList ();
1669 if (enums != null) {
1670 int len = enums.Count;
1671 for (int i = 0; i < len; i++) {
1672 Enum en = (Enum) enums [i];
1674 if ((en.ModFlags & modflags) == 0)
1677 TypeBuilder tb = en.TypeBuilder;
1678 if (tb != null && (filter (tb, criteria) == true)) {
1679 if (members == null)
1680 members = new ArrayList ();
1687 if (delegates != null) {
1688 int len = delegates.Count;
1689 for (int i = 0; i < len; i++) {
1690 Delegate d = (Delegate) delegates [i];
1692 if ((d.ModFlags & modflags) == 0)
1695 TypeBuilder tb = d.TypeBuilder;
1696 if (tb != null && (filter (tb, criteria) == true)) {
1697 if (members == null)
1698 members = new ArrayList ();
1705 if (interfaces != null) {
1706 int len = interfaces.Count;
1707 for (int i = 0; i < len; i++) {
1708 Interface iface = (Interface) interfaces [i];
1710 if ((iface.ModFlags & modflags) == 0)
1713 TypeBuilder tb = iface.TypeBuilder;
1714 if (tb != null && (filter (tb, criteria) == true)) {
1715 if (members == null)
1716 members = new ArrayList ();
1724 if ((mt & MemberTypes.Constructor) != 0){
1725 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1726 int len = instance_constructors.Count;
1727 for (int i = 0; i < len; i++) {
1728 Constructor c = (Constructor) instance_constructors [i];
1730 ConstructorBuilder cb = c.ConstructorBuilder;
1731 if (cb != null && filter (cb, criteria) == true) {
1732 if (members == null)
1733 members = new ArrayList ();
1740 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1741 ConstructorBuilder cb =
1742 default_static_constructor.ConstructorBuilder;
1744 if (cb != null && filter (cb, criteria) == true) {
1745 if (members == null)
1746 members = new ArrayList ();
1754 // Lookup members in parent if requested.
1756 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1757 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1758 if (list.Count > 0) {
1759 if (members == null)
1760 members = new ArrayList ();
1762 members.AddRange (list);
1766 Timer.StopTimer (TimerType.TcFindMembers);
1768 if (members == null)
1769 return MemberList.Empty;
1771 return new MemberList (members);
1774 public override MemberCache MemberCache {
1776 return member_cache;
1780 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1781 MemberFilter filter, object criteria)
1783 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1786 return ds.FindMembers (mt, bf, filter, criteria);
1788 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1792 // FindMethods will look for methods not only in the type `t', but in
1793 // any interfaces implemented by the type.
1795 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1796 MemberFilter filter, object criteria)
1802 /// Emits the values for the constants
1804 public void EmitConstants ()
1806 if (constants != null)
1807 foreach (Const con in constants)
1813 /// Emits the code, this step is performed after all
1814 /// the types, enumerations, constructors
1818 if (instance_constructors != null)
1819 foreach (Constructor c in instance_constructors)
1822 if (default_static_constructor != null)
1823 default_static_constructor.Emit (this);
1825 if (methods != null)
1826 foreach (Method m in methods)
1829 if (operators != null)
1830 foreach (Operator o in operators)
1833 if (properties != null)
1834 foreach (Property p in properties)
1837 if (indexers != null){
1838 foreach (Indexer ix in indexers)
1841 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1842 TypeBuilder.SetCustomAttribute (cb);
1846 foreach (Field f in fields)
1849 if (events != null){
1850 foreach (Event e in Events)
1854 if (Pending != null)
1855 if (Pending.VerifyPendingMethods ())
1858 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1861 // Check for internal or private fields that were never assigned
1863 if (RootContext.WarningLevel >= 3) {
1864 if (fields != null){
1865 foreach (Field f in fields) {
1866 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1869 if ((f.status & Field.Status.USED) == 0){
1871 169, f.Location, "Private field " +
1872 MakeName (f.Name) + " is never used");
1877 // Only report 649 on level 4
1879 if (RootContext.WarningLevel < 4)
1882 if ((f.status & Field.Status.ASSIGNED) != 0)
1887 "Field " + MakeName (f.Name) + " is never assigned " +
1888 " to and will always have its default value");
1892 if (events != null){
1893 foreach (Event e in events){
1895 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1900 // if (types != null)
1901 // foreach (TypeContainer tc in types)
1905 CustomAttributeBuilder EmitDefaultMemberAttr ()
1907 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1909 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1910 ".ctor", MemberTypes.Constructor,
1911 BindingFlags.Public | BindingFlags.Instance,
1914 MethodGroupExpr mg = (MethodGroupExpr) ml;
1916 MethodBase constructor = mg.Methods [0];
1918 string [] vals = { IndexerName };
1920 CustomAttributeBuilder cb = null;
1922 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1924 Report.Warning (-100, "Can not set the indexer default member attribute");
1930 public override void CloseType ()
1937 TypeBuilder.CreateType ();
1938 } catch (TypeLoadException){
1940 // This is fine, the code still created the type
1942 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1943 // Console.WriteLine (e.Message);
1945 Console.WriteLine ("In type: " + Name);
1950 foreach (Enum en in Enums)
1953 if (interface_order != null){
1954 foreach (Interface iface in interface_order)
1959 foreach (TypeContainer tc in Types)
1963 foreach (TypeContainer tc in Types)
1964 if (!(tc is Struct))
1968 if (Delegates != null)
1969 foreach (Delegate d in Delegates)
1977 initialized_fields = null;
1978 initialized_static_fields = null;
1981 interface_order = null;
1987 default_constructor = null;
1988 default_static_constructor = null;
1990 OptAttributes = null;
1992 parent_container = null;
1993 member_cache = null;
1996 public string MakeName (string n)
1998 return "`" + Name + "." + n + "'";
2001 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2004 108, l, "The keyword new is required on " +
2005 MakeName (mi.Name) + " because it hides `" +
2006 mi.ReflectedType.Name + "." + mi.Name + "'");
2009 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2012 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2013 "inherited member, the keyword new is not required");
2016 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2019 72, l, MakeName (mi.Name) + " : cannot override; `" +
2020 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2023 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2029 // Performs the validation on a Method's modifiers (properties have
2030 // the same properties).
2032 public bool MethodModifiersValid (int flags, string n, Location loc)
2034 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2035 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2036 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2040 // At most one of static, virtual or override
2042 if ((flags & Modifiers.STATIC) != 0){
2043 if ((flags & vao) != 0){
2045 112, loc, "static method " + MakeName (n) + "can not be marked " +
2046 "as virtual, abstract or override");
2051 if (this is Struct){
2052 if ((flags & va) != 0){
2053 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2058 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2060 113, loc, MakeName (n) +
2061 " marked as override cannot be marked as new or virtual");
2066 // If the declaration includes the abstract modifier, then the
2067 // declaration does not include static, virtual or extern
2069 if ((flags & Modifiers.ABSTRACT) != 0){
2070 if ((flags & Modifiers.EXTERN) != 0){
2072 180, loc, MakeName (n) + " can not be both abstract and extern");
2076 if ((flags & Modifiers.VIRTUAL) != 0){
2078 503, loc, MakeName (n) + " can not be both abstract and virtual");
2082 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2084 513, loc, MakeName (n) +
2085 " is abstract but its container class is not");
2091 if ((flags & Modifiers.PRIVATE) != 0){
2092 if ((flags & vao) != 0){
2094 621, loc, MakeName (n) +
2095 " virtual or abstract members can not be private");
2100 if ((flags & Modifiers.SEALED) != 0){
2101 if ((flags & Modifiers.OVERRIDE) == 0){
2103 238, loc, MakeName (n) +
2104 " cannot be sealed because it is not an override");
2112 Hashtable builder_and_args;
2114 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2116 if (builder_and_args == null)
2117 builder_and_args = new Hashtable ();
2122 /// Performs checks for an explicit interface implementation. First it
2123 /// checks whether the `interface_type' is a base inteface implementation.
2124 /// Then it checks whether `name' exists in the interface type.
2126 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2130 if (ifaces != null){
2131 foreach (TypeExpr t in ifaces){
2132 if (t.Type == interface_type){
2140 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2151 string IMemberContainer.Name {
2157 Type IMemberContainer.Type {
2163 IMemberContainer IMemberContainer.Parent {
2165 return parent_container;
2169 MemberCache IMemberContainer.MemberCache {
2171 return member_cache;
2175 bool IMemberContainer.IsInterface {
2177 return this is Interface;
2181 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2183 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2185 if (GenericType != null)
2186 return TypeManager.FindMembers (GenericType, mt, new_bf,
2189 return FindMembers (mt, new_bf, null, null);
2193 // Operator pair checking
2196 class OperatorEntry {
2198 public Type ret_type;
2199 public Type type1, type2;
2201 public Operator.OpType ot;
2203 public OperatorEntry (int f, Operator o)
2207 ret_type = o.OperatorMethod.GetReturnType ();
2208 Type [] pt = o.OperatorMethod.ParameterTypes;
2212 ot = o.OperatorType;
2215 public override int GetHashCode ()
2217 return ret_type.GetHashCode ();
2220 public override bool Equals (object o)
2222 OperatorEntry other = (OperatorEntry) o;
2224 if (other.ret_type != ret_type)
2226 if (other.type1 != type1)
2228 if (other.type2 != type2)
2235 // Checks that some operators come in pairs:
2241 // They are matched based on the return type and the argument types
2243 void CheckPairedOperators ()
2245 Hashtable pairs = new Hashtable (null, null);
2246 Operator true_op = null;
2247 Operator false_op = null;
2248 bool has_equality_or_inequality = false;
2250 // Register all the operators we care about.
2251 foreach (Operator op in operators){
2254 switch (op.OperatorType){
2255 case Operator.OpType.Equality:
2257 has_equality_or_inequality = true;
2259 case Operator.OpType.Inequality:
2261 has_equality_or_inequality = true;
2264 case Operator.OpType.True:
2267 case Operator.OpType.False:
2271 case Operator.OpType.GreaterThan:
2273 case Operator.OpType.LessThan:
2276 case Operator.OpType.GreaterThanOrEqual:
2278 case Operator.OpType.LessThanOrEqual:
2284 OperatorEntry oe = new OperatorEntry (reg, op);
2286 object o = pairs [oe];
2290 oe = (OperatorEntry) o;
2295 if (true_op != null){
2296 if (false_op == null)
2297 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2298 } else if (false_op != null)
2299 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2302 // Look for the mistakes.
2304 foreach (DictionaryEntry de in pairs){
2305 OperatorEntry oe = (OperatorEntry) de.Key;
2312 case Operator.OpType.Equality:
2315 case Operator.OpType.Inequality:
2318 case Operator.OpType.GreaterThan:
2321 case Operator.OpType.LessThan:
2324 case Operator.OpType.GreaterThanOrEqual:
2327 case Operator.OpType.LessThanOrEqual:
2331 Report.Error (216, oe.op.Location,
2332 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2335 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2336 MethodSignature equals_ms = new MethodSignature (
2337 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2338 MethodSignature hash_ms = new MethodSignature (
2339 "GetHashCode", TypeManager.int32_type, new Type [0]);
2341 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2342 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2344 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2345 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2348 bool equals_ok = false;
2349 if ((equals_ml != null) && (equals_ml.Count == 1))
2350 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2351 bool hash_ok = false;
2352 if ((hash_ml != null) && (hash_ml.Count == 1))
2353 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2356 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2357 "not override Object.Equals (object o)");
2359 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2360 "not override Object.GetHashCode ()");
2366 public class Class : TypeContainer {
2368 // Modifiers allowed in a class declaration
2370 public const int AllowedModifiers =
2373 Modifiers.PROTECTED |
2374 Modifiers.INTERNAL |
2376 Modifiers.ABSTRACT |
2380 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2381 Attributes attrs, Location l)
2382 : base (ns, parent, name, attrs, l)
2386 if (parent.Parent == null)
2387 accmods = Modifiers.INTERNAL;
2389 accmods = Modifiers.PRIVATE;
2391 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2395 // FIXME: How do we deal with the user specifying a different
2398 public override TypeAttributes TypeAttr {
2400 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2405 public class Struct : TypeContainer {
2407 // Modifiers allowed in a struct declaration
2409 public const int AllowedModifiers =
2412 Modifiers.PROTECTED |
2413 Modifiers.INTERNAL |
2417 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2418 : base (ns, parent, name, attrs, l)
2422 if (parent.Parent == null)
2423 accmods = Modifiers.INTERNAL;
2425 accmods = Modifiers.PRIVATE;
2427 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2429 this.ModFlags |= Modifiers.SEALED;
2433 // FIXME: Allow the user to specify a different set of attributes
2434 // in some cases (Sealed for example is mandatory for a class,
2435 // but what SequentialLayout can be changed
2437 public override TypeAttributes TypeAttr {
2439 return base.TypeAttr |
2440 TypeAttributes.SequentialLayout |
2441 TypeAttributes.Sealed |
2442 TypeAttributes.BeforeFieldInit;
2450 public class Interface : TypeContainer, IMemberContainer {
2452 /// Modifiers allowed in a class declaration
2454 public const int AllowedModifiers =
2457 Modifiers.PROTECTED |
2458 Modifiers.INTERNAL |
2462 public Interface (NamespaceEntry ns, TypeContainer parent, string name, int mod,
2463 Attributes attrs, Location l)
2464 : base (ns, parent, name, attrs, l)
2468 if (parent.Parent == null)
2469 accmods = Modifiers.INTERNAL;
2471 accmods = Modifiers.PRIVATE;
2473 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2476 public override TypeAttributes TypeAttr {
2478 return base.TypeAttr |
2479 TypeAttributes.AutoLayout |
2480 TypeAttributes.Abstract |
2481 TypeAttributes.Interface;
2486 public abstract class MethodCore : MemberBase {
2487 public readonly Parameters Parameters;
2488 protected Block block;
2489 protected DeclSpace ds;
2492 // Parameters, cached for semantic analysis.
2494 protected InternalParameters parameter_info;
2495 protected Type [] parameter_types;
2498 // This is set from TypeContainer.DefineMembers if this method overrides something.
2500 public bool OverridesSomething;
2502 // Whether this is an operator method.
2503 public bool IsOperator;
2505 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2506 bool is_interface, MemberName name, Attributes attrs,
2507 Parameters parameters, Location loc)
2508 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2510 Parameters = parameters;
2511 IsInterface = is_interface;
2516 // Returns the System.Type array for the parameters of this method
2518 public Type [] ParameterTypes {
2520 return parameter_types;
2524 public InternalParameters ParameterInfo
2527 return parameter_info;
2531 public Block Block {
2541 protected virtual bool DoDefineParameters ()
2543 // Check if arguments were correct
2544 parameter_types = Parameters.GetParameterInfo (ds);
2545 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2548 parameter_info = new InternalParameters (ds, Parameters);
2550 Parameter array_param = Parameters.ArrayParameter;
2551 if ((array_param != null) &&
2552 (!array_param.ParameterType.IsArray ||
2553 (array_param.ParameterType.GetArrayRank () != 1))) {
2554 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2561 void error_425 (Type old, Type t, string name)
2563 Report.Error (425, Location,
2564 "The constraints of type parameter `{0}' " +
2565 "of method `{1}' must match the constraints for " +
2566 "type parameter `{2}' of method `{3}'",
2567 TypeManager.CSharpName (old), Name,
2568 TypeManager.CSharpName (t), name);
2571 protected override bool CheckGenericOverride (MethodInfo method, string name)
2573 ParameterData pd = Invocation.GetParameterData (method);
2575 for (int i = 0; i < ParameterTypes.Length; i++) {
2576 GenericConstraints ogc = pd.GenericConstraints (i);
2577 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
2579 if ((gc == null) && (ogc == null))
2582 Type ot = pd.ParameterType (i);
2583 Type t = ParameterTypes [i];
2585 if (!((gc != null) && (ogc != null))) {
2586 error_425 (ot, t, name);
2590 if (gc.HasConstructor != ogc.HasConstructor) {
2591 error_425 (ot, t, name);
2595 Type[] oct = ogc.Types;
2596 Type[] ct = gc.Types;
2598 if (oct.Length != ct.Length) {
2599 error_425 (ot, t, name);
2603 for (int j = 0; j < oct.Length; j++)
2604 if (!oct [j].Equals (ct [j])) {
2605 error_425 (ot, t, name);
2613 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2615 if ((method == this) || (method.Name != Name))
2618 Type[] param_types = method.ParameterTypes;
2619 if (param_types == null)
2622 if (param_types.Length != ParameterTypes.Length)
2628 Type[] infered_types = new Type [param_types.Length];
2629 may_unify = Invocation.InferTypeArguments (
2630 param_types, ParameterTypes, ref infered_types);
2633 infered_types = new Type [param_types.Length];
2634 may_unify = Invocation.InferTypeArguments (
2635 ParameterTypes, param_types, ref infered_types);
2638 for (int i = 0; i < param_types.Length; i++) {
2639 Type a = param_types [i];
2640 Type b = ParameterTypes [i];
2647 Report.Error (111, Location,
2648 "Class `{0}' already defines a member called " +
2649 "`{1}' with the same parameter types",
2652 } else if (may_unify) {
2653 Report.Error (408, Location,
2654 "`{0}' cannot define overload members that " +
2655 "may unify for some type parameter substitutions",
2663 public CallingConventions GetCallingConvention (bool is_class)
2665 CallingConventions cc = 0;
2667 cc = Parameters.GetCallingConvention ();
2670 if ((ModFlags & Modifiers.STATIC) == 0)
2671 cc |= CallingConventions.HasThis;
2673 // FIXME: How is `ExplicitThis' used in C#?
2679 // The method's attributes are passed in because we need to extract
2680 // the "return:" attribute from there to apply on the return type
2682 static public void LabelParameters (EmitContext ec,
2684 Parameters parameters,
2685 Attributes method_attrs,
2689 // Define each type attribute (in/out/ref) and
2690 // the argument names.
2692 Parameter [] p = parameters.FixedParameters;
2695 MethodBuilder mb = null;
2696 ConstructorBuilder cb = null;
2698 if (builder is MethodBuilder)
2699 mb = (MethodBuilder) builder;
2701 cb = (ConstructorBuilder) builder;
2704 for (i = 0; i < p.Length; i++) {
2705 ParameterBuilder pb;
2706 ParameterAttributes par_attr = p [i].Attributes;
2709 pb = cb.DefineParameter (
2710 i + 1, par_attr, p [i].Name);
2712 pb = mb.DefineParameter (
2713 i + 1, par_attr, p [i].Name);
2715 Attributes attr = p [i].OptAttributes;
2717 Attribute.ApplyAttributes (ec, pb, pb, attr);
2719 if (par_attr == ParameterAttributes.Out){
2720 if (attr.Contains (TypeManager.in_attribute_type))
2721 Report.Error (36, loc,
2722 "Can not use [In] attribute on out parameter");
2728 if (parameters.ArrayParameter != null){
2729 ParameterBuilder pb;
2730 Parameter array_param = parameters.ArrayParameter;
2733 pb = cb.DefineParameter (
2734 i + 1, array_param.Attributes,
2737 pb = mb.DefineParameter (
2738 i + 1, array_param.Attributes,
2741 CustomAttributeBuilder a = new CustomAttributeBuilder (
2742 TypeManager.cons_param_array_attribute, new object [0]);
2744 pb.SetCustomAttribute (a);
2748 // And now for the return type attribute decoration
2750 ParameterBuilder ret_pb;
2751 Attributes ret_attrs = null;
2753 if (mb == null || method_attrs == null)
2756 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2758 if (asec.Target != "return")
2761 if (ret_attrs == null)
2762 ret_attrs = new Attributes (asec);
2764 ret_attrs.AddAttributeSection (asec);
2767 if (ret_attrs != null) {
2769 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2770 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2772 } catch (ArgumentOutOfRangeException) {
2775 ".NET SDK 1.0 does not permit setting custom attributes" +
2776 " on the return type of a method");
2782 public class Method : MethodCore, IIteratorContainer {
2783 public MethodBuilder MethodBuilder;
2784 public MethodData MethodData;
2785 public readonly GenericMethod GenericMethod;
2788 /// Modifiers allowed in a class declaration
2790 const int AllowedModifiers =
2793 Modifiers.PROTECTED |
2794 Modifiers.INTERNAL |
2799 Modifiers.OVERRIDE |
2800 Modifiers.ABSTRACT |
2802 Modifiers.METHOD_YIELDS |
2805 const int AllowedInterfaceModifiers =
2809 // return_type can be "null" for VOID values.
2811 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2812 MemberName name, Parameters parameters, Attributes attrs,
2814 : base (ds, return_type, mod,
2815 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2816 is_iface, name, attrs, parameters, l)
2821 // return_type can be "null" for VOID values.
2823 public Method (GenericMethod generic, Expression return_type, int mod,
2824 bool is_iface, MemberName name, Parameters parameters,
2825 Attributes attrs, Location l)
2826 : this ((DeclSpace) generic, return_type, mod, is_iface, name,
2827 parameters, attrs, l)
2829 GenericMethod = generic;
2833 // Returns the `System.Type' for the ReturnType of this
2834 // function. Provides a nice cache. (used between semantic analysis
2835 // and actual code generation
2837 public Type GetReturnType ()
2842 void DuplicateEntryPoint (MethodInfo b, Location location)
2846 "Program `" + CodeGen.FileName +
2847 "' has more than one entry point defined: `" +
2848 TypeManager.CSharpSignature(b) + "'");
2851 void Report28 (MethodInfo b)
2855 "`" + TypeManager.CSharpSignature(b) +
2856 "' has the wrong signature to be an entry point");
2859 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2861 if (b.ReturnType != TypeManager.void_type &&
2862 b.ReturnType != TypeManager.int32_type)
2865 if (pinfo.Count == 0)
2868 if (pinfo.Count > 1)
2871 Type t = pinfo.ParameterType(0);
2873 (t.GetArrayRank() == 1) &&
2874 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2875 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2882 // Checks our base implementation if any
2884 protected override bool CheckBase (TypeContainer container)
2886 base.CheckBase (container);
2888 // Check whether arguments were correct.
2889 if (!DoDefineParameters ())
2892 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2894 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2897 // Check in our class for dups
2899 ArrayList ar = container.Methods;
2901 int arLen = ar.Count;
2903 for (int i = 0; i < arLen; i++) {
2904 Method m = (Method) ar [i];
2905 if (IsDuplicateImplementation (container, m))
2913 // Verify if the parent has a type with the same name, and then
2914 // check whether we have to create a new slot for it or not.
2916 Type ptype = container.TypeBuilder.BaseType;
2918 // ptype is only null for System.Object while compiling corlib.
2919 if (ptype != null) {
2922 // Explicit implementations do not have `parent' methods, however,
2923 // the member cache stores them there. Without this check, we get
2924 // an incorrect warning in corlib.
2926 if (! IsExplicitImpl) {
2927 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
2928 container.TypeBuilder, Name, ParameterTypes, false);
2931 if (parent_method != null) {
2932 string name = parent_method.DeclaringType.Name + "." +
2935 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2938 if ((ModFlags & Modifiers.NEW) == 0) {
2939 Type parent_ret = TypeManager.TypeToCoreType (
2940 parent_method.ReturnType);
2942 if (!parent_ret.Equals (MemberType)) {
2944 508, Location, container.MakeName (Name) + ": cannot " +
2945 "change return type when overriding " +
2946 "inherited member " + name);
2951 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2952 WarningNotHiding (container);
2954 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2955 Report.Error (115, Location,
2956 container.MakeName (Name) +
2957 " no suitable methods found to override");
2960 } else if ((ModFlags & Modifiers.NEW) != 0)
2961 WarningNotHiding (container);
2969 public override bool Define (TypeContainer container)
2972 MethodBuilder mb = null;
2973 if (GenericMethod != null) {
2974 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2975 if (!GenericMethod.Define (container, mb))
2977 decl = GenericMethod;
2981 if (!DoDefine (decl, container))
2984 if (!CheckBase (container))
2987 CallingConventions cc = GetCallingConvention (container is Class);
2989 MethodData = new MethodData (ds, this, null, MemberType,
2990 ParameterTypes, ParameterInfo, cc,
2991 OptAttributes, ModFlags, flags, true,
2994 if (!MethodData.Define (container))
2998 // Setup iterator if we are one
3000 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3001 IteratorHandler ih = new IteratorHandler (
3002 Name, container, MemberType,
3003 ParameterTypes, ParameterInfo,
3004 ModFlags, Location);
3006 Block new_block = ih.Setup (block);
3007 if (new_block == null)
3012 MethodBuilder = MethodData.MethodBuilder;
3015 // This is used to track the Entry Point,
3017 if (Name == "Main" &&
3018 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3019 (RootContext.MainClass == null ||
3020 RootContext.MainClass == container.TypeBuilder.FullName)){
3021 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3022 if (RootContext.EntryPoint == null) {
3023 if (container.IsGeneric){
3024 Report.Error (-201, Location,
3025 "Entry point can not be defined in a generic class");
3028 RootContext.EntryPoint = MethodBuilder;
3029 RootContext.EntryPointLocation = Location;
3031 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3032 DuplicateEntryPoint (MethodBuilder, Location);
3035 Report28(MethodBuilder);
3044 public void Emit (TypeContainer container)
3046 MethodData.Emit (container, Block, this);
3051 void IIteratorContainer.SetYields ()
3053 ModFlags |= Modifiers.METHOD_YIELDS;
3057 public abstract class ConstructorInitializer {
3058 ArrayList argument_list;
3059 ConstructorInfo parent_constructor;
3060 Parameters parameters;
3063 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3066 this.argument_list = argument_list;
3067 this.parameters = parameters;
3071 public ArrayList Arguments {
3073 return argument_list;
3077 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3079 Expression parent_constructor_group;
3082 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3084 if (argument_list != null){
3085 foreach (Argument a in argument_list){
3086 if (!a.Resolve (ec, loc))
3090 ec.CurrentBlock = null;
3092 if (this is ConstructorBaseInitializer) {
3093 if (ec.ContainerType.BaseType == null)
3096 t = ec.ContainerType.BaseType;
3097 if (ec.ContainerType.IsValueType) {
3098 Report.Error (522, loc,
3099 "structs cannot call base class constructors");
3103 t = ec.ContainerType;
3105 parent_constructor_group = Expression.MemberLookup (
3106 ec, t, null, t, ".ctor", 0,
3107 MemberTypes.Constructor,
3108 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3111 if (parent_constructor_group == null){
3112 Report.Error (1501, loc,
3113 "Can not find a constructor for this argument list");
3117 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3118 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3121 if (parent_constructor == null){
3122 Report.Error (1501, loc,
3123 "Can not find a constructor for this argument list");
3127 if (parent_constructor == caller_builder){
3128 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3135 public void Emit (EmitContext ec)
3137 if (parent_constructor != null){
3138 ec.Mark (loc, false);
3140 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3142 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3147 public class ConstructorBaseInitializer : ConstructorInitializer {
3148 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3149 base (argument_list, pars, l)
3154 public class ConstructorThisInitializer : ConstructorInitializer {
3155 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3156 base (argument_list, pars, l)
3161 public class Constructor : MethodCore {
3162 public ConstructorBuilder ConstructorBuilder;
3163 public ConstructorInitializer Initializer;
3166 // Modifiers allowed for a constructor.
3168 public const int AllowedModifiers =
3170 Modifiers.PROTECTED |
3171 Modifiers.INTERNAL |
3178 // The spec claims that static is not permitted, but
3179 // my very own code has static constructors.
3181 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3182 ConstructorInitializer init, Location l)
3183 : base (ds, null, mod, AllowedModifiers, false,
3184 new MemberName (name), null, args, l)
3190 // Returns true if this is a default constructor
3192 public bool IsDefault ()
3194 if ((ModFlags & Modifiers.STATIC) != 0)
3195 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3196 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3199 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3200 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3201 (Initializer is ConstructorBaseInitializer) &&
3202 (Initializer.Arguments == null);
3205 protected override bool CheckBase (TypeContainer container)
3207 base.CheckBase (container);
3209 // Check whether arguments were correct.
3210 if (!DoDefineParameters ())
3213 if ((ModFlags & Modifiers.STATIC) != 0)
3216 if (container is Struct && ParameterTypes.Length == 0) {
3217 Report.Error (568, Location,
3218 "Structs can not contain explicit parameterless " +
3224 // Check in our class for dups
3226 ArrayList ar = container.InstanceConstructors;
3228 int arLen = ar.Count;
3230 for (int i = 0; i < arLen; i++) {
3231 Constructor m = (Constructor) ar [i];
3232 if (IsDuplicateImplementation (container, m))
3241 // Creates the ConstructorBuilder
3243 public override bool Define (TypeContainer container)
3245 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3246 MethodAttributes.SpecialName);
3248 if ((ModFlags & Modifiers.STATIC) != 0){
3249 ca |= MethodAttributes.Static | MethodAttributes.Private;
3251 ca |= MethodAttributes.HideBySig;
3253 if ((ModFlags & Modifiers.PUBLIC) != 0)
3254 ca |= MethodAttributes.Public;
3255 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3256 if ((ModFlags & Modifiers.INTERNAL) != 0)
3257 ca |= MethodAttributes.FamORAssem;
3259 ca |= MethodAttributes.Family;
3260 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3261 ca |= MethodAttributes.Assembly;
3262 else if (IsDefault ())
3263 ca |= MethodAttributes.Public;
3265 ca |= MethodAttributes.Private;
3268 // Check if arguments were correct.
3269 if (!CheckBase (container))
3272 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3273 ca, GetCallingConvention (container is Class), ParameterTypes);
3275 if ((ModFlags & Modifiers.UNSAFE) != 0)
3276 ConstructorBuilder.InitLocals = false;
3279 // HACK because System.Reflection.Emit is lame
3281 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3289 public void Emit (TypeContainer container)
3291 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3292 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3295 // extern methods have no bodies
3297 if ((ModFlags & Modifiers.EXTERN) != 0) {
3298 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3300 179, Location, "External constructor `" +
3301 TypeManager.CSharpSignature (ConstructorBuilder) +
3302 "' can not have a body");
3305 } else if (block == null) {
3307 501, Location, "Constructor `" +
3308 TypeManager.CSharpSignature (ConstructorBuilder) +
3309 "' must declare a body since it is not marked extern");
3313 if ((ModFlags & Modifiers.STATIC) == 0){
3314 if (container is Class && Initializer == null)
3315 Initializer = new ConstructorBaseInitializer (
3316 null, Parameters.EmptyReadOnlyParameters, Location);
3320 // Spec mandates that Initializers will not have
3324 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3326 ec.IsStatic = false;
3329 MethodCore.LabelParameters (ec, ConstructorBuilder,
3330 Parameters, OptAttributes, Location);
3332 SymbolWriter sw = CodeGen.SymbolWriter;
3333 bool generate_debugging = false;
3335 if ((sw != null) && (block != null) &&
3336 !Location.IsNull (Location) &&
3337 !Location.IsNull (block.EndLocation) &&
3338 (Location.SymbolDocument != null)) {
3339 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3341 generate_debugging = true;
3345 // Classes can have base initializers and instance field initializers.
3347 if (container is Class){
3348 if ((ModFlags & Modifiers.STATIC) == 0){
3351 // If we use a "this (...)" constructor initializer, then
3352 // do not emit field initializers, they are initialized in the other constructor
3354 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3355 container.EmitFieldInitializers (ec);
3358 if (Initializer != null)
3359 Initializer.Emit (ec);
3361 if ((ModFlags & Modifiers.STATIC) != 0)
3362 container.EmitFieldInitializers (ec);
3364 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
3366 // If this is a non-static `struct' constructor and doesn't have any
3367 // initializer, it must initialize all of the struct's fields.
3368 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3369 Block.AddThisVariable (container, Location);
3371 ec.EmitTopBlock (block, ParameterInfo, Location);
3373 if (generate_debugging)
3381 // Encapsulates most of the Method's state
3383 public class MethodData {
3385 // The return type of this method
3387 public readonly Type ReturnType;
3388 public readonly Type[] ParameterTypes;
3389 public readonly GenericMethod GenericMethod;
3390 public readonly InternalParameters ParameterInfo;
3391 public readonly CallingConventions CallingConventions;
3392 public readonly Attributes OptAttributes;
3393 public readonly Location Location;
3396 // Are we implementing an interface ?
3398 public bool IsImplementing = false;
3403 protected DeclSpace ds;
3404 protected MemberBase member;
3405 protected int modifiers;
3406 protected MethodAttributes flags;
3407 protected bool is_method;
3408 protected string accessor_name;
3409 protected Type declaring_type;
3412 // It can either hold a string with the condition, or an arraylist of conditions.
3413 object conditionals;
3416 MethodBuilder builder = null;
3417 public MethodBuilder MethodBuilder {
3423 public Type DeclaringType {
3425 return declaring_type;
3429 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3430 Type [] parameter_types, InternalParameters parameters,
3431 CallingConventions cc, Attributes opt_attrs,
3432 int modifiers, MethodAttributes flags, bool is_method)
3435 this.member = member;
3436 this.accessor_name = name;
3437 this.ReturnType = return_type;
3438 this.ParameterTypes = parameter_types;
3439 this.ParameterInfo = parameters;
3440 this.CallingConventions = cc;
3441 this.OptAttributes = opt_attrs;
3442 this.modifiers = modifiers;
3444 this.is_method = is_method;
3445 this.Location = member.Location;
3446 this.conditionals = null;
3449 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
3450 Type [] parameter_types, InternalParameters parameters,
3451 CallingConventions cc, Attributes opt_attrs,
3452 int modifiers, MethodAttributes flags, bool is_method,
3453 MethodBuilder builder, GenericMethod generic)
3454 : this (ds, member, name, return_type, parameter_types, parameters,
3455 cc, opt_attrs, modifiers, flags, is_method)
3457 this.builder = builder;
3458 this.GenericMethod = generic;
3464 Attribute dllimport_attribute = null;
3465 string obsolete = null;
3466 bool obsolete_error = false;
3468 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
3470 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
3473 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
3474 if (asec.Attributes == null)
3477 foreach (Attribute a in asec.Attributes) {
3478 if (a.Name == "Conditional") {
3479 if (!ApplyConditionalAttribute (a))
3481 } else if (a.Name == "Obsolete") {
3482 if (!ApplyObsoleteAttribute (a))
3484 } else if (a.Name.IndexOf ("DllImport") != -1) {
3486 a.Type = TypeManager.dllimport_type;
3487 Attribute.Error_AttributeNotValidForElement (a, Location);
3490 if (!ApplyDllImportAttribute (a))
3500 // Applies the `DllImport' attribute to the method.
3502 protected virtual bool ApplyDllImportAttribute (Attribute a)
3504 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3505 if ((modifiers & extern_static) != extern_static) {
3506 Report.Error (601, Location,
3507 "The DllImport attribute must be specified on a method " +
3508 "marked `static' and `extern'.");
3512 flags |= MethodAttributes.PinvokeImpl;
3513 dllimport_attribute = a;
3518 // Applies the `Obsolete' attribute to the method.
3520 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3522 if (obsolete != null) {
3523 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3527 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3528 return obsolete != null;
3532 // Applies the `Conditional' attribute to the method.
3534 protected virtual bool ApplyConditionalAttribute (Attribute a)
3536 // The Conditional attribute is only valid on methods.
3538 Attribute.Error_AttributeNotValidForElement (a, Location);
3542 string condition = a.Conditional_GetConditionName ();
3544 if (condition == null)
3547 if (ReturnType != TypeManager.void_type) {
3548 Report.Error (578, Location,
3549 "Conditional not valid on `" + member.Name + "' " +
3550 "because its return type is not void");
3554 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3555 Report.Error (243, Location,
3556 "Conditional not valid on `" + member.Name + "' " +
3557 "because it is an override method");
3561 if (member.IsExplicitImpl) {
3562 Report.Error (577, Location,
3563 "Conditional not valid on `" + member.Name + "' " +
3564 "because it is an explicit interface implementation");
3568 if (IsImplementing) {
3569 Report.Error (623, Location,
3570 "Conditional not valid on `" + member.Name + "' " +
3571 "because it is an interface method");
3576 // The likelyhood that the conditional will be more than 1 is very slim
3578 if (conditionals == null)
3579 conditionals = condition;
3580 else if (conditionals is string){
3581 string s = (string) conditionals;
3582 conditionals = new ArrayList ();
3583 ((ArrayList)conditionals).Add (s);
3585 ((ArrayList)conditionals).Add (condition);
3591 // Checks whether this method should be ignored due to its Conditional attributes.
3593 bool ShouldIgnore (Location loc)
3595 // When we're overriding a virtual method, we implicitly inherit the
3596 // Conditional attributes from our parent.
3597 if (member.ParentMethod != null) {
3598 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3599 member.ParentMethod, loc);
3601 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3605 if (conditionals != null){
3606 if (conditionals is string){
3607 if (RootContext.AllDefines [conditionals] == null)
3610 foreach (string condition in (ArrayList) conditionals)
3611 if (RootContext.AllDefines [condition] == null)
3619 // Returns the TypeManager.MethodFlags for this method.
3620 // This emits an error 619 / warning 618 if the method is obsolete.
3621 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3623 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3625 TypeManager.MethodFlags flags = 0;
3627 if (obsolete != null) {
3628 if (obsolete_error) {
3629 Report.Error (619, loc, "Method `" + member.Name +
3630 "' is obsolete: `" + obsolete + "'");
3631 return TypeManager.MethodFlags.IsObsoleteError;
3633 Report.Warning (618, loc, "Method `" + member.Name +
3634 "' is obsolete: `" + obsolete + "'");
3636 flags |= TypeManager.MethodFlags.IsObsolete;
3639 if (ShouldIgnore (loc))
3640 flags |= TypeManager.MethodFlags.ShouldIgnore;
3645 public virtual bool Define (TypeContainer container)
3647 MethodInfo implementing = null;
3648 string method_name, name, prefix;
3650 if (OptAttributes != null)
3651 if (!ApplyAttributes (OptAttributes, is_method))
3654 if (member.IsExplicitImpl)
3655 prefix = member.InterfaceType.FullName + ".";
3659 if (accessor_name != null)
3660 name = accessor_name + "_" + member.ShortName;
3662 name = member.ShortName;
3663 method_name = prefix + name;
3665 if (container.Pending != null){
3666 if (member is Indexer)
3667 implementing = container.Pending.IsInterfaceIndexer (
3668 member.InterfaceType, ReturnType, ParameterTypes);
3670 implementing = container.Pending.IsInterfaceMethod (
3671 member.InterfaceType, name, ReturnType, ParameterTypes);
3673 if (member.InterfaceType != null && implementing == null){
3674 Report.Error (539, Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3680 // For implicit implementations, make sure we are public, for
3681 // explicit implementations, make sure we are private.
3683 if (implementing != null){
3685 // Setting null inside this block will trigger a more
3686 // verbose error reporting for missing interface implementations
3688 // The "candidate" function has been flagged already
3689 // but it wont get cleared
3691 if (member.IsExplicitImpl){
3692 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3693 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3694 implementing = null;
3696 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3697 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3699 // If this is an interface method implementation,
3700 // check for public accessibility
3702 implementing = null;
3703 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3704 // We may never be private.
3705 implementing = null;
3706 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3708 // We may be protected if we're overriding something.
3710 implementing = null;
3715 // Static is not allowed
3717 if ((modifiers & Modifiers.STATIC) != 0){
3718 implementing = null;
3719 Modifiers.Error_InvalidModifier (Location, "static");
3724 // If implementing is still valid, set flags
3726 if (implementing != null){
3728 // When implementing interface methods, set NewSlot
3729 // unless, we are overwriting a method.
3731 if (implementing.DeclaringType.IsInterface){
3732 if ((modifiers & Modifiers.OVERRIDE) == 0)
3733 flags |= MethodAttributes.NewSlot;
3736 MethodAttributes.Virtual |
3737 MethodAttributes.HideBySig;
3739 // Set Final unless we're virtual, abstract or already overriding a method.
3740 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3741 flags |= MethodAttributes.Final;
3743 // Get the method name from the explicit interface.
3744 if (member.InterfaceType != null) {
3745 name = implementing.Name;
3746 method_name = prefix + name;
3749 IsImplementing = true;
3752 ec = new EmitContext (
3753 container, ds, Location, null, ReturnType, modifiers, false);
3756 // Create the MethodBuilder for the method
3758 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3759 if ((modifiers & Modifiers.STATIC) == 0) {
3760 Report.Error (601, Location,
3761 "The DllImport attribute must be specified on " +
3762 "a method marked 'static' and 'extern'.");
3765 builder = dllimport_attribute.DefinePInvokeMethod (
3766 ec, container.TypeBuilder, method_name, flags,
3767 ReturnType, ParameterTypes);
3768 } else if (builder == null)
3769 builder = container.TypeBuilder.DefineMethod (
3770 method_name, flags, CallingConventions,
3771 ReturnType, ParameterTypes);
3773 builder.SetGenericMethodSignature (
3774 flags, CallingConventions,
3775 ReturnType, ParameterTypes);
3777 if (builder == null)
3780 if (GenericMethod != null) {
3781 if (!GenericMethod.DefineType (ec, builder))
3785 if (container.CurrentType != null)
3786 declaring_type = container.CurrentType.ResolveType (ec);
3788 declaring_type = container.TypeBuilder;
3790 if ((modifiers & Modifiers.UNSAFE) != 0)
3791 builder.InitLocals = false;
3793 if (IsImplementing){
3795 // clear the pending implemntation flag
3797 if (member is Indexer) {
3798 container.Pending.ImplementIndexer (
3799 member.InterfaceType, builder, ReturnType,
3800 ParameterTypes, true);
3802 container.Pending.ImplementMethod (
3803 member.InterfaceType, name, ReturnType,
3804 ParameterTypes, member.IsExplicitImpl);
3806 if (member.IsExplicitImpl)
3807 container.TypeBuilder.DefineMethodOverride (
3808 builder, implementing);
3812 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3813 Report.Error (111, Location,
3814 "Class `" + container.Name +
3815 "' already contains a definition with the " +
3816 "same return value and parameter types as the " +
3817 "'get' method of property `" + member.Name + "'");
3821 TypeManager.AddMethod (builder, this);
3829 public virtual void Emit (TypeContainer container, Block block, object kind)
3834 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3835 ig = builder.GetILGenerator ();
3839 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3841 if (OptAttributes != null)
3842 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3844 if (member is MethodCore)
3845 MethodCore.LabelParameters (ec, MethodBuilder,
3846 ((MethodCore) member).Parameters,
3850 SymbolWriter sw = CodeGen.SymbolWriter;
3853 // abstract or extern methods have no bodies
3855 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3856 if (block == null) {
3857 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
3858 !Location.IsNull (Location) &&
3859 (Location.SymbolDocument != null)) {
3860 sw.OpenMethod (container, MethodBuilder, Location, Location);
3868 // abstract or extern methods have no bodies.
3870 if ((modifiers & Modifiers.ABSTRACT) != 0)
3872 500, Location, "Abstract method `" +
3873 TypeManager.CSharpSignature (builder) +
3874 "' can not have a body");
3876 if ((modifiers & Modifiers.EXTERN) != 0)
3878 179, Location, "External method `" +
3879 TypeManager.CSharpSignature (builder) +
3880 "' can not have a body");
3886 // Methods must have a body unless they're extern or abstract
3888 if (block == null) {
3890 501, Location, "Method `" +
3891 TypeManager.CSharpSignature (builder) +
3892 "' must declare a body since it is not marked " +
3893 "abstract or extern");
3898 // Handle destructors specially
3900 // FIXME: This code generates buggy code
3902 if ((sw != null) && !Location.IsNull (Location) &&
3903 !Location.IsNull (block.EndLocation) &&
3904 (Location.SymbolDocument != null)) {
3905 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3907 if (member is Destructor)
3908 EmitDestructor (ec, block);
3910 ec.EmitTopBlock (block, ParameterInfo, Location);
3914 if (member is Destructor)
3915 EmitDestructor (ec, block);
3917 ec.EmitTopBlock (block, ParameterInfo, Location);
3921 void EmitDestructor (EmitContext ec, Block block)
3923 ILGenerator ig = ec.ig;
3925 Label finish = ig.DefineLabel ();
3927 block.SetDestructor ();
3929 ig.BeginExceptionBlock ();
3930 ec.ReturnLabel = finish;
3931 ec.HasReturnLabel = true;
3932 ec.EmitTopBlock (block, null, Location);
3934 // ig.MarkLabel (finish);
3935 ig.BeginFinallyBlock ();
3937 if (ec.ContainerType.BaseType != null) {
3938 Expression member_lookup = Expression.MemberLookup (
3939 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3940 "Finalize", 0, MemberTypes.Method, Expression.AllBindingFlags, Location);
3942 if (member_lookup != null){
3943 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3945 ig.Emit (OpCodes.Ldarg_0);
3946 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3950 ig.EndExceptionBlock ();
3951 //ig.MarkLabel (ec.ReturnLabel);
3952 ig.Emit (OpCodes.Ret);
3956 public class Destructor : Method {
3958 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
3959 Parameters parameters, Attributes attrs, Location l)
3960 : base (ds, return_type, mod, false, new MemberName (name),
3961 parameters, attrs, l)
3966 abstract public class MemberBase : MemberCore {
3967 public Expression Type;
3969 protected MethodAttributes flags;
3971 protected readonly int explicit_mod_flags;
3973 public readonly MemberName MemberName;
3976 // The "short" name of this property / indexer / event. This is the
3977 // name without the explicit interface.
3979 public string ShortName;
3982 // The type of this property / indexer / event
3984 public Type MemberType;
3987 // If true, this is an explicit interface implementation
3989 public bool IsExplicitImpl = false;
3992 // The name of the interface we are explicitly implementing
3994 public Expression ExplicitInterfaceName = null;
3997 // Whether this is an interface member.
3999 public bool IsInterface;
4002 // If true, the interface type we are explicitly implementing
4004 public Type InterfaceType = null;
4007 // The method we're overriding if this is an override method.
4009 protected MethodInfo parent_method = null;
4010 public MethodInfo ParentMethod {
4012 return parent_method;
4017 // The constructor is only exposed to our children
4019 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod,
4020 MemberName name, Attributes attrs, Location loc)
4021 : base (name.GetMemberName (), attrs, loc)
4023 explicit_mod_flags = mod;
4026 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4029 protected virtual bool CheckBase (TypeContainer container)
4031 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4032 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4033 if (container is Struct){
4034 Report.Error (666, Location, "Protected member in struct declaration");
4037 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4043 protected void WarningNotHiding (TypeContainer parent)
4047 "The member " + parent.MakeName (Name) + " does not hide an " +
4048 "inherited member. The keyword new is not required");
4052 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4056 // FIXME: report the old/new permissions?
4059 507, Location, parent.MakeName (Name) +
4060 ": can't change the access modifiers when overriding inherited " +
4061 "member `" + name + "'");
4064 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4067 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4068 // that have been defined.
4070 // `name' is the user visible name for reporting errors (this is used to
4071 // provide the right name regarding method names and properties)
4073 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4074 MethodInfo mb, string name)
4078 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4079 if (!(mb.IsAbstract || mb.IsVirtual)){
4081 506, Location, parent.MakeName (Name) +
4082 ": cannot override inherited member `" +
4083 name + "' because it is not " +
4084 "virtual, abstract or override");
4088 // Now we check that the overriden method is not final
4091 // This happens when implementing interface methods.
4092 if (mb.IsHideBySig && mb.IsVirtual) {
4094 506, Location, parent.MakeName (Name) +
4095 ": cannot override inherited member `" +
4096 name + "' because it is not " +
4097 "virtual, abstract or override");
4099 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4100 "override inherited member `" + name +
4101 "' because it is sealed.");
4106 // Check that the constraints match when overriding a
4110 if (!CheckGenericOverride (mb, name))
4114 // Check that the permissions are not being changed
4116 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4117 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4120 // special case for "protected internal"
4123 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4125 // when overriding protected internal, the method can be declared
4126 // protected internal only within the same assembly
4129 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4130 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4132 // assemblies differ - report an error
4135 Error_CannotChangeAccessModifiers (parent, mb, name);
4137 } else if (thisp != parentp) {
4139 // same assembly, but other attributes differ - report an error
4142 Error_CannotChangeAccessModifiers (parent, mb, name);
4145 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4147 // if it's not "protected internal", it must be "protected"
4150 Error_CannotChangeAccessModifiers (parent, mb, name);
4152 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4154 // protected within the same assembly - an error
4156 Error_CannotChangeAccessModifiers (parent, mb, name);
4158 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4159 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4161 // protected ok, but other attributes differ - report an error
4163 Error_CannotChangeAccessModifiers (parent, mb, name);
4167 if (thisp != parentp){
4168 Error_CannotChangeAccessModifiers (parent, mb, name);
4174 if (mb.IsVirtual || mb.IsAbstract){
4175 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4176 if (Name != "Finalize"){
4178 114, 2, Location, parent.MakeName (Name) +
4179 " hides inherited member `" + name +
4180 "'. To make the current member override that " +
4181 "implementation, add the override keyword, " +
4182 "otherwise use the new keyword");
4183 ModFlags |= Modifiers.NEW;
4187 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4188 if (Name != "Finalize"){
4190 108, 1, Location, "The keyword new is required on " +
4191 parent.MakeName (Name) + " because it hides " +
4192 "inherited member `" + name + "'");
4193 ModFlags |= Modifiers.NEW;
4201 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4205 foreach (Type partype in parameters){
4206 if (partype.IsPointer){
4209 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4213 if (ds.AsAccessible (partype, ModFlags))
4216 if (this is Indexer)
4217 Report.Error (55, Location,
4218 "Inconsistent accessibility: parameter type `" +
4219 TypeManager.CSharpName (partype) + "' is less " +
4220 "accessible than indexer `" + Name + "'");
4221 else if ((this is Method) && ((Method) this).IsOperator)
4222 Report.Error (57, Location,
4223 "Inconsistent accessibility: parameter type `" +
4224 TypeManager.CSharpName (partype) + "' is less " +
4225 "accessible than operator `" + Name + "'");
4227 Report.Error (51, Location,
4228 "Inconsistent accessibility: parameter type `" +
4229 TypeManager.CSharpName (partype) + "' is less " +
4230 "accessible than method `" + Name + "'");
4237 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
4243 ModFlags = Modifiers.PUBLIC |
4244 Modifiers.ABSTRACT |
4247 flags = MethodAttributes.Public |
4248 MethodAttributes.Abstract |
4249 MethodAttributes.HideBySig |
4250 MethodAttributes.NewSlot |
4251 MethodAttributes.Virtual;
4253 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4256 flags = Modifiers.MethodAttr (ModFlags);
4259 // Lookup Type, verify validity
4260 MemberType = decl.ResolveType (Type, false, Location);
4261 if (MemberType == null)
4264 if ((container.ModFlags & Modifiers.SEALED) != 0){
4265 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4266 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4271 // verify accessibility
4272 if (!container.AsAccessible (MemberType, ModFlags)) {
4273 if (this is Property)
4274 Report.Error (53, Location,
4275 "Inconsistent accessibility: property type `" +
4276 TypeManager.CSharpName (MemberType) + "' is less " +
4277 "accessible than property `" + Name + "'");
4278 else if (this is Indexer)
4279 Report.Error (54, Location,
4280 "Inconsistent accessibility: indexer return type `" +
4281 TypeManager.CSharpName (MemberType) + "' is less " +
4282 "accessible than indexer `" + Name + "'");
4283 else if (this is Method) {
4284 if (((Method) this).IsOperator)
4285 Report.Error (56, Location,
4286 "Inconsistent accessibility: return type `" +
4287 TypeManager.CSharpName (MemberType) + "' is less " +
4288 "accessible than operator `" + Name + "'");
4290 Report.Error (50, Location,
4291 "Inconsistent accessibility: return type `" +
4292 TypeManager.CSharpName (MemberType) + "' is less " +
4293 "accessible than method `" + Name + "'");
4295 Report.Error (52, Location,
4296 "Inconsistent accessibility: field type `" +
4297 TypeManager.CSharpName (MemberType) + "' is less " +
4298 "accessible than field `" + Name + "'");
4302 if (MemberType.IsPointer && !UnsafeOK (container))
4306 // Check for explicit interface implementation
4308 if (MemberName.Left != null) {
4309 ExplicitInterfaceName = MemberName.Left.GetTypeExpression (Location);
4310 ShortName = MemberName.Name;
4314 if (ExplicitInterfaceName != null) {
4315 InterfaceType = container.ResolveType (
4316 ExplicitInterfaceName, false, Location);
4317 if (InterfaceType == null)
4320 if (InterfaceType.IsClass) {
4321 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4325 // Compute the full name that we need to export.
4326 Name = InterfaceType.FullName + "." + ShortName;
4328 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4331 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4333 IsExplicitImpl = true;
4335 IsExplicitImpl = false;
4342 // Fields and Events both generate FieldBuilders, we use this to share
4343 // their common bits. This is also used to flag usage of the field
4345 abstract public class FieldBase : MemberBase {
4346 public FieldBuilder FieldBuilder;
4347 public Status status;
4350 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4353 // The constructor is only exposed to our children
4355 protected FieldBase (Expression type, int mod, int allowed_mod, MemberName name,
4356 object init, Attributes attrs, Location loc)
4357 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4363 // Whether this field has an initializer.
4365 public bool HasInitializer {
4367 return init != null;
4371 protected readonly Object init;
4373 Expression init_expr;
4374 bool init_expr_initialized = false;
4376 protected override bool CheckGenericOverride (MethodInfo method, string name)
4382 // Resolves and returns the field initializer.
4384 public Expression GetInitializerExpression (EmitContext ec)
4386 if (init_expr_initialized)
4390 if (init is Expression)
4391 e = (Expression) init;
4393 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4395 ec.IsFieldInitializer = true;
4396 e = e.DoResolve (ec);
4397 ec.IsFieldInitializer = false;
4400 init_expr_initialized = true;
4405 public void SetAssigned ()
4407 status |= Status.ASSIGNED;
4412 // The Field class is used to represents class/struct fields during parsing.
4414 public class Field : FieldBase {
4416 // Modifiers allowed in a class declaration
4418 const int AllowedModifiers =
4421 Modifiers.PROTECTED |
4422 Modifiers.INTERNAL |
4425 Modifiers.VOLATILE |
4429 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4430 Attributes attrs, Location loc)
4431 : base (type, mod, AllowedModifiers, new MemberName (name),
4432 expr_or_array_init, attrs, loc)
4436 public override bool Define (TypeContainer container)
4438 Type t = container.ResolveType (Type, false, Location);
4443 CheckBase (container);
4445 if (!container.AsAccessible (t, ModFlags)) {
4446 Report.Error (52, Location,
4447 "Inconsistent accessibility: field type `" +
4448 TypeManager.CSharpName (t) + "' is less " +
4449 "accessible than field `" + Name + "'");
4453 if (t.IsPointer && !UnsafeOK (container))
4456 if (RootContext.WarningLevel > 1){
4457 Type ptype = container.TypeBuilder.BaseType;
4459 // ptype is only null for System.Object while compiling corlib.
4461 TypeContainer.FindMembers (
4462 ptype, MemberTypes.Method,
4463 BindingFlags.Public |
4464 BindingFlags.Static | BindingFlags.Instance,
4465 System.Type.FilterName, Name);
4469 if ((ModFlags & Modifiers.VOLATILE) != 0){
4473 if (TypeManager.IsEnumType (vt))
4474 vt = TypeManager.EnumToUnderlying (t);
4476 if (!((vt == TypeManager.bool_type) ||
4477 (vt == TypeManager.sbyte_type) ||
4478 (vt == TypeManager.byte_type) ||
4479 (vt == TypeManager.short_type) ||
4480 (vt == TypeManager.ushort_type) ||
4481 (vt == TypeManager.int32_type) ||
4482 (vt == TypeManager.uint32_type) ||
4483 (vt == TypeManager.char_type) ||
4484 (vt == TypeManager.float_type))){
4486 677, Location, container.MakeName (Name) +
4487 " A volatile field can not be of type `" +
4488 TypeManager.CSharpName (vt) + "'");
4493 if ((ModFlags & Modifiers.READONLY) != 0){
4496 "A field can not be both volatile and readonly");
4501 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4503 if (container is Struct &&
4504 ((fa & FieldAttributes.Static) == 0) &&
4505 t == container.TypeBuilder &&
4506 !TypeManager.IsBuiltinType (t)){
4507 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4508 "' causes a cycle in the structure layout");
4513 FieldBuilder = container.TypeBuilder.DefineField (
4514 Name, t, Modifiers.FieldAttr (ModFlags));
4516 TypeManager.RegisterFieldBase (FieldBuilder, this);
4518 catch (ArgumentException) {
4519 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4526 public void Emit (TypeContainer tc)
4528 EmitContext ec = new EmitContext (tc, Location, null,
4529 FieldBuilder.FieldType, ModFlags);
4531 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
4536 // `set' and `get' accessors are represented with an Accessor.
4538 public class Accessor {
4540 // Null if the accessor is empty, or a Block if not
4543 public Attributes OptAttributes;
4545 public Accessor (Block b, Attributes attrs)
4548 OptAttributes = attrs;
4553 // Properties and Indexers both generate PropertyBuilders, we use this to share
4554 // their common bits.
4556 abstract public class PropertyBase : MethodCore {
4557 public Accessor Get, Set;
4558 public PropertyBuilder PropertyBuilder;
4559 public MethodBuilder GetBuilder, SetBuilder;
4560 public MethodData GetData, SetData;
4562 protected EmitContext ec;
4564 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
4565 int allowed_mod, bool is_iface, MemberName name,
4566 Parameters parameters, Attributes attrs,
4567 Accessor get_block, Accessor set_block,
4569 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
4570 attrs, parameters, loc)
4576 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
4578 if (!base.DoDefine (decl, container))
4581 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4587 // Checks our base implementation if any
4589 protected override bool CheckBase (TypeContainer container)
4591 base.CheckBase (container);
4593 // Check whether arguments were correct.
4594 if (!DoDefineParameters ())
4601 // Check in our class for dups
4603 ArrayList ar = container.Properties;
4605 int arLen = ar.Count;
4607 for (int i = 0; i < arLen; i++) {
4608 Property m = (Property) ar [i];
4609 if (IsDuplicateImplementation (container, m))
4618 MethodSignature ms, base_ms;
4619 if (this is Indexer) {
4620 string name, base_name;
4622 report_name = "this";
4623 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4624 ms = new MethodSignature (name, null, ParameterTypes);
4625 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4626 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4629 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4633 // Verify if the parent has a type with the same name, and then
4634 // check whether we have to create a new slot for it or not.
4636 Type ptype = container.TypeBuilder.BaseType;
4638 // ptype is only null for System.Object while compiling corlib.
4639 if (ptype == null) {
4640 if ((ModFlags & Modifiers.NEW) != 0)
4641 WarningNotHiding (container);
4646 PropertyInfo parent_property = null;
4649 // Explicit implementations do not have `parent' methods, however,
4650 // the member cache stores them there. Without this check, we get
4651 // an incorrect warning in corlib.
4653 if (! IsExplicitImpl) {
4654 parent_property = (PropertyInfo) ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
4655 container.TypeBuilder, Name, ParameterTypes, true);
4658 if (parent_property != null) {
4659 string name = parent_property.DeclaringType.Name + "." +
4660 parent_property.Name;
4662 MethodInfo get, set, parent_method;
4663 get = parent_property.GetGetMethod (true);
4664 set = parent_property.GetSetMethod (true);
4667 parent_method = get;
4668 else if (set != null)
4669 parent_method = set;
4671 throw new Exception ("Internal error!");
4673 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4676 if ((ModFlags & Modifiers.NEW) == 0) {
4677 Type parent_type = TypeManager.TypeToCoreType (
4678 parent_property.PropertyType);
4680 if (parent_type != MemberType) {
4682 508, Location, container.MakeName (Name) + ": cannot " +
4683 "change return type when overriding " +
4684 "inherited member " + name);
4689 if ((ModFlags & Modifiers.NEW) != 0)
4690 WarningNotHiding (container);
4692 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4693 if (this is Indexer)
4694 Report.Error (115, Location,
4695 container.MakeName (Name) +
4696 " no suitable indexers found to override");
4698 Report.Error (115, Location,
4699 container.MakeName (Name) +
4700 " no suitable properties found to override");
4707 public void Emit (TypeContainer tc)
4710 // The PropertyBuilder can be null for explicit implementations, in that
4711 // case, we do not actually emit the ".property", so there is nowhere to
4712 // put the attribute
4714 if (PropertyBuilder != null)
4715 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4717 if (GetData != null) {
4718 GetData.Emit (tc, Get.Block, Get);
4722 if (SetData != null) {
4723 SetData.Emit (tc, Set.Block, Set);
4729 public class Property : PropertyBase, IIteratorContainer {
4730 const int AllowedModifiers =
4733 Modifiers.PROTECTED |
4734 Modifiers.INTERNAL |
4738 Modifiers.OVERRIDE |
4739 Modifiers.ABSTRACT |
4742 Modifiers.METHOD_YIELDS |
4745 const int AllowedInterfaceModifiers =
4748 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
4749 MemberName name, Attributes attrs, Accessor get_block,
4750 Accessor set_block, Location loc)
4751 : base (ds, type, mod_flags,
4752 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4753 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
4754 get_block, set_block, loc)
4758 public override bool Define (TypeContainer container)
4760 if (!DoDefine (container, container))
4763 if (!CheckBase (container))
4766 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4769 Type [] parameters = TypeManager.NoTypes;
4771 InternalParameters ip = new InternalParameters (
4772 container, Parameters.EmptyReadOnlyParameters);
4774 GetData = new MethodData (container, this, "get", MemberType,
4775 parameters, ip, CallingConventions.Standard,
4776 Get.OptAttributes, ModFlags, flags, false);
4779 // Setup iterator if we are one
4781 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4782 IteratorHandler ih = new IteratorHandler (
4783 "get", container, MemberType,
4784 parameters, ip, ModFlags, Location);
4786 Block new_block = ih.Setup (block);
4787 if (new_block == null)
4792 if (!GetData.Define (container))
4795 GetBuilder = GetData.MethodBuilder;
4799 Type [] parameters = new Type [1];
4800 parameters [0] = MemberType;
4802 Parameter [] parms = new Parameter [1];
4803 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4804 InternalParameters ip = new InternalParameters (
4805 container, new Parameters (parms, null, Location));
4807 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4808 parameters, ip, CallingConventions.Standard,
4809 Set.OptAttributes, ModFlags, flags, false);
4811 if (!SetData.Define (container))
4814 SetBuilder = SetData.MethodBuilder;
4815 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4818 // FIXME - PropertyAttributes.HasDefault ?
4820 PropertyAttributes prop_attr = PropertyAttributes.None;
4822 prop_attr |= PropertyAttributes.RTSpecialName |
4823 PropertyAttributes.SpecialName;
4825 if (!IsExplicitImpl){
4826 PropertyBuilder = container.TypeBuilder.DefineProperty (
4827 Name, prop_attr, MemberType, null);
4830 PropertyBuilder.SetGetMethod (GetBuilder);
4833 PropertyBuilder.SetSetMethod (SetBuilder);
4836 // HACK for the reasons exposed above
4838 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4841 "Class `" + container.Name +
4842 "' already contains a definition for the property `" +
4850 public void SetYields ()
4852 ModFlags |= Modifiers.METHOD_YIELDS;
4857 /// Gigantic workaround for lameness in SRE follows :
4858 /// This class derives from EventInfo and attempts to basically
4859 /// wrap around the EventBuilder so that FindMembers can quickly
4860 /// return this in it search for members
4862 public class MyEventBuilder : EventInfo {
4865 // We use this to "point" to our Builder which is
4866 // not really a MemberInfo
4868 EventBuilder MyBuilder;
4871 // We "catch" and wrap these methods
4873 MethodInfo raise, remove, add;
4875 EventAttributes attributes;
4876 Type declaring_type, reflected_type, event_type;
4881 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4883 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4885 // And now store the values in our own fields.
4887 declaring_type = type_builder;
4889 reflected_type = type_builder;
4891 attributes = event_attr;
4894 this.event_type = event_type;
4898 // Methods that you have to override. Note that you only need
4899 // to "implement" the variants that take the argument (those are
4900 // the "abstract" methods, the others (GetAddMethod()) are
4903 public override MethodInfo GetAddMethod (bool nonPublic)
4908 public override MethodInfo GetRemoveMethod (bool nonPublic)
4913 public override MethodInfo GetRaiseMethod (bool nonPublic)
4919 // These methods make "MyEventInfo" look like a Builder
4921 public void SetRaiseMethod (MethodBuilder raiseMethod)
4923 raise = raiseMethod;
4924 MyBuilder.SetRaiseMethod (raiseMethod);
4927 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4929 remove = removeMethod;
4930 MyBuilder.SetRemoveOnMethod (removeMethod);
4933 public void SetAddOnMethod (MethodBuilder addMethod)
4936 MyBuilder.SetAddOnMethod (addMethod);
4939 public void SetCustomAttribute (CustomAttributeBuilder cb)
4941 MyBuilder.SetCustomAttribute (cb);
4944 public override object [] GetCustomAttributes (bool inherit)
4946 // FIXME : There's nothing which can be seemingly done here because
4947 // we have no way of getting at the custom attribute objects of the
4952 public override object [] GetCustomAttributes (Type t, bool inherit)
4954 // FIXME : Same here !
4958 public override bool IsDefined (Type t, bool b)
4963 public override EventAttributes Attributes {
4969 public override string Name {
4975 public override Type DeclaringType {
4977 return declaring_type;
4981 public override Type ReflectedType {
4983 return reflected_type;
4987 public Type EventType {
4993 public void SetUsed ()
4995 if (my_event != null)
4996 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5000 public class Event : FieldBase {
5001 const int AllowedModifiers =
5004 Modifiers.PROTECTED |
5005 Modifiers.INTERNAL |
5010 Modifiers.OVERRIDE |
5014 const int AllowedInterfaceModifiers =
5017 public readonly Accessor Add;
5018 public readonly Accessor Remove;
5019 public MyEventBuilder EventBuilder;
5021 public MethodBuilder AddBuilder, RemoveBuilder;
5022 MethodData AddData, RemoveData;
5024 public Event (Expression type, int mod_flags, bool is_iface, MemberName name,
5025 Object init, Attributes attrs, Accessor add, Accessor remove,
5027 : base (type, mod_flags,
5028 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5029 name, init, attrs, loc)
5033 IsInterface = is_iface;
5036 public override bool Define (TypeContainer container)
5038 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
5039 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
5041 if (!DoDefine (container, container))
5044 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5045 Report.Error (74, Location, "'" + container.Name + "." + Name +
5046 "': abstract event can not have an initializer");
5050 if (!TypeManager.IsDelegateType (MemberType)) {
5051 Report.Error (66, Location, "'" + container.Name + "." + Name +
5052 "' : event must be of a delegate type");
5056 Type [] parameter_types = new Type [1];
5057 parameter_types [0] = MemberType;
5059 Parameter [] parms = new Parameter [1];
5060 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5061 InternalParameters ip = new InternalParameters (
5062 container, new Parameters (parms, null, Location));
5064 if (!CheckBase (container))
5068 // Now define the accessors
5070 AddData = new MethodData (container, this, "add", TypeManager.void_type,
5071 parameter_types, ip, CallingConventions.Standard,
5072 (Add != null) ? Add.OptAttributes : null,
5073 ModFlags, flags | m_attr, false);
5075 if (!AddData.Define (container))
5078 AddBuilder = AddData.MethodBuilder;
5079 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5081 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
5082 parameter_types, ip, CallingConventions.Standard,
5083 (Remove != null) ? Remove.OptAttributes : null,
5084 ModFlags, flags | m_attr, false);
5086 if (!RemoveData.Define (container))
5089 RemoveBuilder = RemoveData.MethodBuilder;
5090 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5092 if (!IsExplicitImpl){
5093 EventBuilder = new MyEventBuilder (this,
5094 container.TypeBuilder, Name, e_attr, MemberType);
5096 if (Add == null && Remove == null) {
5097 FieldBuilder = container.TypeBuilder.DefineField (
5099 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5100 TypeManager.RegisterPrivateFieldOfEvent (
5101 (EventInfo) EventBuilder, FieldBuilder);
5102 TypeManager.RegisterFieldBase (FieldBuilder, this);
5105 EventBuilder.SetAddOnMethod (AddBuilder);
5106 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5108 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5109 Report.Error (111, Location,
5110 "Class `" + container.Name +
5111 "' already contains a definition for the event `" +
5120 void EmitDefaultMethod (EmitContext ec, bool is_add)
5122 ILGenerator ig = ec.ig;
5123 MethodInfo method = null;
5126 method = TypeManager.delegate_combine_delegate_delegate;
5128 method = TypeManager.delegate_remove_delegate_delegate;
5130 if ((ModFlags & Modifiers.STATIC) != 0) {
5131 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
5132 ig.Emit (OpCodes.Ldarg_0);
5133 ig.Emit (OpCodes.Call, method);
5134 ig.Emit (OpCodes.Castclass, MemberType);
5135 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
5137 ig.Emit (OpCodes.Ldarg_0);
5138 ig.Emit (OpCodes.Ldarg_0);
5139 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
5140 ig.Emit (OpCodes.Ldarg_1);
5141 ig.Emit (OpCodes.Call, method);
5142 ig.Emit (OpCodes.Castclass, MemberType);
5143 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
5145 ig.Emit (OpCodes.Ret);
5148 public void Emit (TypeContainer tc)
5152 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5153 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
5156 AddData.Emit (tc, Add.Block, Add);
5159 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
5160 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5161 EmitDefaultMethod (ec, true);
5164 if (Remove != null) {
5165 RemoveData.Emit (tc, Remove.Block, Remove);
5166 Remove.Block = null;
5168 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
5169 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
5170 EmitDefaultMethod (ec, false);
5177 // FIXME: This does not handle:
5179 // int INTERFACENAME [ args ]
5184 // int this [ args ]
5186 public class Indexer : PropertyBase {
5188 const int AllowedModifiers =
5191 Modifiers.PROTECTED |
5192 Modifiers.INTERNAL |
5196 Modifiers.OVERRIDE |
5201 const int AllowedInterfaceModifiers =
5204 public string IndexerName;
5205 public string InterfaceIndexerName;
5208 // Are we implementing an interface ?
5210 public Indexer (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5211 MemberName name, Parameters parameters, Attributes attrs,
5212 Accessor get_block, Accessor set_block, Location loc)
5213 : base (ds, type, mod_flags,
5214 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5215 is_iface, name, parameters, attrs, get_block, set_block, loc)
5219 public override bool Define (TypeContainer container)
5221 PropertyAttributes prop_attr =
5222 PropertyAttributes.RTSpecialName |
5223 PropertyAttributes.SpecialName;
5225 if (!DoDefine (container, container))
5228 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
5229 if (IndexerName == null)
5230 IndexerName = "Item";
5231 else if (IsExplicitImpl)
5232 Report.Error (592, Location,
5233 "Attribute 'IndexerName' is not valid on this declaration " +
5234 "type. It is valid on `property' declarations only.");
5236 ShortName = IndexerName;
5237 if (IsExplicitImpl) {
5238 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5239 Name = InterfaceType.FullName + "." + IndexerName;
5241 InterfaceIndexerName = IndexerName;
5245 if (!CheckNameCollision (container))
5248 if (!CheckBase (container))
5251 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5253 InternalParameters ip = new InternalParameters (container, Parameters);
5255 GetData = new MethodData (container, this, "get", MemberType,
5256 ParameterTypes, ip, CallingConventions.Standard,
5257 Get.OptAttributes, ModFlags, flags, false);
5259 if (!GetData.Define (container))
5262 GetBuilder = GetData.MethodBuilder;
5266 int top = ParameterTypes.Length;
5267 Type [] set_pars = new Type [top + 1];
5268 ParameterTypes.CopyTo (set_pars, 0);
5269 set_pars [top] = MemberType;
5271 Parameter [] fixed_parms = Parameters.FixedParameters;
5273 if (fixed_parms == null){
5274 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
5275 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5276 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5278 // Here is the problem: the `value' parameter has
5279 // to come *after* the array parameter in the declaration
5281 // X (object [] x, Type value)
5284 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5285 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
5289 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
5292 fixed_parms.CopyTo (tmp, 0);
5293 tmp [fixed_parms.Length] = new Parameter (
5294 Type, "value", Parameter.Modifier.NONE, null);
5296 Parameters set_formal_params = new Parameters (tmp, null, Location);
5298 InternalParameters ip = new InternalParameters (container, set_formal_params);
5300 SetData = new MethodData (container, this, "set", TypeManager.void_type,
5301 set_pars, ip, CallingConventions.Standard,
5302 Set.OptAttributes, ModFlags, flags, false);
5304 if (!SetData.Define (container))
5307 SetBuilder = SetData.MethodBuilder;
5311 // Now name the parameters
5313 Parameter [] p = Parameters.FixedParameters;
5317 for (i = 0; i < p.Length; ++i) {
5319 GetBuilder.DefineParameter (
5320 i + 1, p [i].Attributes, p [i].Name);
5323 SetBuilder.DefineParameter (
5324 i + 1, p [i].Attributes, p [i].Name);
5328 SetBuilder.DefineParameter (
5329 i + 1, ParameterAttributes.None, "value");
5331 if (i != ParameterTypes.Length) {
5332 Parameter array_param = Parameters.ArrayParameter;
5334 SetBuilder.DefineParameter (
5335 i + 1, array_param.Attributes, array_param.Name);
5340 // Define the PropertyBuilder if one of the following conditions are met:
5341 // a) we're not implementing an interface indexer.
5342 // b) the indexer has a different IndexerName and this is no
5343 // explicit interface implementation.
5345 if (!IsExplicitImpl) {
5346 PropertyBuilder = container.TypeBuilder.DefineProperty (
5347 IndexerName, prop_attr, MemberType, ParameterTypes);
5349 if (GetData != null)
5350 PropertyBuilder.SetGetMethod (GetBuilder);
5352 if (SetData != null)
5353 PropertyBuilder.SetSetMethod (SetBuilder);
5355 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
5362 bool CheckNameCollision (TypeContainer container) {
5363 switch (VerifyName (container)){
5364 case DeclSpace.AdditionResult.NameExists:
5365 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
5368 case DeclSpace.AdditionResult.Success:
5371 throw new NotImplementedException ();
5374 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
5375 if (!AddIndexer (container, container.Name + "." + Name))
5376 return DeclSpace.AdditionResult.NameExists;
5379 if (!AddIndexer (container, container.Name + ".get_" + Name))
5380 return DeclSpace.AdditionResult.NameExists;
5384 if (!AddIndexer (container, container.Name + ".set_" + Name))
5385 return DeclSpace.AdditionResult.NameExists;
5387 return DeclSpace.AdditionResult.Success;
5390 bool AddIndexer (TypeContainer container, string fullname)
5392 object value = container.GetDefinition (fullname);
5394 if (value != null) {
5395 return value.GetType () != GetType () ? false : true;
5398 container.DefineName (fullname, this);
5402 public override string GetSignatureForError () {
5403 return TypeManager.CSharpSignature (PropertyBuilder, true);
5407 public class Operator : MemberBase, IIteratorContainer {
5409 const int AllowedModifiers =
5415 const int RequiredModifiers =
5419 public enum OpType : byte {
5429 // Unary and Binary operators
5452 // Implicit and Explicit
5457 public readonly OpType OperatorType;
5458 public readonly Expression ReturnType;
5459 public readonly Expression FirstArgType, SecondArgType;
5460 public readonly string FirstArgName, SecondArgName;
5462 public MethodBuilder OperatorMethodBuilder;
5464 public string MethodName;
5465 public Method OperatorMethod;
5467 public Operator (OpType type, Expression ret_type, int mod_flags,
5468 Expression arg1type, string arg1name,
5469 Expression arg2type, string arg2name,
5470 Block block, Attributes attrs, Location loc)
5471 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC,
5472 MemberName.Null, attrs, loc)
5474 OperatorType = type;
5475 Name = "op_" + OperatorType;
5476 ReturnType = ret_type;
5477 FirstArgType = arg1type;
5478 FirstArgName = arg1name;
5479 SecondArgType = arg2type;
5480 SecondArgName = arg2name;
5484 string Prototype (TypeContainer container)
5486 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
5487 SecondArgType + ")";
5490 protected override bool CheckGenericOverride (MethodInfo method, string name)
5495 public override bool Define (TypeContainer container)
5498 MethodName = "op_" + OperatorType;
5500 if (SecondArgType != null)
5503 Parameter [] param_list = new Parameter [length];
5505 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
5508 "User defined operators `" +
5509 Prototype (container) +
5510 "' must be declared static and public");
5514 param_list[0] = new Parameter (FirstArgType, FirstArgName,
5515 Parameter.Modifier.NONE, null);
5516 if (SecondArgType != null)
5517 param_list[1] = new Parameter (SecondArgType, SecondArgName,
5518 Parameter.Modifier.NONE, null);
5520 OperatorMethod = new Method (
5521 container, ReturnType, ModFlags, false,
5522 new MemberName (MethodName),
5523 new Parameters (param_list, null, Location),
5524 OptAttributes, Location);
5526 OperatorMethod.Block = Block;
5527 OperatorMethod.IsOperator = true;
5528 OperatorMethod.Define (container);
5530 if (OperatorMethod.MethodBuilder == null)
5533 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
5535 Type [] param_types = OperatorMethod.ParameterTypes;
5536 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
5537 Type return_type = OperatorMethod.GetReturnType ();
5538 Type first_arg_type = param_types [0];
5540 // Rules for conversion operators
5542 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
5543 if (first_arg_type == return_type && first_arg_type == declaring_type){
5546 "User-defined conversion cannot take an object of the " +
5547 "enclosing type and convert to an object of the enclosing" +
5552 if (first_arg_type != declaring_type && return_type != declaring_type){
5555 "User-defined conversion must convert to or from the " +
5560 if (first_arg_type == TypeManager.object_type ||
5561 return_type == TypeManager.object_type){
5564 "User-defined conversion cannot convert to or from " +
5569 if (first_arg_type.IsInterface || return_type.IsInterface){
5572 "User-defined conversion cannot convert to or from an " +
5577 if (first_arg_type.IsSubclassOf (return_type) ||
5578 return_type.IsSubclassOf (first_arg_type)){
5581 "User-defined conversion cannot convert between types " +
5582 "that derive from each other");
5585 } else if (SecondArgType == null) {
5586 // Checks for Unary operators
5588 if (first_arg_type != declaring_type){
5591 "The parameter of a unary operator must be the " +
5596 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
5597 if (return_type != declaring_type){
5600 "The parameter and return type for ++ and -- " +
5601 "must be the containing type");
5607 if (OperatorType == OpType.True || OperatorType == OpType.False) {
5608 if (return_type != TypeManager.bool_type){
5611 "The return type of operator True or False " +
5618 // Checks for Binary operators
5620 if (first_arg_type != declaring_type &&
5621 param_types [1] != declaring_type){
5624 "One of the parameters of a binary operator must " +
5625 "be the containing type");
5633 public void Emit (TypeContainer container)
5636 // abstract or extern methods have no bodies
5638 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
5641 OperatorMethod.Emit (container);
5645 public static string GetName (OpType ot)
5648 case OpType.LogicalNot:
5650 case OpType.OnesComplement:
5652 case OpType.Increment:
5654 case OpType.Decrement:
5660 case OpType.Addition:
5662 case OpType.Subtraction:
5664 case OpType.UnaryPlus:
5666 case OpType.UnaryNegation:
5668 case OpType.Multiply:
5670 case OpType.Division:
5672 case OpType.Modulus:
5674 case OpType.BitwiseAnd:
5676 case OpType.BitwiseOr:
5678 case OpType.ExclusiveOr:
5680 case OpType.LeftShift:
5682 case OpType.RightShift:
5684 case OpType.Equality:
5686 case OpType.Inequality:
5688 case OpType.GreaterThan:
5690 case OpType.LessThan:
5692 case OpType.GreaterThanOrEqual:
5694 case OpType.LessThanOrEqual:
5696 case OpType.Implicit:
5698 case OpType.Explicit:
5704 public override string ToString ()
5706 Type return_type = OperatorMethod.GetReturnType();
5707 Type [] param_types = OperatorMethod.ParameterTypes;
5709 if (SecondArgType == null)
5710 return String.Format (
5711 "{0} operator {1}({2})",
5712 TypeManager.CSharpName (return_type),
5713 GetName (OperatorType),
5716 return String.Format (
5717 "{0} operator {1}({2}, {3})",
5718 TypeManager.CSharpName (return_type),
5719 GetName (OperatorType),
5720 param_types [0], param_types [1]);
5723 public void SetYields ()
5725 ModFlags |= Modifiers.METHOD_YIELDS;
5730 // This is used to compare method signatures
5732 struct MethodSignature {
5734 public Type RetType;
5735 public Type [] Parameters;
5738 /// This delegate is used to extract methods which have the
5739 /// same signature as the argument
5741 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
5743 public MethodSignature (string name, Type ret_type, Type [] parameters)
5748 if (parameters == null)
5749 Parameters = TypeManager.NoTypes;
5751 Parameters = parameters;
5754 public override string ToString ()
5757 if (Parameters.Length != 0){
5758 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5759 for (int i = 0; i < Parameters.Length; i++){
5760 sb.Append (Parameters [i]);
5761 if (i+1 < Parameters.Length)
5764 pars = sb.ToString ();
5767 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5770 public override int GetHashCode ()
5772 return Name.GetHashCode ();
5775 public override bool Equals (Object o)
5777 MethodSignature other = (MethodSignature) o;
5779 if (other.Name != Name)
5782 if (other.RetType != RetType)
5785 if (Parameters == null){
5786 if (other.Parameters == null)
5791 if (other.Parameters == null)
5794 int c = Parameters.Length;
5795 if (other.Parameters.Length != c)
5798 for (int i = 0; i < c; i++)
5799 if (other.Parameters [i] != Parameters [i])
5805 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5807 MethodSignature sig = (MethodSignature) filter_criteria;
5809 if (m.Name != sig.Name)
5813 MethodInfo mi = m as MethodInfo;
5814 PropertyInfo pi = m as PropertyInfo;
5817 ReturnType = mi.ReturnType;
5818 else if (pi != null)
5819 ReturnType = pi.PropertyType;
5824 // we use sig.RetType == null to mean `do not check the
5825 // method return value.
5827 if (sig.RetType != null)
5828 if (ReturnType != sig.RetType)
5833 args = TypeManager.GetArgumentTypes (mi);
5835 args = TypeManager.GetArgumentTypes (pi);
5836 Type [] sigp = sig.Parameters;
5838 if (args.Length != sigp.Length)
5841 for (int i = args.Length; i > 0; ){
5843 if (args [i] != sigp [i])