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;
37 using System.Runtime.InteropServices;
39 namespace Mono.CSharp {
42 /// This is the base class for structs and classes.
44 public class TypeContainer : DeclSpace, IMemberContainer {
45 // Holds a list of classes and structures
48 // Holds the list of properties
51 // Holds the list of enumerations
54 // Holds the list of delegates
57 // Holds the list of constructors
58 ArrayList instance_constructors;
60 // Holds the list of fields
63 // Holds a list of fields that have initializers
64 ArrayList initialized_fields;
66 // Holds a list of static fields that have initializers
67 ArrayList initialized_static_fields;
69 // Holds the list of constants
75 // Holds order in which interfaces must be closed
76 ArrayList interface_order;
87 // Holds the operators
90 // The emit context for toplevel objects.
94 // Pointers to the default constructor and the default static constructor
96 Constructor default_constructor;
97 Constructor default_static_constructor;
100 // Whether we have seen a static constructor for this class or not
102 public bool UserDefinedStaticConstructor = false;
105 // Whether we have at least one non-static field
107 bool have_nonstatic_fields = false;
110 // This one is computed after we can distinguish interfaces
111 // from classes from the arraylist `type_bases'
113 string base_class_name;
115 ArrayList type_bases;
117 bool members_defined;
118 bool members_defined_ok;
120 // The interfaces we implement.
122 Type[] base_inteface_types;
124 // The parent member container and our member cache
125 IMemberContainer parent_container;
126 MemberCache member_cache;
129 // The indexer name for this class
131 public string IndexerName;
135 public TypeContainer ():
136 this (null, null, MemberName.Null, null, new Location (-1)) {
139 public TypeContainer (NamespaceEntry ns, TypeContainer parent,
140 MemberName name, Attributes attrs, Location l)
141 : base (ns, parent, name, attrs, l)
143 types = new ArrayList ();
145 base_class_name = null;
148 public AdditionResult AddConstant (Const constant)
151 string basename = constant.Name;
152 string fullname = Name + "." + basename;
154 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
157 if (constants == null)
158 constants = new ArrayList ();
160 constants.Add (constant);
161 DefineName (fullname, constant);
163 return AdditionResult.Success;
166 public AdditionResult AddEnum (Mono.CSharp.Enum e)
170 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
174 enums = new ArrayList ();
177 DefineName (e.Name, e);
179 return AdditionResult.Success;
182 public AdditionResult AddClass (Class c)
185 string name = c.Basename;
187 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
190 DefineName (c.Name, c);
193 return AdditionResult.Success;
196 public AdditionResult AddStruct (Struct s)
199 string name = s.Basename;
201 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
204 DefineName (s.Name, s);
207 return AdditionResult.Success;
210 public AdditionResult AddDelegate (Delegate d)
213 string name = d.Basename;
215 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
218 if (delegates == null)
219 delegates = new ArrayList ();
221 DefineName (d.Name, d);
224 return AdditionResult.Success;
227 public AdditionResult AddMethod (Method method)
229 string basename = method.Name;
230 string fullname = Name + "." + basename;
232 Object value = defined_names [fullname];
234 if (value != null && (!(value is Method)))
235 return AdditionResult.NameExists;
237 if (basename == Basename)
238 return AdditionResult.EnclosingClash;
241 methods = new ArrayList ();
243 if (method.Name.IndexOf ('.') != -1)
244 methods.Insert (0, method);
246 methods.Add (method);
249 DefineName (fullname, method);
251 return AdditionResult.Success;
254 public AdditionResult AddConstructor (Constructor c)
256 if (c.Name != Basename)
257 return AdditionResult.NotAConstructor;
259 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
262 UserDefinedStaticConstructor = true;
263 if (default_static_constructor != null)
264 return AdditionResult.MethodExists;
266 default_static_constructor = c;
269 if (default_constructor != null)
270 return AdditionResult.MethodExists;
271 default_constructor = c;
274 if (instance_constructors == null)
275 instance_constructors = new ArrayList ();
277 instance_constructors.Add (c);
280 return AdditionResult.Success;
283 public AdditionResult AddInterface (Interface iface)
286 string name = iface.Basename;
288 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
291 if (interfaces == null)
292 interfaces = new ArrayList ();
293 interfaces.Add (iface);
294 DefineName (iface.Name, iface);
296 return AdditionResult.Success;
299 public AdditionResult AddField (Field field)
302 string basename = field.Name;
303 string fullname = Name + "." + basename;
305 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
309 fields = new ArrayList ();
313 if (field.HasInitializer){
314 if ((field.ModFlags & Modifiers.STATIC) != 0){
315 if (initialized_static_fields == null)
316 initialized_static_fields = new ArrayList ();
318 initialized_static_fields.Add (field);
321 if (initialized_fields == null)
322 initialized_fields = new ArrayList ();
324 initialized_fields.Add (field);
328 if ((field.ModFlags & Modifiers.STATIC) == 0)
329 have_nonstatic_fields = true;
331 DefineName (fullname, field);
332 return AdditionResult.Success;
335 public AdditionResult AddProperty (Property prop)
339 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
342 if (prop.Get != null) {
343 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
347 if (prop.Set != null) {
348 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
352 if (properties == null)
353 properties = new ArrayList ();
355 if (prop.Name.IndexOf ('.') != -1)
356 properties.Insert (0, prop);
358 properties.Add (prop);
360 return AdditionResult.Success;
363 AdditionResult AddProperty (Property prop, string basename)
366 string fullname = Name + "." + basename;
368 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
371 DefineName (fullname, prop);
373 return AdditionResult.Success;
376 public AdditionResult AddEvent (Event e)
379 string basename = e.Name;
380 string fullname = Name + "." + basename;
382 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
386 events = new ArrayList ();
389 DefineName (fullname, e);
391 return AdditionResult.Success;
394 public void AddIndexer (Indexer i)
396 if (indexers == null)
397 indexers = new ArrayList ();
399 if (i.MemberName.TypeName != null)
400 indexers.Insert (0, i);
405 public AdditionResult AddOperator (Operator op)
407 if (operators == null)
408 operators = new ArrayList ();
412 string basename = op.Name;
413 string fullname = Name + "." + basename;
414 if (!defined_names.Contains (fullname))
416 DefineName (fullname, op);
418 return AdditionResult.Success;
421 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
423 if (a.Type == TypeManager.default_member_type) {
424 if (Indexers != null) {
425 Report.Error (646, a.Location,
426 "Cannot specify the DefaultMember attribute on" +
427 " a type containing an indexer");
432 base.ApplyAttributeBuilder (a, cb);
435 public override AttributeTargets AttributeTargets {
437 throw new NotSupportedException ();
441 public void RegisterOrder (Interface iface)
443 if (interface_order == null)
444 interface_order = new ArrayList ();
446 interface_order.Add (iface);
449 public ArrayList Types {
455 public ArrayList Methods {
461 public ArrayList Constants {
467 public ArrayList Interfaces {
475 return base_class_name;
479 public ArrayList Bases {
489 public ArrayList Fields {
499 public ArrayList InstanceConstructors {
501 return instance_constructors;
505 public ArrayList Properties {
511 public ArrayList Events {
517 public ArrayList Enums {
523 public ArrayList Indexers {
529 public ArrayList Operators {
535 public ArrayList Delegates {
541 public virtual TypeAttributes TypeAttr {
543 return Modifiers.TypeAttr (ModFlags, this);
548 // Emits the instance field initializers
550 public bool EmitFieldInitializers (EmitContext ec)
553 Expression instance_expr;
556 fields = initialized_static_fields;
557 instance_expr = null;
559 fields = initialized_fields;
560 instance_expr = new This (Location.Null).Resolve (ec);
566 foreach (Field f in fields){
567 Expression e = f.GetInitializerExpression (ec);
571 Location l = f.Location;
572 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
573 fe.InstanceExpression = instance_expr;
574 ExpressionStatement a = new Assign (fe, e, l);
576 a = a.ResolveStatement (ec);
580 a.EmitStatement (ec);
587 // Defines the default constructors
589 void DefineDefaultConstructor (bool is_static)
593 // The default constructor is public
594 // If the class is abstract, the default constructor is protected
595 // The default static constructor is private
597 int mods = Modifiers.PUBLIC;
599 mods = Modifiers.STATIC | Modifiers.PRIVATE;
600 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
601 mods = Modifiers.PROTECTED;
603 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
604 new ConstructorBaseInitializer (
605 null, Parameters.EmptyReadOnlyParameters,
611 c.Block = new ToplevelBlock (null, Location);
615 public void ReportStructInitializedInstanceError ()
617 string n = TypeBuilder.FullName;
619 foreach (Field f in initialized_fields){
622 "`" + n + "." + f.Name + "': can not have " +
623 "instance field initializers in structs");
628 /// The pending methods that need to be implemented (interfaces or abstract methods)
630 public PendingImplementation Pending;
633 /// This function computes the Base class and also the
634 /// list of interfaces that the class or struct @c implements.
636 /// The return value is an array (might be null) of
637 /// interfaces implemented (as Types).
639 /// The @parent argument is set to the parent object or null
640 /// if this is `System.Object'.
642 TypeExpr [] GetClassBases (bool is_class, bool is_iface,
643 out TypeExpr parent, out bool error)
645 ArrayList bases = Bases;
651 if (is_class || is_iface)
654 parent = TypeManager.system_valuetype_expr;
658 if (RootContext.StdLib)
659 parent = TypeManager.system_object_expr;
660 else if (Name != "System.Object")
661 parent = TypeManager.system_object_expr;
664 // If we are compiling our runtime,
665 // and we are defining ValueType, then our
666 // parent is `System.Object'.
668 if (!RootContext.StdLib && Name == "System.ValueType")
669 parent = TypeManager.system_object_expr;
676 // Bases should be null if there are no bases at all
681 TypeExpr name = ResolveTypeExpr ((Expression) bases [0], false, Location);
688 if (name is TypeParameterExpr){
691 "Type parameter `{0}' can not be used as a " +
692 "base class or interface", name.Name);
697 if (IsGeneric && name.IsAttribute){
700 "A generic type cannot derive from `{0}' " +
701 "because it is an attribute class", name.Name);
710 parent = TypeManager.system_object_expr;
716 if (name.IsValueType)
717 detail = " (a class can not inherit from a struct/enum)";
719 Report.Error (509, "class `"+ Name +
720 "': Cannot inherit from sealed class `"+
721 name.Name + "'" + detail);
726 if (!parent.CanInheritFrom ()){
727 Report.Error (644, Location,
728 "`{0}' cannot inherit from special class `{1}'",
734 if (!parent.AsAccessible (this, ModFlags))
735 Report.Error (60, Location,
736 "Inconsistent accessibility: base class `" +
737 name.Name + "' is less accessible than class `" +
745 base_class_name = parent.Name;
747 TypeExpr [] ifaces = new TypeExpr [count-start];
749 for (i = start, j = 0; i < count; i++, j++){
750 Expression name = (Expression) bases [i];
751 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
753 if (resolved == null)
756 bases [i] = resolved;
758 if (is_class == false && !resolved.IsInterface){
759 Report.Error (527, "In Struct `" + Name + "', type `"+
760 name +"' is not an interface");
765 if (resolved.IsClass) {
767 Report.Error (527, "In Class `" + Name + "', type `"+
768 name+"' is not an interface");
774 for (int x = 0; x < j; x++) {
775 if (resolved.Equals (ifaces [x])) {
776 Report.Error (528, "`" + name + "' is already listed in interface list");
783 !resolved.AsAccessible (Parent, ModFlags))
784 Report.Error (61, Location,
785 "Inconsistent accessibility: base interface `" +
786 name + "' is less accessible than interface `" +
789 ifaces [j] = resolved;
792 return TypeManager.ExpandInterfaces (ifaces);
795 bool CheckGenericInterfaces (Type[] ifaces)
797 ArrayList already_checked = new ArrayList ();
799 for (int i = 0; i < ifaces.Length; i++) {
800 Type iface = ifaces [i];
801 foreach (Type t in already_checked) {
805 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
810 "`{0}' cannot implement both `{1}' and `{2}' " +
811 "because they may unify for some type " +
812 "parameter substitutions",
813 TypeManager.GetFullName (TypeBuilder),
818 already_checked.Add (iface);
827 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
829 public override TypeBuilder DefineType ()
832 bool is_class, is_iface;
834 if (TypeBuilder != null)
841 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
848 if (this is Interface) {
859 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
861 ifaces = GetClassBases (is_class, is_iface, out parent, out error);
867 foreach (TypeParameter type_param in TypeParameters)
868 if (!type_param.Resolve (this)) {
874 if (!is_class && TypeManager.value_type == null)
875 throw new Exception ();
877 TypeAttributes type_attributes = TypeAttr;
880 ConstructedType constructed = parent as ConstructedType;
881 if ((constructed == null) && (parent != null))
882 ptype = parent.ResolveType (ec);
887 if (TypeManager.NamespaceClash (Name, Location)) {
892 ModuleBuilder builder = CodeGen.Module.Builder;
893 TypeBuilder = builder.DefineType (
894 Name, type_attributes, ptype, null);
896 TypeBuilder builder = Parent.DefineType ();
897 if (builder == null) {
902 TypeBuilder = builder.DefineNestedType (
903 MemberName.Basename, type_attributes, ptype, null);
906 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
909 CurrentType = new ConstructedType (
910 Name, TypeParameters, Location);
912 string[] param_names = new string [TypeParameters.Length];
913 for (int i = 0; i < TypeParameters.Length; i++)
914 param_names [i] = TypeParameters [i].Name;
916 GenericTypeParameterBuilder[] gen_params;
918 gen_params = TypeBuilder.DefineGenericParameters (param_names);
920 for (int i = 0; i < gen_params.Length; i++)
921 TypeParameters [i].Define (gen_params [i]);
924 if (constructed != null) {
925 ptype = constructed.ResolveType (ec);
931 TypeBuilder.SetParent (ptype);
935 foreach (TypeParameter type_param in TypeParameters)
936 if (!type_param.DefineType (ec))
944 // Structs with no fields need to have at least one byte.
945 // The right thing would be to set the PackingSize in a DefineType
946 // but there are no functions that allow interfaces *and* the size to
950 if (!is_class && !is_iface && !have_nonstatic_fields){
951 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
952 FieldAttributes.Private);
955 // add interfaces that were not added at type creation
956 if (ifaces != null) {
957 Type[] itypes = new Type[ifaces.Length];
958 for (int i = 0; i < ifaces.Length; ++i) {
959 Type itype = ifaces [i].ResolveType (ec);
960 TypeBuilder.AddInterfaceImplementation (itype);
967 if (!CheckGenericInterfaces (itypes)) {
974 // Finish the setup for the EmitContext
976 ec.ContainerType = TypeBuilder;
978 if ((parent != null) && parent.IsAttribute) {
979 RootContext.RegisterAttribute (this);
981 RootContext.RegisterOrder (this);
983 if (Interfaces != null) {
984 foreach (Interface iface in Interfaces)
985 if (iface.DefineType () == null) {
992 foreach (TypeContainer tc in Types)
993 if (tc.DefineType () == null) {
999 if (Delegates != null) {
1000 foreach (Delegate d in Delegates)
1001 if (d.DefineType () == null) {
1007 if (Enums != null) {
1008 foreach (Enum en in Enums)
1009 if (en.DefineType () == null) {
1021 /// Defines the MemberCore objects that are in the `list' Arraylist
1023 /// The `defined_names' array contains a list of members defined in
1026 static ArrayList remove_list = new ArrayList ();
1027 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1031 remove_list.Clear ();
1033 foreach (MemberCore mc in list){
1035 if (defined_names != null)
1036 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1041 if (RootContext.WarningLevel >= 4){
1042 if ((mc.ModFlags & Modifiers.NEW) != 0)
1043 Warning_KeywordNewNotRequired (mc.Location, mc);
1045 } else if (mc is MethodCore)
1046 ((MethodCore) mc).OverridesSomething = true;
1048 if (!mc.Define (this)){
1049 remove_list.Add (mc);
1056 MemberInfo match = defined_names [idx];
1058 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1062 // If we are both methods, let the method resolution emit warnings
1064 if (match is MethodBase && mc is MethodCore)
1067 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1069 if (!(match is EventInfo)) {
1070 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1074 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1078 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1082 foreach (object o in remove_list)
1085 remove_list.Clear ();
1089 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1090 // class is consistent. Either it is `Item' or it is the name defined by all the
1091 // indexers with the `IndexerName' attribute.
1093 // Turns out that the IndexerNameAttribute is applied to each indexer,
1094 // but it is never emitted, instead a DefaultMember attribute is attached
1097 void DefineIndexers ()
1099 string class_indexer_name = null;
1102 // If there's both an explicit and an implicit interface implementation, the
1103 // explicit one actually implements the interface while the other one is just
1104 // a normal indexer. See bug #37714.
1107 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1108 bool seen_normal_indexers = false;
1109 foreach (Indexer i in Indexers) {
1114 name = i.IndexerName;
1116 if (i.InterfaceType != null) {
1117 if (seen_normal_indexers)
1118 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1122 seen_normal_indexers = true;
1124 if (class_indexer_name == null)
1125 class_indexer_name = name;
1126 else if (name != class_indexer_name)
1127 Report.Error (668, "Two indexers have different names, " +
1128 " you should use the same name for all your indexers");
1131 if (seen_normal_indexers && class_indexer_name == null)
1132 class_indexer_name = "Item";
1133 IndexerName = class_indexer_name;
1136 static void Error_KeywordNotAllowed (Location loc)
1138 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1142 /// Populates our TypeBuilder with fields and methods
1144 public override bool DefineMembers (TypeContainer container)
1146 if (members_defined)
1147 return members_defined_ok;
1149 members_defined_ok = DoDefineMembers ();
1150 members_defined = true;
1152 return members_defined_ok;
1155 bool DoDefineMembers ()
1157 MemberInfo [] defined_names = null;
1160 // We need to be able to use the member cache while we are checking/defining
1163 if (TypeBuilder.BaseType != null)
1164 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1167 if (interface_order != null){
1168 foreach (Interface iface in interface_order)
1169 if ((iface.ModFlags & Modifiers.NEW) == 0)
1170 iface.DefineMembers (this);
1172 Error_KeywordNotAllowed (iface.Location);
1175 if (RootContext.WarningLevel > 1){
1179 // This code throws an exception in the comparer
1180 // I guess the string is not an object?
1182 ptype = TypeBuilder.BaseType;
1184 defined_names = (MemberInfo []) FindMembers (
1185 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1186 BindingFlags.Public | BindingFlags.Instance |
1187 BindingFlags.Static, null, null);
1189 Array.Sort (defined_names, mif_compare);
1193 Class pclass = Parent as Class;
1194 if (pclass != null) {
1195 string pname = null;
1196 TypeExpr ptype = null;
1197 Type t = pclass.TypeBuilder.BaseType;
1198 while ((t != null) && (ptype == null)) {
1199 pname = t.FullName + "." + Basename;
1200 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1204 if ((ModFlags & Modifiers.NEW) != 0) {
1206 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1207 "inherited member. The keyword new is not required.");
1208 } else if (ptype != null) {
1209 Report.Warning (108, Location, "The keyword new is required on `" +
1210 Name + "' because it hides inherited member '" +
1213 } else if ((ModFlags & Modifiers.NEW) != 0)
1214 Error_KeywordNotAllowed (Location);
1216 if (constants != null)
1217 DefineMembers (constants, defined_names);
1220 DefineMembers (fields, defined_names);
1223 if (instance_constructors == null){
1224 if (default_constructor == null)
1225 DefineDefaultConstructor (false);
1228 if (initialized_static_fields != null &&
1229 default_static_constructor == null)
1230 DefineDefaultConstructor (true);
1233 if (this is Struct){
1235 // Structs can not have initialized instance
1238 if (initialized_static_fields != null &&
1239 default_static_constructor == null)
1240 DefineDefaultConstructor (true);
1242 if (initialized_fields != null)
1243 ReportStructInitializedInstanceError ();
1246 if (!(this is Interface))
1247 Pending = PendingImplementation.GetPendingImplementations (this);
1250 // Constructors are not in the defined_names array
1252 if (instance_constructors != null)
1253 DefineMembers (instance_constructors, null);
1255 if (default_static_constructor != null)
1256 default_static_constructor.Define (this);
1258 if (methods != null)
1259 DefineMembers (methods, defined_names);
1261 if (properties != null)
1262 DefineMembers (properties, defined_names);
1265 DefineMembers (events, defined_names);
1267 if (indexers != null)
1270 if (operators != null){
1271 DefineMembers (operators, null);
1273 CheckPairedOperators ();
1277 DefineMembers (enums, defined_names);
1279 if (delegates != null)
1280 DefineMembers (delegates, defined_names);
1282 if (CurrentType != null) {
1283 GenericType = CurrentType.ResolveType (ec);
1285 ec.ContainerType = GenericType;
1290 member_cache = new MemberCache (this);
1297 public override bool Define (TypeContainer container)
1299 if (interface_order != null){
1300 foreach (Interface iface in interface_order)
1301 if ((iface.ModFlags & Modifiers.NEW) == 0)
1302 iface.Define (this);
1309 /// This function is based by a delegate to the FindMembers routine
1311 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1317 /// This filter is used by FindMembers, and we just keep
1318 /// a global for the filter to `AlwaysAccept'
1320 static MemberFilter accepting_filter;
1324 /// A member comparission method based on name only
1326 static IComparer mif_compare;
1328 static TypeContainer ()
1330 accepting_filter = new MemberFilter (AlwaysAccept);
1331 mif_compare = new MemberInfoCompare ();
1334 public MethodInfo[] GetMethods ()
1336 ArrayList members = new ArrayList ();
1338 DefineMembers (null);
1340 if (methods != null) {
1341 int len = methods.Count;
1342 for (int i = 0; i < len; i++) {
1343 Method m = (Method) methods [i];
1345 members.Add (m.MethodBuilder);
1349 if (operators != null) {
1350 int len = operators.Count;
1351 for (int i = 0; i < len; i++) {
1352 Operator o = (Operator) operators [i];
1354 members.Add (o.OperatorMethodBuilder);
1358 if (properties != null) {
1359 int len = properties.Count;
1360 for (int i = 0; i < len; i++) {
1361 Property p = (Property) properties [i];
1363 if (p.GetBuilder != null)
1364 members.Add (p.GetBuilder);
1365 if (p.SetBuilder != null)
1366 members.Add (p.SetBuilder);
1370 if (indexers != null) {
1371 int len = indexers.Count;
1372 for (int i = 0; i < len; i++) {
1373 Indexer ix = (Indexer) indexers [i];
1375 if (ix.GetBuilder != null)
1376 members.Add (ix.GetBuilder);
1377 if (ix.SetBuilder != null)
1378 members.Add (ix.SetBuilder);
1382 if (events != null) {
1383 int len = events.Count;
1384 for (int i = 0; i < len; i++) {
1385 Event e = (Event) events [i];
1387 if (e.AddBuilder != null)
1388 members.Add (e.AddBuilder);
1389 if (e.RemoveBuilder != null)
1390 members.Add (e.RemoveBuilder);
1394 MethodInfo[] retMethods = new MethodInfo [members.Count];
1395 members.CopyTo (retMethods, 0);
1400 /// This method returns the members of this type just like Type.FindMembers would
1401 /// Only, we need to use this for types which are _being_ defined because MS'
1402 /// implementation can't take care of that.
1405 // FIXME: return an empty static array instead of null, that cleans up
1406 // some code and is consistent with some coding conventions I just found
1410 // Notice that in various cases we check if our field is non-null,
1411 // something that would normally mean that there was a bug elsewhere.
1413 // The problem happens while we are defining p-invoke methods, as those
1414 // will trigger a FindMembers, but this happens before things are defined
1416 // Since the whole process is a no-op, it is fine to check for null here.
1418 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1419 MemberFilter filter, object criteria)
1421 ArrayList members = null;
1424 if ((bf & BindingFlags.Public) != 0)
1425 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1427 if ((bf & BindingFlags.NonPublic) != 0)
1428 modflags |= Modifiers.PRIVATE;
1430 int static_mask = 0, static_flags = 0;
1431 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1432 case BindingFlags.Static:
1433 static_mask = static_flags = Modifiers.STATIC;
1436 case BindingFlags.Instance:
1437 static_mask = Modifiers.STATIC;
1442 static_mask = static_flags = 0;
1446 Timer.StartTimer (TimerType.TcFindMembers);
1449 filter = accepting_filter;
1451 if ((mt & MemberTypes.Field) != 0) {
1452 if (fields != null) {
1453 int len = fields.Count;
1454 for (int i = 0; i < len; i++) {
1455 Field f = (Field) fields [i];
1457 if ((f.ModFlags & modflags) == 0)
1459 if ((f.ModFlags & static_mask) != static_flags)
1462 FieldBuilder fb = f.FieldBuilder;
1463 if (fb != null && filter (fb, criteria) == true) {
1464 if (members == null)
1465 members = new ArrayList ();
1472 if (constants != null) {
1473 int len = constants.Count;
1474 for (int i = 0; i < len; i++) {
1475 Const con = (Const) constants [i];
1477 if ((con.ModFlags & modflags) == 0)
1479 if ((con.ModFlags & static_mask) != static_flags)
1482 FieldBuilder fb = con.FieldBuilder;
1483 if (fb != null && filter (fb, criteria) == true) {
1484 if (members == null)
1485 members = new ArrayList ();
1493 if ((mt & MemberTypes.Method) != 0) {
1494 if (methods != null) {
1495 int len = methods.Count;
1496 for (int i = 0; i < len; i++) {
1497 Method m = (Method) methods [i];
1499 if ((m.ModFlags & modflags) == 0)
1501 if ((m.ModFlags & static_mask) != static_flags)
1504 MethodBuilder mb = m.MethodBuilder;
1506 if (mb != null && filter (mb, criteria) == true) {
1507 if (members == null)
1508 members = new ArrayList ();
1515 if (operators != null) {
1516 int len = operators.Count;
1517 for (int i = 0; i < len; i++) {
1518 Operator o = (Operator) operators [i];
1520 if ((o.ModFlags & modflags) == 0)
1522 if ((o.ModFlags & static_mask) != static_flags)
1525 MethodBuilder ob = o.OperatorMethodBuilder;
1526 if (ob != null && filter (ob, criteria) == true) {
1527 if (members == null)
1528 members = new ArrayList ();
1535 if (properties != null) {
1536 int len = properties.Count;
1537 for (int i = 0; i < len; i++) {
1538 Property p = (Property) properties [i];
1540 if ((p.ModFlags & modflags) == 0)
1542 if ((p.ModFlags & static_mask) != static_flags)
1548 if (b != null && filter (b, criteria) == true) {
1549 if (members == null)
1550 members = new ArrayList ();
1556 if (b != null && filter (b, criteria) == true) {
1557 if (members == null)
1558 members = new ArrayList ();
1565 if (indexers != null) {
1566 int len = indexers.Count;
1567 for (int i = 0; i < len; i++) {
1568 Indexer ix = (Indexer) indexers [i];
1570 if ((ix.ModFlags & modflags) == 0)
1572 if ((ix.ModFlags & static_mask) != static_flags)
1578 if (b != null && filter (b, criteria) == true) {
1579 if (members == null)
1580 members = new ArrayList ();
1586 if (b != null && filter (b, criteria) == true) {
1587 if (members == null)
1588 members = new ArrayList ();
1596 if ((mt & MemberTypes.Event) != 0) {
1597 if (events != null) {
1598 int len = events.Count;
1599 for (int i = 0; i < len; i++) {
1600 Event e = (Event) events [i];
1602 if ((e.ModFlags & modflags) == 0)
1604 if ((e.ModFlags & static_mask) != static_flags)
1607 MemberInfo eb = e.EventBuilder;
1608 if (eb != null && filter (eb, criteria) == true) {
1609 if (members == null)
1610 members = new ArrayList ();
1612 members.Add (e.EventBuilder);
1618 if ((mt & MemberTypes.Property) != 0){
1619 if (properties != null) {
1620 int len = properties.Count;
1621 for (int i = 0; i < len; i++) {
1622 Property p = (Property) properties [i];
1624 if ((p.ModFlags & modflags) == 0)
1626 if ((p.ModFlags & static_mask) != static_flags)
1629 MemberInfo pb = p.PropertyBuilder;
1630 if (pb != null && filter (pb, criteria) == true) {
1631 if (members == null)
1632 members = new ArrayList ();
1634 members.Add (p.PropertyBuilder);
1639 if (indexers != null) {
1640 int len = indexers.Count;
1641 for (int i = 0; i < len; i++) {
1642 Indexer ix = (Indexer) indexers [i];
1644 if ((ix.ModFlags & modflags) == 0)
1646 if ((ix.ModFlags & static_mask) != static_flags)
1649 MemberInfo ib = ix.PropertyBuilder;
1650 if (ib != null && filter (ib, criteria) == true) {
1651 if (members == null)
1652 members = new ArrayList ();
1654 members.Add (ix.PropertyBuilder);
1660 if ((mt & MemberTypes.NestedType) != 0) {
1661 if (types != null) {
1662 int len = types.Count;
1663 for (int i = 0; i < len; i++) {
1664 TypeContainer t = (TypeContainer) types [i];
1666 if ((t.ModFlags & modflags) == 0)
1669 TypeBuilder tb = t.TypeBuilder;
1670 if (tb != null && (filter (tb, criteria) == true)) {
1671 if (members == null)
1672 members = new ArrayList ();
1679 if (enums != null) {
1680 int len = enums.Count;
1681 for (int i = 0; i < len; i++) {
1682 Enum en = (Enum) enums [i];
1684 if ((en.ModFlags & modflags) == 0)
1687 TypeBuilder tb = en.TypeBuilder;
1688 if (tb != null && (filter (tb, criteria) == true)) {
1689 if (members == null)
1690 members = new ArrayList ();
1697 if (delegates != null) {
1698 int len = delegates.Count;
1699 for (int i = 0; i < len; i++) {
1700 Delegate d = (Delegate) delegates [i];
1702 if ((d.ModFlags & modflags) == 0)
1705 TypeBuilder tb = d.TypeBuilder;
1706 if (tb != null && (filter (tb, criteria) == true)) {
1707 if (members == null)
1708 members = new ArrayList ();
1715 if (interfaces != null) {
1716 int len = interfaces.Count;
1717 for (int i = 0; i < len; i++) {
1718 Interface iface = (Interface) interfaces [i];
1720 if ((iface.ModFlags & modflags) == 0)
1723 TypeBuilder tb = iface.TypeBuilder;
1724 if (tb != null && (filter (tb, criteria) == true)) {
1725 if (members == null)
1726 members = new ArrayList ();
1734 if ((mt & MemberTypes.Constructor) != 0){
1735 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1736 int len = instance_constructors.Count;
1737 for (int i = 0; i < len; i++) {
1738 Constructor c = (Constructor) instance_constructors [i];
1740 ConstructorBuilder cb = c.ConstructorBuilder;
1741 if (cb != null && filter (cb, criteria) == true) {
1742 if (members == null)
1743 members = new ArrayList ();
1750 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1751 ConstructorBuilder cb =
1752 default_static_constructor.ConstructorBuilder;
1754 if (cb != null && filter (cb, criteria) == true) {
1755 if (members == null)
1756 members = new ArrayList ();
1764 // Lookup members in parent if requested.
1766 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1767 if (TypeBuilder.BaseType != null) {
1768 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1769 if (list.Count > 0) {
1770 if (members == null)
1771 members = new ArrayList ();
1773 members.AddRange (list);
1777 if (base_inteface_types != null) {
1778 foreach (Type base_type in base_inteface_types) {
1779 MemberList list = TypeContainer.FindMembers (base_type, mt, bf, filter, criteria);
1781 if (list.Count > 0) {
1782 if (members == null)
1783 members = new ArrayList ();
1784 members.AddRange (list);
1790 Timer.StopTimer (TimerType.TcFindMembers);
1792 if (members == null)
1793 return MemberList.Empty;
1795 return new MemberList (members);
1798 public override MemberCache MemberCache {
1800 return member_cache;
1804 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1805 MemberFilter filter, object criteria)
1807 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1810 return ds.FindMembers (mt, bf, filter, criteria);
1812 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1816 // FindMethods will look for methods not only in the type `t', but in
1817 // any interfaces implemented by the type.
1819 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1820 MemberFilter filter, object criteria)
1826 /// Emits the values for the constants
1828 public void EmitConstants ()
1830 if (constants != null)
1831 foreach (Const con in constants)
1836 protected virtual void VerifyMembers (EmitContext ec)
1839 // Check for internal or private fields that were never assigned
1841 if (RootContext.WarningLevel >= 3) {
1842 if (fields != null){
1843 foreach (Field f in fields) {
1844 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
1847 if ((f.status & Field.Status.USED) == 0){
1849 169, f.Location, "Private field " +
1850 MakeName (f.Name) + " is never used");
1855 // Only report 649 on level 4
1857 if (RootContext.WarningLevel < 4)
1860 if ((f.status & Field.Status.ASSIGNED) != 0)
1865 "Field " + MakeName (f.Name) + " is never assigned " +
1866 " to and will always have its default value");
1870 if (events != null){
1871 foreach (Event e in events){
1873 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1880 /// Emits the code, this step is performed after all
1881 /// the types, enumerations, constructors
1885 if (OptAttributes != null)
1886 OptAttributes.Emit (ec, this);
1890 if (instance_constructors != null) {
1891 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
1892 bool has_compliant_args = false;
1894 foreach (Constructor c in instance_constructors) {
1897 if (has_compliant_args)
1900 has_compliant_args = c.HasCompliantArgs;
1902 if (!has_compliant_args)
1903 Report.Error_T (3015, Location, GetSignatureForError ());
1905 foreach (Constructor c in instance_constructors)
1910 if (default_static_constructor != null)
1911 default_static_constructor.Emit (this);
1913 if (methods != null)
1914 foreach (Method m in methods)
1917 if (operators != null)
1918 foreach (Operator o in operators)
1921 if (properties != null)
1922 foreach (Property p in properties)
1925 if (indexers != null){
1926 foreach (Indexer ix in indexers)
1928 if (IndexerName != null) {
1929 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
1930 TypeBuilder.SetCustomAttribute (cb);
1935 foreach (Field f in fields)
1938 if (events != null){
1939 foreach (Event e in Events)
1943 if (delegates != null) {
1944 foreach (Delegate d in Delegates) {
1949 if (Pending != null)
1950 if (Pending.VerifyPendingMethods ())
1955 // if (types != null)
1956 // foreach (TypeContainer tc in types)
1960 CustomAttributeBuilder EmitDefaultMemberAttr ()
1962 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
1964 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
1965 ".ctor", MemberTypes.Constructor,
1966 BindingFlags.Public | BindingFlags.Instance,
1969 MethodGroupExpr mg = (MethodGroupExpr) ml;
1971 MethodBase constructor = mg.Methods [0];
1973 string [] vals = { IndexerName };
1975 CustomAttributeBuilder cb = null;
1977 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
1979 Report.Warning (-100, "Can not set the indexer default member attribute");
1985 public override void CloseType ()
1987 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1991 caching_flags |= Flags.CloseTypeCreated;
1992 TypeBuilder.CreateType ();
1993 } catch (TypeLoadException){
1995 // This is fine, the code still created the type
1997 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1998 // Console.WriteLine (e.Message);
2000 Console.WriteLine ("In type: " + Name);
2005 foreach (Enum en in Enums)
2008 if (interface_order != null){
2009 foreach (Interface iface in interface_order)
2014 foreach (TypeContainer tc in Types)
2018 foreach (TypeContainer tc in Types)
2019 if (!(tc is Struct))
2023 if (Delegates != null)
2024 foreach (Delegate d in Delegates)
2032 initialized_fields = null;
2033 initialized_static_fields = null;
2036 interface_order = null;
2042 default_constructor = null;
2043 default_static_constructor = null;
2045 OptAttributes = null;
2047 parent_container = null;
2048 member_cache = null;
2051 public string MakeName (string n)
2053 return "`" + Name + "." + n + "'";
2056 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2059 108, l, "The keyword new is required on " +
2060 MakeName (mi.Name) + " because it hides `" +
2061 mi.ReflectedType.Name + "." + mi.Name + "'");
2064 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2067 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2068 "inherited member, the keyword new is not required");
2071 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2074 72, l, MakeName (mi.Name) + " : cannot override; `" +
2075 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2078 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2084 // Performs the validation on a Method's modifiers (properties have
2085 // the same properties).
2087 public bool MethodModifiersValid (int flags, string n, Location loc)
2089 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2090 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2091 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2095 // At most one of static, virtual or override
2097 if ((flags & Modifiers.STATIC) != 0){
2098 if ((flags & vao) != 0){
2100 112, loc, "static method " + MakeName (n) + "can not be marked " +
2101 "as virtual, abstract or override");
2106 if (this is Struct){
2107 if ((flags & va) != 0){
2108 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2113 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2115 113, loc, MakeName (n) +
2116 " marked as override cannot be marked as new or virtual");
2121 // If the declaration includes the abstract modifier, then the
2122 // declaration does not include static, virtual or extern
2124 if ((flags & Modifiers.ABSTRACT) != 0){
2125 if ((flags & Modifiers.EXTERN) != 0){
2127 180, loc, MakeName (n) + " can not be both abstract and extern");
2131 if ((flags & Modifiers.VIRTUAL) != 0){
2133 503, loc, MakeName (n) + " can not be both abstract and virtual");
2137 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2139 513, loc, MakeName (n) +
2140 " is abstract but its container class is not");
2146 if ((flags & Modifiers.PRIVATE) != 0){
2147 if ((flags & vao) != 0){
2149 621, loc, MakeName (n) +
2150 " virtual or abstract members can not be private");
2155 if ((flags & Modifiers.SEALED) != 0){
2156 if ((flags & Modifiers.OVERRIDE) == 0){
2158 238, loc, MakeName (n) +
2159 " cannot be sealed because it is not an override");
2167 Hashtable builder_and_args;
2169 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2171 if (builder_and_args == null)
2172 builder_and_args = new Hashtable ();
2176 protected override bool VerifyClsCompliance (DeclSpace ds)
2178 if (!base.VerifyClsCompliance (ds))
2181 // parent_container is null for System.Object
2182 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2183 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2190 /// Performs checks for an explicit interface implementation. First it
2191 /// checks whether the `interface_type' is a base inteface implementation.
2192 /// Then it checks whether `name' exists in the interface type.
2194 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
2198 if (ifaces != null){
2199 foreach (TypeExpr t in ifaces){
2200 if (t.Type == interface_type){
2208 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2219 string IMemberContainer.Name {
2225 Type IMemberContainer.Type {
2231 IMemberContainer IMemberContainer.Parent {
2233 return parent_container;
2237 MemberCache IMemberContainer.MemberCache {
2239 return member_cache;
2243 bool IMemberContainer.IsInterface {
2245 return this is Interface;
2249 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2251 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2253 if (GenericType != null)
2254 return TypeManager.FindMembers (GenericType, mt, new_bf,
2257 return FindMembers (mt, new_bf, null, null);
2261 // Operator pair checking
2264 class OperatorEntry {
2266 public Type ret_type;
2267 public Type type1, type2;
2269 public Operator.OpType ot;
2271 public OperatorEntry (int f, Operator o)
2275 ret_type = o.OperatorMethod.GetReturnType ();
2276 Type [] pt = o.OperatorMethod.ParameterTypes;
2280 ot = o.OperatorType;
2283 public override int GetHashCode ()
2285 return ret_type.GetHashCode ();
2288 public override bool Equals (object o)
2290 OperatorEntry other = (OperatorEntry) o;
2292 if (other.ret_type != ret_type)
2294 if (other.type1 != type1)
2296 if (other.type2 != type2)
2303 // Checks that some operators come in pairs:
2309 // They are matched based on the return type and the argument types
2311 void CheckPairedOperators ()
2313 Hashtable pairs = new Hashtable (null, null);
2314 Operator true_op = null;
2315 Operator false_op = null;
2316 bool has_equality_or_inequality = false;
2318 // Register all the operators we care about.
2319 foreach (Operator op in operators){
2322 switch (op.OperatorType){
2323 case Operator.OpType.Equality:
2325 has_equality_or_inequality = true;
2327 case Operator.OpType.Inequality:
2329 has_equality_or_inequality = true;
2332 case Operator.OpType.True:
2335 case Operator.OpType.False:
2339 case Operator.OpType.GreaterThan:
2341 case Operator.OpType.LessThan:
2344 case Operator.OpType.GreaterThanOrEqual:
2346 case Operator.OpType.LessThanOrEqual:
2352 OperatorEntry oe = new OperatorEntry (reg, op);
2354 object o = pairs [oe];
2358 oe = (OperatorEntry) o;
2363 if (true_op != null){
2364 if (false_op == null)
2365 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2366 } else if (false_op != null)
2367 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2370 // Look for the mistakes.
2372 foreach (DictionaryEntry de in pairs){
2373 OperatorEntry oe = (OperatorEntry) de.Key;
2380 case Operator.OpType.Equality:
2383 case Operator.OpType.Inequality:
2386 case Operator.OpType.GreaterThan:
2389 case Operator.OpType.LessThan:
2392 case Operator.OpType.GreaterThanOrEqual:
2395 case Operator.OpType.LessThanOrEqual:
2399 Report.Error (216, oe.op.Location,
2400 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2403 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2404 MethodSignature equals_ms = new MethodSignature (
2405 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2406 MethodSignature hash_ms = new MethodSignature (
2407 "GetHashCode", TypeManager.int32_type, new Type [0]);
2409 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2410 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2412 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2413 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2416 bool equals_ok = false;
2417 if ((equals_ml != null) && (equals_ml.Count == 1))
2418 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2419 bool hash_ok = false;
2420 if ((hash_ml != null) && (hash_ml.Count == 1))
2421 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2424 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2425 "not override Object.Equals (object o)");
2427 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2428 "not override Object.GetHashCode ()");
2434 public class ClassOrStruct : TypeContainer {
2435 bool hasExplicitLayout = false;
2436 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2437 Attributes attrs, Location l)
2438 : base (ns, parent, name, attrs, l)
2442 protected override void VerifyMembers (EmitContext ec)
2444 if (Fields != null) {
2445 foreach (Field f in Fields) {
2446 if ((f.ModFlags & Modifiers.STATIC) != 0)
2448 if (hasExplicitLayout) {
2449 if (f.OptAttributes == null
2450 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2451 Report.Error (625, f.Location,
2452 "Instance field of type marked with"
2453 + " StructLayout(LayoutKind.Explicit) must have a"
2454 + " FieldOffset attribute.");
2458 if (f.OptAttributes != null
2459 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2460 Report.Error (636, f.Location,
2461 "The FieldOffset attribute can only be placed on members of "
2462 + "types marked with the StructLayout(LayoutKind.Explicit)");
2467 base.VerifyMembers (ec);
2470 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2472 if (a.Type == TypeManager.struct_layout_attribute_type
2473 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2474 hasExplicitLayout = true;
2476 base.ApplyAttributeBuilder (a, cb);
2480 public class Class : ClassOrStruct {
2482 // Modifiers allowed in a class declaration
2484 public const int AllowedModifiers =
2487 Modifiers.PROTECTED |
2488 Modifiers.INTERNAL |
2490 Modifiers.ABSTRACT |
2494 // Information in the case we are an attribute type
2495 AttributeUsageAttribute attribute_usage;
2497 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name,
2498 int mod, Attributes attrs, Location l)
2499 : base (ns, parent, name, attrs, l)
2503 if (parent.Parent == null)
2504 accmods = Modifiers.INTERNAL;
2506 accmods = Modifiers.PRIVATE;
2508 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2509 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2512 public override AttributeTargets AttributeTargets {
2514 return AttributeTargets.Class;
2518 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2520 if (a.UsageAttribute != null)
2521 attribute_usage = a.UsageAttribute;
2523 base.ApplyAttributeBuilder (a, cb);
2526 public AttributeUsageAttribute AttributeUsage {
2528 return attribute_usage;
2533 // FIXME: How do we deal with the user specifying a different
2536 public override TypeAttributes TypeAttr {
2538 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2543 public class Struct : ClassOrStruct {
2545 // Modifiers allowed in a struct declaration
2547 public const int AllowedModifiers =
2550 Modifiers.PROTECTED |
2551 Modifiers.INTERNAL |
2555 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2556 int mod, Attributes attrs, Location l)
2557 : base (ns, parent, name, attrs, l)
2561 if (parent.Parent == null)
2562 accmods = Modifiers.INTERNAL;
2564 accmods = Modifiers.PRIVATE;
2566 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2568 this.ModFlags |= Modifiers.SEALED;
2571 public override AttributeTargets AttributeTargets {
2573 return AttributeTargets.Struct;
2579 // FIXME: Allow the user to specify a different set of attributes
2580 // in some cases (Sealed for example is mandatory for a class,
2581 // but what SequentialLayout can be changed
2583 public override TypeAttributes TypeAttr {
2585 return base.TypeAttr |
2586 TypeAttributes.SequentialLayout |
2587 TypeAttributes.Sealed |
2588 TypeAttributes.BeforeFieldInit;
2596 public class Interface : TypeContainer, IMemberContainer {
2598 /// Modifiers allowed in a class declaration
2600 public const int AllowedModifiers =
2603 Modifiers.PROTECTED |
2604 Modifiers.INTERNAL |
2608 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
2609 int mod, Attributes attrs, Location l)
2610 : base (ns, parent, name, attrs, l)
2614 if (parent.Parent == null)
2615 accmods = Modifiers.INTERNAL;
2617 accmods = Modifiers.PRIVATE;
2619 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2622 public override AttributeTargets AttributeTargets {
2624 return AttributeTargets.Interface;
2628 public override TypeAttributes TypeAttr {
2630 return base.TypeAttr |
2631 TypeAttributes.AutoLayout |
2632 TypeAttributes.Abstract |
2633 TypeAttributes.Interface;
2638 public abstract class MethodCore : MemberBase {
2639 public readonly Parameters Parameters;
2640 public readonly GenericMethod GenericMethod;
2641 protected Block block;
2642 public DeclSpace ds;
2645 // Parameters, cached for semantic analysis.
2647 protected InternalParameters parameter_info;
2648 protected Type [] parameter_types;
2651 // This is set from TypeContainer.DefineMembers if this method overrides something.
2653 public bool OverridesSomething;
2655 // Whether this is an operator method.
2656 public bool IsOperator;
2658 static string[] attribute_targets = new string [] { "method", "return" };
2660 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2661 bool is_interface, MemberName name, Attributes attrs,
2662 Parameters parameters, Location loc)
2663 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2665 Parameters = parameters;
2666 IsInterface = is_interface;
2668 this.GenericMethod = ds as GenericMethod;
2672 // Returns the System.Type array for the parameters of this method
2674 public Type [] ParameterTypes {
2676 return parameter_types;
2680 public InternalParameters ParameterInfo
2683 return parameter_info;
2687 public Block Block {
2697 protected virtual bool DoDefineParameters ()
2699 // Check if arguments were correct
2700 parameter_types = Parameters.GetParameterInfo (ds);
2701 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2704 parameter_info = new InternalParameters (ds, Parameters);
2706 Parameter array_param = Parameters.ArrayParameter;
2707 if ((array_param != null) &&
2708 (!array_param.ParameterType.IsArray ||
2709 (array_param.ParameterType.GetArrayRank () != 1))) {
2710 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2717 void error_425 (Type old, Type t, string name)
2719 Report.Error (425, Location,
2720 "The constraints of type parameter `{0}' " +
2721 "of method `{1}' must match the constraints for " +
2722 "type parameter `{2}' of method `{3}'",
2723 TypeManager.CSharpName (old), Name,
2724 TypeManager.CSharpName (t), name);
2727 protected override bool CheckGenericOverride (MethodInfo method, string name)
2729 ParameterData pd = Invocation.GetParameterData (method);
2731 for (int i = 0; i < ParameterTypes.Length; i++) {
2732 GenericConstraints ogc = pd.GenericConstraints (i);
2733 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
2735 if ((gc == null) && (ogc == null))
2738 Type ot = pd.ParameterType (i);
2739 Type t = ParameterTypes [i];
2741 if (!((gc != null) && (ogc != null))) {
2742 error_425 (ot, t, name);
2746 if (gc.HasConstructor != ogc.HasConstructor) {
2747 error_425 (ot, t, name);
2751 if (ogc.HasClassConstraint != gc.HasClassConstraint) {
2752 error_425 (ot, t, name);
2756 if (ogc.HasClassConstraint &&
2757 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
2758 error_425 (ot, t, name);
2762 Type[] oct = ogc.InterfaceConstraints;
2763 Type[] ct = gc.InterfaceConstraints;
2765 if (oct.Length != ct.Length) {
2766 error_425 (ot, t, name);
2770 for (int j = 0; j < oct.Length; j++)
2771 if (!oct [j].Equals (ct [j])) {
2772 error_425 (ot, t, name);
2780 protected override string[] ValidAttributeTargets {
2782 return attribute_targets;
2786 protected override bool VerifyClsCompliance (DeclSpace ds)
2788 if (!base.VerifyClsCompliance (ds)) {
2789 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
2790 Report.Error_T (3011, Location, GetSignatureForError ());
2795 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
2797 if (!AttributeTester.IsClsCompliant (MemberType)) {
2798 Report.Error_T (3002, Location, GetSignatureForError ());
2804 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
2806 if ((method == this) || (method.Name != Name))
2809 Type[] param_types = method.ParameterTypes;
2810 if (param_types == null)
2813 if (param_types.Length != ParameterTypes.Length)
2816 int type_params = 0;
2817 if (GenericMethod != null)
2818 type_params = GenericMethod.CountTypeParameters;
2820 int m_type_params = 0;
2821 if (method.GenericMethod != null)
2822 m_type_params = method.GenericMethod.CountTypeParameters;
2824 if (type_params != m_type_params)
2830 Type[] infered_types = new Type [param_types.Length];
2831 may_unify = Invocation.InferTypeArguments (
2832 param_types, ParameterTypes, ref infered_types);
2835 infered_types = new Type [param_types.Length];
2836 may_unify = Invocation.InferTypeArguments (
2837 ParameterTypes, param_types, ref infered_types);
2840 for (int i = 0; i < param_types.Length; i++) {
2841 Type a = param_types [i];
2842 Type b = ParameterTypes [i];
2850 // Try to report 663: method only differs on out/ref
2852 ParameterData info = ParameterInfo;
2853 ParameterData other_info = method.ParameterInfo;
2854 for (int i = 0; i < info.Count; i++){
2855 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
2856 Report.Error (663, Location,
2857 "Overload method only differs " +
2858 "in parameter modifier");
2863 Report.Error (111, Location,
2864 "Class `{0}' already defines a member called " +
2865 "`{1}' with the same parameter types",
2868 } else if (may_unify) {
2869 Report.Error (408, Location,
2870 "`{0}' cannot define overload members that " +
2871 "may unify for some type parameter substitutions",
2879 public CallingConventions GetCallingConvention (bool is_class)
2881 CallingConventions cc = 0;
2883 cc = Parameters.GetCallingConvention ();
2886 if ((ModFlags & Modifiers.STATIC) == 0)
2887 cc |= CallingConventions.HasThis;
2889 // FIXME: How is `ExplicitThis' used in C#?
2895 public class Method : MethodCore, IIteratorContainer, IMethodData {
2896 public MethodBuilder MethodBuilder;
2897 public MethodData MethodData;
2898 ReturnParameter return_attributes;
2901 /// Modifiers allowed in a class declaration
2903 const int AllowedModifiers =
2906 Modifiers.PROTECTED |
2907 Modifiers.INTERNAL |
2912 Modifiers.OVERRIDE |
2913 Modifiers.ABSTRACT |
2915 Modifiers.METHOD_YIELDS |
2918 const int AllowedInterfaceModifiers =
2919 Modifiers.NEW | Modifiers.UNSAFE;
2922 // return_type can be "null" for VOID values.
2924 public Method (DeclSpace ds, Expression return_type, int mod, bool is_iface,
2925 MemberName name, Parameters parameters, Attributes attrs,
2927 : base (ds, return_type, mod,
2928 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
2929 is_iface, name, attrs, parameters, l)
2933 public override AttributeTargets AttributeTargets {
2935 return AttributeTargets.Method | AttributeTargets.ReturnValue;
2940 // Returns the `System.Type' for the ReturnType of this
2941 // function. Provides a nice cache. (used between semantic analysis
2942 // and actual code generation
2944 public Type GetReturnType ()
2949 public override string GetSignatureForError()
2951 return TypeManager.CSharpSignature (MethodBuilder);
2954 void DuplicateEntryPoint (MethodInfo b, Location location)
2958 "Program `" + CodeGen.FileName +
2959 "' has more than one entry point defined: `" +
2960 TypeManager.CSharpSignature(b) + "'");
2963 void Report28 (MethodInfo b)
2967 "`" + TypeManager.CSharpSignature(b) +
2968 "' has the wrong signature to be an entry point");
2971 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2973 if (b.ReturnType != TypeManager.void_type &&
2974 b.ReturnType != TypeManager.int32_type)
2977 if (pinfo.Count == 0)
2980 if (pinfo.Count > 1)
2983 Type t = pinfo.ParameterType(0);
2985 (t.GetArrayRank() == 1) &&
2986 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2987 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2993 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2995 if (a.Target == "return") {
2996 if (return_attributes == null)
2997 return_attributes = new ReturnParameter (MethodBuilder, Location);
2999 return_attributes.ApplyAttributeBuilder (a, cb);
3003 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3004 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3007 if (a.Type == TypeManager.dllimport_type)
3010 MethodBuilder.SetCustomAttribute (cb);
3014 // Checks our base implementation if any
3016 protected override bool CheckBase (TypeContainer container)
3018 base.CheckBase (container);
3020 // Check whether arguments were correct.
3021 if (!DoDefineParameters ())
3024 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3026 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3029 // Check in our class for dups
3031 ArrayList ar = container.Methods;
3033 int arLen = ar.Count;
3035 for (int i = 0; i < arLen; i++) {
3036 Method m = (Method) ar [i];
3037 if (IsDuplicateImplementation (container, m))
3045 // Verify if the parent has a type with the same name, and then
3046 // check whether we have to create a new slot for it or not.
3048 Type ptype = container.TypeBuilder.BaseType;
3050 // ptype is only null for System.Object while compiling corlib.
3051 if (ptype != null) {
3054 // Explicit implementations do not have `parent' methods, however,
3055 // the member cache stores them there. Without this check, we get
3056 // an incorrect warning in corlib.
3058 if (! IsExplicitImpl) {
3059 parent_method = (MethodInfo)((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
3060 container.TypeBuilder, Name, ParameterTypes, false);
3063 if (parent_method != null) {
3064 string name = parent_method.DeclaringType.Name + "." +
3067 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
3070 if ((ModFlags & Modifiers.NEW) == 0) {
3071 Type parent_ret = TypeManager.TypeToCoreType (
3072 parent_method.ReturnType);
3074 if (!parent_ret.Equals (MemberType)) {
3076 508, Location, container.MakeName (Name) + ": cannot " +
3077 "change return type when overriding " +
3078 "inherited member " + name);
3083 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
3084 WarningNotHiding (container);
3086 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3087 Report.Error (115, Location,
3088 container.MakeName (Name) +
3089 " no suitable methods found to override");
3092 } else if ((ModFlags & Modifiers.NEW) != 0)
3093 WarningNotHiding (container);
3101 public override bool Define (TypeContainer container)
3104 MethodBuilder mb = null;
3105 if (GenericMethod != null) {
3106 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
3107 if (!GenericMethod.Define (container, mb))
3109 decl = GenericMethod;
3113 if (!DoDefine (decl, container))
3116 if (!CheckBase (container))
3119 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
3120 true, this, mb, GenericMethod);
3122 if (!MethodData.Define (container))
3126 // Setup iterator if we are one
3128 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3129 IteratorHandler ih = new IteratorHandler (
3130 Name, container, MemberType,
3131 ParameterTypes, ParameterInfo,
3132 ModFlags, Location);
3134 Block new_block = ih.Setup (block);
3135 if (new_block == null)
3140 MethodBuilder = MethodData.MethodBuilder;
3143 // This is used to track the Entry Point,
3145 if (Name == "Main" &&
3146 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3147 (RootContext.MainClass == null ||
3148 RootContext.MainClass == container.TypeBuilder.FullName)){
3149 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3150 if (RootContext.EntryPoint == null) {
3151 if (container.IsGeneric){
3152 Report.Error (-201, Location,
3153 "Entry point can not be defined in a generic class");
3156 RootContext.EntryPoint = MethodBuilder;
3157 RootContext.EntryPointLocation = Location;
3159 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3160 DuplicateEntryPoint (MethodBuilder, Location);
3163 Report28(MethodBuilder);
3172 public override void Emit (TypeContainer container)
3174 MethodData.Emit (container, this);
3175 base.Emit (container);
3180 void IIteratorContainer.SetYields ()
3182 ModFlags |= Modifiers.METHOD_YIELDS;
3185 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3187 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3190 #region IMethodData Members
3192 public CallingConventions CallingConventions {
3194 CallingConventions cc = Parameters.GetCallingConvention ();
3197 if ((ModFlags & Modifiers.STATIC) == 0)
3198 cc |= CallingConventions.HasThis;
3200 // FIXME: How is `ExplicitThis' used in C#?
3206 public Type ReturnType {
3212 public string MethodName {
3218 public new Location Location {
3220 return base.Location;
3224 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3226 return new EmitContext (tc, ds, Location, ig, ReturnType, ModFlags, false);
3232 public abstract class ConstructorInitializer {
3233 ArrayList argument_list;
3234 ConstructorInfo parent_constructor;
3235 Parameters parameters;
3238 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3241 this.argument_list = argument_list;
3242 this.parameters = parameters;
3246 public ArrayList Arguments {
3248 return argument_list;
3252 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3254 Expression parent_constructor_group;
3257 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3259 if (argument_list != null){
3260 foreach (Argument a in argument_list){
3261 if (!a.Resolve (ec, loc))
3265 ec.CurrentBlock = null;
3267 if (this is ConstructorBaseInitializer) {
3268 if (ec.ContainerType.BaseType == null)
3271 t = ec.ContainerType.BaseType;
3272 if (ec.ContainerType.IsValueType) {
3273 Report.Error (522, loc,
3274 "structs cannot call base class constructors");
3278 t = ec.ContainerType;
3280 parent_constructor_group = Expression.MemberLookup (
3281 ec, t, ".ctor", MemberTypes.Constructor,
3282 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3285 if (parent_constructor_group == null){
3286 parent_constructor_group = Expression.MemberLookup (
3287 ec, t, ".ctor", MemberTypes.Constructor,
3288 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3291 if (parent_constructor_group != null)
3293 112, loc, "`{0}.{1}' is inaccessible due to " +
3294 "its protection level", t.FullName, t.Name);
3297 1501, loc, "Can not find a constructor for " +
3298 "this argument list");
3302 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3303 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3306 if (parent_constructor == null){
3307 Report.Error (1501, loc,
3308 "Can not find a constructor for this argument list");
3312 if (parent_constructor == caller_builder){
3313 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3320 public void Emit (EmitContext ec)
3322 if (parent_constructor != null){
3323 ec.Mark (loc, false);
3325 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3327 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3332 public class ConstructorBaseInitializer : ConstructorInitializer {
3333 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
3334 base (argument_list, pars, l)
3339 public class ConstructorThisInitializer : ConstructorInitializer {
3340 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
3341 base (argument_list, pars, l)
3346 public class Constructor : MethodCore {
3347 public ConstructorBuilder ConstructorBuilder;
3348 public ConstructorInitializer Initializer;
3351 // Modifiers allowed for a constructor.
3353 public const int AllowedModifiers =
3355 Modifiers.PROTECTED |
3356 Modifiers.INTERNAL |
3362 bool has_compliant_args = false;
3364 // The spec claims that static is not permitted, but
3365 // my very own code has static constructors.
3367 public Constructor (DeclSpace ds, string name, int mod, Parameters args,
3368 ConstructorInitializer init, Location l)
3369 : base (ds, null, mod, AllowedModifiers, false,
3370 new MemberName (name), null, args, l)
3375 public override string GetSignatureForError()
3377 return TypeManager.CSharpSignature (ConstructorBuilder);
3380 public bool HasCompliantArgs {
3382 return has_compliant_args;
3386 public override AttributeTargets AttributeTargets {
3388 return AttributeTargets.Constructor;
3394 // Returns true if this is a default constructor
3396 public bool IsDefault ()
3398 if ((ModFlags & Modifiers.STATIC) != 0)
3399 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3400 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
3403 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
3404 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
3405 (Initializer is ConstructorBaseInitializer) &&
3406 (Initializer.Arguments == null);
3409 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3411 ConstructorBuilder.SetCustomAttribute (cb);
3414 protected override bool CheckBase (TypeContainer container)
3416 base.CheckBase (container);
3418 // Check whether arguments were correct.
3419 if (!DoDefineParameters ())
3422 if ((ModFlags & Modifiers.STATIC) != 0)
3425 if (container is Struct && ParameterTypes.Length == 0) {
3426 Report.Error (568, Location,
3427 "Structs can not contain explicit parameterless " +
3433 // Check in our class for dups
3435 ArrayList ar = container.InstanceConstructors;
3437 int arLen = ar.Count;
3439 for (int i = 0; i < arLen; i++) {
3440 Constructor m = (Constructor) ar [i];
3441 if (IsDuplicateImplementation (container, m))
3450 // Creates the ConstructorBuilder
3452 public override bool Define (TypeContainer container)
3454 MethodAttributes ca = (MethodAttributes.RTSpecialName |
3455 MethodAttributes.SpecialName);
3457 if ((ModFlags & Modifiers.STATIC) != 0){
3458 ca |= MethodAttributes.Static | MethodAttributes.Private;
3460 ca |= MethodAttributes.HideBySig;
3462 if ((ModFlags & Modifiers.PUBLIC) != 0)
3463 ca |= MethodAttributes.Public;
3464 else if ((ModFlags & Modifiers.PROTECTED) != 0){
3465 if ((ModFlags & Modifiers.INTERNAL) != 0)
3466 ca |= MethodAttributes.FamORAssem;
3468 ca |= MethodAttributes.Family;
3469 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
3470 ca |= MethodAttributes.Assembly;
3471 else if (IsDefault ())
3472 ca |= MethodAttributes.Public;
3474 ca |= MethodAttributes.Private;
3477 // Check if arguments were correct.
3478 if (!CheckBase (container))
3481 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
3482 ca, GetCallingConvention (container is Class), ParameterTypes);
3484 if ((ModFlags & Modifiers.UNSAFE) != 0)
3485 ConstructorBuilder.InitLocals = false;
3488 // HACK because System.Reflection.Emit is lame
3490 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
3498 public override void Emit (TypeContainer container)
3500 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
3501 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
3504 // extern methods have no bodies
3506 if ((ModFlags & Modifiers.EXTERN) != 0) {
3507 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
3509 179, Location, "External constructor `" +
3510 TypeManager.CSharpSignature (ConstructorBuilder) +
3511 "' can not have a body");
3514 } else if (block == null) {
3516 501, Location, "Constructor `" +
3517 TypeManager.CSharpSignature (ConstructorBuilder) +
3518 "' must declare a body since it is not marked extern");
3522 if ((ModFlags & Modifiers.STATIC) == 0){
3523 if (container is Class && Initializer == null)
3524 Initializer = new ConstructorBaseInitializer (
3525 null, Parameters.EmptyReadOnlyParameters, Location);
3529 // Spec mandates that Initializers will not have
3533 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
3535 ec.IsStatic = false;
3538 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
3540 SymbolWriter sw = CodeGen.SymbolWriter;
3541 bool generate_debugging = false;
3543 if ((sw != null) && (block != null) &&
3544 !Location.IsNull (Location) &&
3545 !Location.IsNull (block.EndLocation) &&
3546 (Location.SymbolDocument != null)) {
3547 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
3549 generate_debugging = true;
3553 // Classes can have base initializers and instance field initializers.
3555 if (container is Class){
3556 if ((ModFlags & Modifiers.STATIC) == 0){
3559 // If we use a "this (...)" constructor initializer, then
3560 // do not emit field initializers, they are initialized in the other constructor
3562 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
3563 container.EmitFieldInitializers (ec);
3566 if (Initializer != null)
3567 Initializer.Emit (ec);
3569 if ((ModFlags & Modifiers.STATIC) != 0)
3570 container.EmitFieldInitializers (ec);
3572 if (OptAttributes != null)
3573 OptAttributes.Emit (ec, this);
3575 // If this is a non-static `struct' constructor and doesn't have any
3576 // initializer, it must initialize all of the struct's fields.
3577 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
3578 Block.AddThisVariable (container, Location);
3580 ec.EmitTopBlock (block, ParameterInfo, Location);
3582 if (generate_debugging)
3585 base.Emit (container);
3590 // For constructors is needed to test only parameters
3591 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3593 if (parameter_types == null || parameter_types.Length == 0)
3596 TypeContainer tc = ds as TypeContainer;
3598 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
3599 Constructor c = (Constructor) tc.InstanceConstructors [i];
3601 if (c == this || c.ParameterTypes.Length == 0)
3604 if (!c.IsClsCompliaceRequired (ds))
3607 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
3608 Report.Error_T (3006, Location, GetSignatureForError ());
3613 if (tc.TypeBuilder.BaseType == null)
3616 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
3617 if (temp_ds != null)
3618 return IsIdentifierClsCompliant (temp_ds);
3620 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
3621 // Skip parameter-less ctor
3625 foreach (ConstructorInfo ci in ml) {
3626 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
3627 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
3630 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
3631 Report.Error_T (3006, Location, GetSignatureForError ());
3639 protected override bool VerifyClsCompliance (DeclSpace ds)
3641 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
3645 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
3646 foreach (Type param in parameter_types) {
3647 if (param.IsArray) {
3652 has_compliant_args = true;
3659 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
3661 public interface IMethodData
3663 CallingConventions CallingConventions { get; }
3664 Location Location { get; }
3665 string MethodName { get; }
3666 Type[] ParameterTypes { get; }
3667 Type ReturnType { get; }
3669 Attributes OptAttributes { get; }
3670 Block Block { get; }
3672 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
3676 // Encapsulates most of the Method's state
3678 public class MethodData {
3680 readonly IMethodData method;
3683 // The return type of this method
3685 public readonly GenericMethod GenericMethod;
3686 public readonly InternalParameters ParameterInfo;
3689 // Are we implementing an interface ?
3691 public bool IsImplementing = false;
3696 protected MemberBase member;
3697 protected int modifiers;
3698 protected MethodAttributes flags;
3699 protected bool is_method;
3700 protected Type declaring_type;
3703 // It can either hold a string with the condition, or an arraylist of conditions.
3704 object conditionals;
3707 MethodBuilder builder = null;
3708 public MethodBuilder MethodBuilder {
3714 public Type DeclaringType {
3716 return declaring_type;
3720 public MethodData (MemberBase member, InternalParameters parameters,
3721 int modifiers, MethodAttributes flags, bool is_method,
3724 this.member = member;
3725 this.ParameterInfo = parameters;
3726 this.modifiers = modifiers;
3728 this.is_method = is_method;
3729 this.conditionals = null;
3731 this.method = method;
3734 public MethodData (MemberBase member, InternalParameters parameters,
3735 int modifiers, MethodAttributes flags, bool is_method,
3736 IMethodData method, MethodBuilder builder,
3737 GenericMethod generic)
3738 : this (member, parameters, modifiers, flags, is_method, method)
3740 this.builder = builder;
3741 this.GenericMethod = generic;
3747 Attribute dllimport_attribute = null;
3748 string obsolete = null;
3749 bool obsolete_error = false;
3751 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method,
3754 if ((opt_attrs == null) || (opt_attrs.Attrs == null))
3757 foreach (Attribute a in opt_attrs.Attrs) {
3758 Type attr_type = a.ResolveType (ec, true);
3759 if (attr_type == TypeManager.conditional_attribute_type) {
3760 if (!ApplyConditionalAttribute (a))
3762 } else if (attr_type == TypeManager.obsolete_attribute_type) {
3763 if (!ApplyObsoleteAttribute (a))
3765 } else if (attr_type == TypeManager.dllimport_type) {
3767 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3770 if (!ApplyDllImportAttribute (a))
3779 // Applies the `DllImport' attribute to the method.
3781 protected virtual bool ApplyDllImportAttribute (Attribute a)
3783 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3784 if ((modifiers & extern_static) != extern_static) {
3785 Report.Error (601, method.Location,
3786 "The DllImport attribute must be specified on a method " +
3787 "marked `static' and `extern'.");
3791 flags |= MethodAttributes.PinvokeImpl;
3792 dllimport_attribute = a;
3797 // Applies the `Obsolete' attribute to the method.
3799 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3801 if (obsolete != null) {
3802 Report.Error (579, method.Location, "Duplicate `Obsolete' attribute");
3806 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3807 return obsolete != null;
3811 // Applies the `Conditional' attribute to the method.
3813 protected virtual bool ApplyConditionalAttribute (Attribute a)
3815 // The Conditional attribute is only valid on methods.
3817 Attribute.Error_AttributeNotValidForElement (a, method.Location);
3821 string condition = a.Conditional_GetConditionName ();
3823 if (condition == null)
3826 if (method.ReturnType != TypeManager.void_type) {
3827 Report.Error (578, method.Location,
3828 "Conditional not valid on `" + member.Name + "' " +
3829 "because its return type is not void");
3833 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3834 Report.Error (243, method.Location,
3835 "Conditional not valid on `" + member.Name + "' " +
3836 "because it is an override method");
3840 if (member.IsExplicitImpl) {
3841 Report.Error (577, method.Location,
3842 "Conditional not valid on `" + member.Name + "' " +
3843 "because it is an explicit interface implementation");
3847 if (IsImplementing) {
3848 Report.Error (623, method.Location,
3849 "Conditional not valid on `" + member.Name + "' " +
3850 "because it is an interface method");
3855 // The likelyhood that the conditional will be more than 1 is very slim
3857 if (conditionals == null)
3858 conditionals = condition;
3859 else if (conditionals is string){
3860 string s = (string) conditionals;
3861 conditionals = new ArrayList ();
3862 ((ArrayList)conditionals).Add (s);
3864 ((ArrayList)conditionals).Add (condition);
3870 // Checks whether this method should be ignored due to its Conditional attributes.
3872 bool ShouldIgnore (Location loc)
3874 // When we're overriding a virtual method, we implicitly inherit the
3875 // Conditional attributes from our parent.
3876 if (member.ParentMethod != null) {
3877 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3878 member.ParentMethod, loc);
3880 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3884 if (conditionals != null){
3885 if (conditionals is string){
3886 if (RootContext.AllDefines [conditionals] == null)
3889 foreach (string condition in (ArrayList) conditionals)
3890 if (RootContext.AllDefines [condition] == null)
3898 // Returns the TypeManager.MethodFlags for this method.
3899 // This emits an error 619 / warning 618 if the method is obsolete.
3900 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3902 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3904 TypeManager.MethodFlags flags = 0;
3906 if (obsolete != null) {
3907 if (obsolete_error) {
3908 Report.Error (619, loc, "Method `" + member.Name +
3909 "' is obsolete: `" + obsolete + "'");
3910 return TypeManager.MethodFlags.IsObsoleteError;
3912 Report.Warning (618, loc, "Method `" + member.Name +
3913 "' is obsolete: `" + obsolete + "'");
3915 flags |= TypeManager.MethodFlags.IsObsolete;
3918 if (ShouldIgnore (loc))
3919 flags |= TypeManager.MethodFlags.ShouldIgnore;
3924 public bool Define (TypeContainer container)
3926 MethodInfo implementing = null;
3929 ec = method.CreateEmitContext (container, null);
3931 if (method.OptAttributes != null)
3932 if (!ApplyAttributes (method.OptAttributes, is_method, ec))
3935 if (member.IsExplicitImpl)
3936 prefix = member.InterfaceType.FullName + ".";
3940 string name = method.MethodName;
3941 string method_name = prefix + name;
3942 Type[] ParameterTypes = method.ParameterTypes;
3944 if (container.Pending != null){
3945 if (member is Indexer)
3946 implementing = container.Pending.IsInterfaceIndexer (
3947 member.InterfaceType, method.ReturnType, ParameterTypes);
3949 implementing = container.Pending.IsInterfaceMethod (
3950 member.InterfaceType, name, method.ReturnType, ParameterTypes);
3952 if (member.InterfaceType != null && implementing == null){
3953 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
3959 // For implicit implementations, make sure we are public, for
3960 // explicit implementations, make sure we are private.
3962 if (implementing != null){
3964 // Setting null inside this block will trigger a more
3965 // verbose error reporting for missing interface implementations
3967 // The "candidate" function has been flagged already
3968 // but it wont get cleared
3970 if (member.IsExplicitImpl){
3971 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3972 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
3973 implementing = null;
3975 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3976 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3978 // If this is an interface method implementation,
3979 // check for public accessibility
3981 implementing = null;
3982 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3983 // We may never be private.
3984 implementing = null;
3985 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3987 // We may be protected if we're overriding something.
3989 implementing = null;
3994 // Static is not allowed
3996 if ((modifiers & Modifiers.STATIC) != 0){
3997 implementing = null;
3998 Modifiers.Error_InvalidModifier (method.Location, "static");
4003 // If implementing is still valid, set flags
4005 if (implementing != null){
4007 // When implementing interface methods, set NewSlot
4008 // unless, we are overwriting a method.
4010 if (implementing.DeclaringType.IsInterface){
4011 if ((modifiers & Modifiers.OVERRIDE) == 0)
4012 flags |= MethodAttributes.NewSlot;
4015 MethodAttributes.Virtual |
4016 MethodAttributes.HideBySig;
4018 // Set Final unless we're virtual, abstract or already overriding a method.
4019 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4020 flags |= MethodAttributes.Final;
4022 // Get the method name from the explicit interface.
4023 if (member.InterfaceType != null) {
4024 name = implementing.Name;
4025 method_name = prefix + name;
4028 IsImplementing = true;
4032 // Create the MethodBuilder for the method
4034 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
4035 if ((modifiers & Modifiers.STATIC) == 0) {
4036 Report.Error (601, method.Location,
4037 "The DllImport attribute must be specified on " +
4038 "a method marked 'static' and 'extern'.");
4041 builder = dllimport_attribute.DefinePInvokeMethod (
4042 ec, container.TypeBuilder, method_name, flags,
4043 method.ReturnType, ParameterTypes);
4044 } else if (builder == null)
4045 builder = container.TypeBuilder.DefineMethod (
4046 method_name, flags, method.CallingConventions,
4047 method.ReturnType, ParameterTypes);
4049 builder.SetGenericMethodSignature (
4050 flags, method.CallingConventions,
4051 method.ReturnType, ParameterTypes);
4053 if (builder == null)
4056 if (GenericMethod != null) {
4057 if (!GenericMethod.DefineType (ec, builder))
4061 if (container.CurrentType != null)
4062 declaring_type = container.CurrentType.ResolveType (ec);
4064 declaring_type = container.TypeBuilder;
4066 if ((modifiers & Modifiers.UNSAFE) != 0)
4067 builder.InitLocals = false;
4069 if (IsImplementing){
4071 // clear the pending implemntation flag
4073 if (member is Indexer) {
4074 container.Pending.ImplementIndexer (
4075 member.InterfaceType, builder, method.ReturnType,
4076 ParameterTypes, true);
4078 container.Pending.ImplementMethod (
4079 member.InterfaceType, name, method.ReturnType,
4080 ParameterTypes, member.IsExplicitImpl);
4082 if (member.IsExplicitImpl)
4083 container.TypeBuilder.DefineMethodOverride (
4084 builder, implementing);
4088 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
4089 Report.Error (111, method.Location,
4090 "Class `" + container.Name +
4091 "' already contains a definition with the " +
4092 "same return value and parameter types as the " +
4093 "'get' method of property `" + member.Name + "'");
4097 TypeManager.AddMethod (builder, this);
4105 public void Emit (TypeContainer container, Attributable kind)
4109 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4110 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
4112 ec = method.CreateEmitContext (container, null);
4114 Location loc = method.Location;
4115 Attributes OptAttributes = method.OptAttributes;
4117 if (OptAttributes != null)
4118 OptAttributes.Emit (ec, kind);
4120 if (member is MethodCore)
4121 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
4123 SymbolWriter sw = CodeGen.SymbolWriter;
4124 Block block = method.Block;
4127 // abstract or extern methods have no bodies
4129 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4130 if (block == null) {
4131 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0) &&
4132 !Location.IsNull (loc) &&
4133 (method.Location.SymbolDocument != null)) {
4134 sw.OpenMethod (container, MethodBuilder, loc, loc);
4142 // abstract or extern methods have no bodies.
4144 if ((modifiers & Modifiers.ABSTRACT) != 0)
4146 500, method.Location, "Abstract method `" +
4147 TypeManager.CSharpSignature (builder) +
4148 "' can not have a body");
4150 if ((modifiers & Modifiers.EXTERN) != 0)
4152 179, method.Location, "External method `" +
4153 TypeManager.CSharpSignature (builder) +
4154 "' can not have a body");
4160 // Methods must have a body unless they're extern or abstract
4162 if (block == null) {
4164 501, method.Location, "Method `" +
4165 TypeManager.CSharpSignature (builder) +
4166 "' must declare a body since it is not marked " +
4167 "abstract or extern");
4172 // Handle destructors specially
4174 // FIXME: This code generates buggy code
4176 if ((sw != null) && !Location.IsNull (loc) &&
4177 !Location.IsNull (block.EndLocation) &&
4178 (loc.SymbolDocument != null)) {
4179 sw.OpenMethod (container, MethodBuilder, loc, block.EndLocation);
4181 if (member is Destructor)
4182 EmitDestructor (ec, block);
4184 ec.EmitTopBlock (block, ParameterInfo, loc);
4188 if (member is Destructor)
4189 EmitDestructor (ec, block);
4191 ec.EmitTopBlock (block, ParameterInfo, loc);
4195 void EmitDestructor (EmitContext ec, Block block)
4197 ILGenerator ig = ec.ig;
4199 Label finish = ig.DefineLabel ();
4201 block.SetDestructor ();
4203 ig.BeginExceptionBlock ();
4204 ec.ReturnLabel = finish;
4205 ec.HasReturnLabel = true;
4206 ec.EmitTopBlock (block, null, method.Location);
4208 // ig.MarkLabel (finish);
4209 ig.BeginFinallyBlock ();
4211 if (ec.ContainerType.BaseType != null) {
4212 Expression member_lookup = Expression.MemberLookup (
4213 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4214 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4216 if (member_lookup != null){
4217 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4219 ig.Emit (OpCodes.Ldarg_0);
4220 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4224 ig.EndExceptionBlock ();
4225 //ig.MarkLabel (ec.ReturnLabel);
4226 ig.Emit (OpCodes.Ret);
4230 public class Destructor : Method {
4232 public Destructor (DeclSpace ds, Expression return_type, int mod, string name,
4233 Parameters parameters, Attributes attrs, Location l)
4234 : base (ds, return_type, mod, false, new MemberName (name),
4235 parameters, attrs, l)
4240 abstract public class MemberBase : MemberCore {
4241 public Expression Type;
4243 public MethodAttributes flags;
4245 protected readonly int explicit_mod_flags;
4248 // The "short" name of this property / indexer / event. This is the
4249 // name without the explicit interface.
4251 public string ShortName;
4254 // The type of this property / indexer / event
4256 public Type MemberType;
4259 // If true, this is an explicit interface implementation
4261 public bool IsExplicitImpl = false;
4264 // The name of the interface we are explicitly implementing
4266 public Expression ExplicitInterfaceName = null;
4269 // Whether this is an interface member.
4271 public bool IsInterface;
4274 // If true, the interface type we are explicitly implementing
4276 public Type InterfaceType = null;
4279 // The method we're overriding if this is an override method.
4281 protected MethodInfo parent_method = null;
4282 public MethodInfo ParentMethod {
4284 return parent_method;
4289 // The constructor is only exposed to our children
4291 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod,
4292 MemberName name, Attributes attrs, Location loc)
4293 : base (name, attrs, loc)
4295 explicit_mod_flags = mod;
4297 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4300 protected virtual bool CheckBase (TypeContainer container)
4302 if ((container is Struct) || (RootContext.WarningLevel > 3)){
4303 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
4304 if (container is Struct){
4305 Report.Error (666, Location, "Protected member in struct declaration");
4308 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
4314 protected void WarningNotHiding (TypeContainer parent)
4318 "The member " + parent.MakeName (Name) + " does not hide an " +
4319 "inherited member. The keyword new is not required");
4323 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4327 // FIXME: report the old/new permissions?
4330 507, Location, parent.MakeName (Name) +
4331 ": can't change the access modifiers when overriding inherited " +
4332 "member `" + name + "'");
4335 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4338 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4339 // that have been defined.
4341 // `name' is the user visible name for reporting errors (this is used to
4342 // provide the right name regarding method names and properties)
4344 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4345 MethodInfo mb, string name)
4349 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4350 if (!(mb.IsAbstract || mb.IsVirtual)){
4352 506, Location, parent.MakeName (Name) +
4353 ": cannot override inherited member `" +
4354 name + "' because it is not " +
4355 "virtual, abstract or override");
4359 // Now we check that the overriden method is not final
4362 // This happens when implementing interface methods.
4363 if (mb.IsHideBySig && mb.IsVirtual) {
4365 506, Location, parent.MakeName (Name) +
4366 ": cannot override inherited member `" +
4367 name + "' because it is not " +
4368 "virtual, abstract or override");
4370 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4371 "override inherited member `" + name +
4372 "' because it is sealed.");
4377 // Check that the constraints match when overriding a
4381 if (!CheckGenericOverride (mb, name))
4385 // Check that the permissions are not being changed
4387 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4388 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4391 // special case for "protected internal"
4394 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4396 // when overriding protected internal, the method can be declared
4397 // protected internal only within the same assembly
4400 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4401 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4403 // assemblies differ - report an error
4406 Error_CannotChangeAccessModifiers (parent, mb, name);
4408 } else if (thisp != parentp) {
4410 // same assembly, but other attributes differ - report an error
4413 Error_CannotChangeAccessModifiers (parent, mb, name);
4416 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4418 // if it's not "protected internal", it must be "protected"
4421 Error_CannotChangeAccessModifiers (parent, mb, name);
4423 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4425 // protected within the same assembly - an error
4427 Error_CannotChangeAccessModifiers (parent, mb, name);
4429 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4430 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4432 // protected ok, but other attributes differ - report an error
4434 Error_CannotChangeAccessModifiers (parent, mb, name);
4438 if (thisp != parentp){
4439 Error_CannotChangeAccessModifiers (parent, mb, name);
4445 if (mb.IsVirtual || mb.IsAbstract){
4446 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4447 if (Name != "Finalize"){
4449 114, 2, Location, parent.MakeName (Name) +
4450 " hides inherited member `" + name +
4451 "'. To make the current member override that " +
4452 "implementation, add the override keyword, " +
4453 "otherwise use the new keyword");
4454 ModFlags |= Modifiers.NEW;
4458 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4459 if (Name != "Finalize"){
4461 108, 1, Location, "The keyword new is required on " +
4462 parent.MakeName (Name) + " because it hides " +
4463 "inherited member `" + name + "'");
4464 ModFlags |= Modifiers.NEW;
4472 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
4476 foreach (Type partype in parameters){
4477 if (partype == TypeManager.void_type) {
4479 1547, Location, "Keyword 'void' cannot " +
4480 "be used in this context");
4484 if (partype.IsPointer){
4487 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
4491 if (ds.AsAccessible (partype, ModFlags))
4494 if (this is Indexer)
4495 Report.Error (55, Location,
4496 "Inconsistent accessibility: parameter type `" +
4497 TypeManager.CSharpName (partype) + "' is less " +
4498 "accessible than indexer `" + Name + "'");
4499 else if ((this is Method) && ((Method) this).IsOperator)
4500 Report.Error (57, Location,
4501 "Inconsistent accessibility: parameter type `" +
4502 TypeManager.CSharpName (partype) + "' is less " +
4503 "accessible than operator `" + Name + "'");
4505 Report.Error (51, Location,
4506 "Inconsistent accessibility: parameter type `" +
4507 TypeManager.CSharpName (partype) + "' is less " +
4508 "accessible than method `" + Name + "'");
4515 protected virtual bool DoDefine (DeclSpace decl, TypeContainer container)
4521 ModFlags = Modifiers.PUBLIC |
4522 Modifiers.ABSTRACT |
4523 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
4525 flags = MethodAttributes.Public |
4526 MethodAttributes.Abstract |
4527 MethodAttributes.HideBySig |
4528 MethodAttributes.NewSlot |
4529 MethodAttributes.Virtual;
4531 if (!container.MethodModifiersValid (ModFlags, Name, Location))
4534 flags = Modifiers.MethodAttr (ModFlags);
4537 // Lookup Type, verify validity
4538 MemberType = decl.ResolveType (Type, false, Location);
4539 if (MemberType == null)
4542 if ((container.ModFlags & Modifiers.SEALED) != 0){
4543 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
4544 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
4549 // verify accessibility
4550 if (!container.AsAccessible (MemberType, ModFlags)) {
4551 if (this is Property)
4552 Report.Error (53, Location,
4553 "Inconsistent accessibility: property type `" +
4554 TypeManager.CSharpName (MemberType) + "' is less " +
4555 "accessible than property `" + Name + "'");
4556 else if (this is Indexer)
4557 Report.Error (54, Location,
4558 "Inconsistent accessibility: indexer return type `" +
4559 TypeManager.CSharpName (MemberType) + "' is less " +
4560 "accessible than indexer `" + Name + "'");
4561 else if (this is Method) {
4562 if (((Method) this).IsOperator)
4563 Report.Error (56, Location,
4564 "Inconsistent accessibility: return type `" +
4565 TypeManager.CSharpName (MemberType) + "' is less " +
4566 "accessible than operator `" + Name + "'");
4568 Report.Error (50, Location,
4569 "Inconsistent accessibility: return type `" +
4570 TypeManager.CSharpName (MemberType) + "' is less " +
4571 "accessible than method `" + Name + "'");
4573 Report.Error (52, Location,
4574 "Inconsistent accessibility: field type `" +
4575 TypeManager.CSharpName (MemberType) + "' is less " +
4576 "accessible than field `" + Name + "'");
4580 if (MemberType.IsPointer && !UnsafeOK (container))
4584 // Check for explicit interface implementation
4586 if (MemberName.TypeName != null) {
4587 ExplicitInterfaceName = MemberName.TypeName.GetTypeExpression (Location);
4588 ShortName = MemberName.Name;
4592 if (ExplicitInterfaceName != null) {
4593 InterfaceType = container.ResolveType (
4594 ExplicitInterfaceName, false, Location);
4595 if (InterfaceType == null)
4598 if (InterfaceType.IsClass) {
4599 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
4603 // Compute the full name that we need to export.
4604 Name = InterfaceType.FullName + "." + ShortName;
4606 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
4609 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
4611 IsExplicitImpl = true;
4613 IsExplicitImpl = false;
4618 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4620 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
4623 protected override bool VerifyClsCompliance(DeclSpace ds)
4625 if (base.VerifyClsCompliance (ds)) {
4629 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
4630 Report.Error_T (3010, Location, GetSignatureForError ());
4639 // Fields and Events both generate FieldBuilders, we use this to share
4640 // their common bits. This is also used to flag usage of the field
4642 abstract public class FieldBase : MemberBase {
4643 public FieldBuilder FieldBuilder;
4644 public Status status;
4647 public enum Status : byte { ASSIGNED = 1, USED = 2 }
4649 static string[] attribute_targets = new string [] { "field" };
4652 // The constructor is only exposed to our children
4654 protected FieldBase (Expression type, int mod, int allowed_mod, MemberName name,
4655 object init, Attributes attrs, Location loc)
4656 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
4661 public override AttributeTargets AttributeTargets {
4663 return AttributeTargets.Field;
4667 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4669 if (a.Type == TypeManager.marshal_as_attr_type) {
4670 UnmanagedMarshal marshal = a.GetMarshal ();
4671 if (marshal != null) {
4672 FieldBuilder.SetMarshal (marshal);
4675 Report.Warning_T (-24, a.Location);
4680 FieldBuilder.SetCustomAttribute (cb);
4684 // Whether this field has an initializer.
4686 public bool HasInitializer {
4688 return init != null;
4692 protected readonly Object init;
4694 Expression init_expr;
4695 bool init_expr_initialized = false;
4697 protected override bool CheckGenericOverride (MethodInfo method, string name)
4703 // Resolves and returns the field initializer.
4705 public Expression GetInitializerExpression (EmitContext ec)
4707 if (init_expr_initialized)
4711 if (init is Expression)
4712 e = (Expression) init;
4714 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
4716 ec.IsFieldInitializer = true;
4717 e = e.DoResolve (ec);
4718 ec.IsFieldInitializer = false;
4721 init_expr_initialized = true;
4726 protected override bool DoDefine (DeclSpace ds, TypeContainer container)
4728 if (!base.DoDefine (ds, container))
4731 if (MemberType == TypeManager.void_type) {
4732 Report.Error (1547, Location,
4733 "Keyword 'void' cannot be used in this context");
4740 public override string GetSignatureForError ()
4742 return TypeManager.GetFullNameSignature (FieldBuilder);
4745 protected override string[] ValidAttributeTargets {
4747 return attribute_targets;
4751 protected override bool VerifyClsCompliance (DeclSpace ds)
4753 if (!base.VerifyClsCompliance (ds))
4756 if (FieldBuilder == null) {
4760 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
4761 Report.Error_T (3003, Location, GetSignatureForError ());
4767 public void SetAssigned ()
4769 status |= Status.ASSIGNED;
4774 // The Field class is used to represents class/struct fields during parsing.
4776 public class Field : FieldBase {
4778 // Modifiers allowed in a class declaration
4780 const int AllowedModifiers =
4783 Modifiers.PROTECTED |
4784 Modifiers.INTERNAL |
4787 Modifiers.VOLATILE |
4791 public Field (Expression type, int mod, string name, Object expr_or_array_init,
4792 Attributes attrs, Location loc)
4793 : base (type, mod, AllowedModifiers, new MemberName (name),
4794 expr_or_array_init, attrs, loc)
4798 public override bool Define (TypeContainer container)
4800 Type t = container.ResolveType (Type, false, Location);
4805 CheckBase (container);
4807 if (!container.AsAccessible (t, ModFlags)) {
4808 Report.Error (52, Location,
4809 "Inconsistent accessibility: field type `" +
4810 TypeManager.CSharpName (t) + "' is less " +
4811 "accessible than field `" + Name + "'");
4815 if (t.IsPointer && !UnsafeOK (container))
4818 if (RootContext.WarningLevel > 1){
4819 Type ptype = container.TypeBuilder.BaseType;
4821 // ptype is only null for System.Object while compiling corlib.
4823 TypeContainer.FindMembers (
4824 ptype, MemberTypes.Method,
4825 BindingFlags.Public |
4826 BindingFlags.Static | BindingFlags.Instance,
4827 System.Type.FilterName, Name);
4831 if ((ModFlags & Modifiers.VOLATILE) != 0){
4835 if (TypeManager.IsEnumType (vt))
4836 vt = TypeManager.EnumToUnderlying (t);
4838 if (!((vt == TypeManager.bool_type) ||
4839 (vt == TypeManager.sbyte_type) ||
4840 (vt == TypeManager.byte_type) ||
4841 (vt == TypeManager.short_type) ||
4842 (vt == TypeManager.ushort_type) ||
4843 (vt == TypeManager.int32_type) ||
4844 (vt == TypeManager.uint32_type) ||
4845 (vt == TypeManager.char_type) ||
4846 (vt == TypeManager.float_type) ||
4847 (!vt.IsValueType))){
4849 677, Location, container.MakeName (Name) +
4850 " A volatile field can not be of type `" +
4851 TypeManager.CSharpName (vt) + "'");
4856 if ((ModFlags & Modifiers.READONLY) != 0){
4859 "A field can not be both volatile and readonly");
4864 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
4866 if (container is Struct &&
4867 ((fa & FieldAttributes.Static) == 0) &&
4868 t == container.TypeBuilder &&
4869 !TypeManager.IsBuiltinType (t)){
4870 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
4871 "' causes a cycle in the structure layout");
4876 FieldBuilder = container.TypeBuilder.DefineField (
4877 Name, t, Modifiers.FieldAttr (ModFlags));
4879 TypeManager.RegisterFieldBase (FieldBuilder, this);
4881 catch (ArgumentException) {
4882 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
4889 public override void Emit (TypeContainer tc)
4891 if (OptAttributes != null) {
4892 EmitContext ec = new EmitContext (tc, Location, null, FieldBuilder.FieldType, ModFlags);
4893 OptAttributes.Emit (ec, this);
4901 // `set' and `get' accessors are represented with an Accessor.
4903 public class Accessor {
4905 // Null if the accessor is empty, or a Block if not
4908 public Attributes Attributes;
4910 public Accessor (Block b, Attributes attrs)
4918 // Properties and Indexers both generate PropertyBuilders, we use this to share
4919 // their common bits.
4921 abstract public class PropertyBase : MethodCore {
4923 public class GetMethod: PropertyMethod
4925 static string[] attribute_targets = new string [] { "method", "return" };
4927 public GetMethod (MethodCore method, Accessor accessor):
4928 base (method, accessor)
4932 public override MethodBuilder Define(TypeContainer container)
4934 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, false, this);
4936 if (!method_data.Define (container))
4939 return method_data.MethodBuilder;
4942 public override string MethodName {
4944 return "get_" + method.ShortName;
4948 public override Type ReturnType {
4950 return method.MemberType;
4954 protected override string[] ValidAttributeTargets {
4956 return attribute_targets;
4961 public class SetMethod: PropertyMethod {
4963 static string[] attribute_targets = new string [] { "method", "param", "return" };
4964 ImplicitParameter param_attr;
4966 public SetMethod (MethodCore method, Accessor accessor):
4967 base (method, accessor)
4971 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4973 if (a.Target == "param") {
4974 if (param_attr == null)
4975 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4977 param_attr.ApplyAttributeBuilder (a, cb);
4981 base.ApplyAttributeBuilder (a, cb);
4984 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
4986 Parameter [] parms = new Parameter [1];
4987 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
4988 return new InternalParameters (
4989 container, new Parameters (parms, null, method.Location));
4992 public override MethodBuilder Define(TypeContainer container)
4994 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, false, this);
4996 if (!method_data.Define (container))
4999 return method_data.MethodBuilder;
5002 public override string MethodName {
5004 return "set_" + method.ShortName;
5008 public override Type[] ParameterTypes {
5010 return new Type[] { method.MemberType };
5014 public override Type ReturnType {
5016 return TypeManager.void_type;
5020 protected override string[] ValidAttributeTargets {
5022 return attribute_targets;
5027 static string[] attribute_targets = new string [] { "property" };
5029 public abstract class PropertyMethod: Attributable, IMethodData {
5030 protected readonly MethodCore method;
5031 protected MethodData method_data;
5034 ReturnParameter return_attributes;
5036 public PropertyMethod (MethodCore method, Accessor accessor):
5037 base (accessor.Attributes)
5039 this.method = method;
5040 this.block = accessor.Block;
5043 public override AttributeTargets AttributeTargets {
5045 return AttributeTargets.Method | AttributeTargets.ReturnValue;
5049 public override bool IsClsCompliaceRequired(DeclSpace ds)
5051 return method.IsClsCompliaceRequired (ds);
5054 public InternalParameters ParameterInfo
5057 return method_data.ParameterInfo;
5061 #region IMethodData Members
5063 public Block Block {
5069 public CallingConventions CallingConventions {
5071 return CallingConventions.Standard;
5075 public abstract MethodBuilder Define (TypeContainer container);
5077 public void Emit (TypeContainer container)
5079 method_data.Emit (container, this);
5084 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5086 if (a.Target == "return") {
5087 if (return_attributes == null)
5088 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5090 return_attributes.ApplyAttributeBuilder (a, cb);
5094 method_data.MethodBuilder.SetCustomAttribute (cb);
5097 public virtual Type[] ParameterTypes {
5099 return TypeManager.NoTypes;
5103 public abstract Type ReturnType { get; }
5105 public Location Location {
5107 return method.Location;
5111 public abstract string MethodName { get; }
5113 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5115 return new EmitContext (tc, method.ds, method.Location, ig, ReturnType, method.ModFlags, false);
5121 public PropertyMethod Get, Set;
5122 public PropertyBuilder PropertyBuilder;
5123 public MethodBuilder GetBuilder, SetBuilder;
5125 protected EmitContext ec;
5127 public PropertyBase (DeclSpace ds, Expression type, int mod_flags,
5128 int allowed_mod, bool is_iface, MemberName name,
5129 Parameters parameters, Attributes attrs,
5131 : base (ds, type, mod_flags, allowed_mod, is_iface, name,
5132 attrs, parameters, loc)
5136 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5138 PropertyBuilder.SetCustomAttribute (cb);
5141 public override AttributeTargets AttributeTargets {
5143 return AttributeTargets.Property;
5147 protected override bool DoDefine (DeclSpace decl, TypeContainer container)
5149 if (!base.DoDefine (decl, container))
5152 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
5157 public override string GetSignatureForError()
5159 return TypeManager.CSharpSignature (PropertyBuilder, false);
5162 protected virtual string RealMethodName {
5168 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5170 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5173 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5176 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5184 // Checks our base implementation if any
5186 protected override bool CheckBase (TypeContainer container)
5188 base.CheckBase (container);
5190 // Check whether arguments were correct.
5191 if (!DoDefineParameters ())
5198 // Check in our class for dups
5200 ArrayList ar = container.Properties;
5202 int arLen = ar.Count;
5204 for (int i = 0; i < arLen; i++) {
5205 Property m = (Property) ar [i];
5206 if (IsDuplicateImplementation (container, m))
5215 MethodSignature ms, base_ms;
5216 if (this is Indexer) {
5217 string name, base_name;
5219 report_name = "this";
5220 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
5221 ms = new MethodSignature (name, null, ParameterTypes);
5222 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
5223 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5226 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5230 // Verify if the parent has a type with the same name, and then
5231 // check whether we have to create a new slot for it or not.
5233 Type ptype = container.TypeBuilder.BaseType;
5235 // ptype is only null for System.Object while compiling corlib.
5236 if (ptype == null) {
5237 if ((ModFlags & Modifiers.NEW) != 0)
5238 WarningNotHiding (container);
5243 MemberInfo parent_member = null;
5246 // Explicit implementations do not have `parent' methods, however,
5247 // the member cache stores them there. Without this check, we get
5248 // an incorrect warning in corlib.
5250 if (! IsExplicitImpl) {
5251 parent_member = ((IMemberContainer)container).Parent.MemberCache.FindMemberToOverride (
5252 container.TypeBuilder, Name, ParameterTypes, true);
5255 if (parent_member is PropertyInfo) {
5256 PropertyInfo parent_property = (PropertyInfo)parent_member;
5258 string name = parent_property.DeclaringType.Name + "." +
5259 parent_property.Name;
5261 MethodInfo get, set, parent_method;
5262 get = parent_property.GetGetMethod (true);
5263 set = parent_property.GetSetMethod (true);
5266 parent_method = get;
5267 else if (set != null)
5268 parent_method = set;
5270 throw new Exception ("Internal error!");
5272 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
5275 if ((ModFlags & Modifiers.NEW) == 0) {
5276 Type parent_type = TypeManager.TypeToCoreType (
5277 parent_property.PropertyType);
5279 if (parent_type != MemberType) {
5281 508, Location, container.MakeName (Name) + ": cannot " +
5282 "change return type when overriding " +
5283 "inherited member " + name);
5287 } else if (parent_member == null){
5288 if ((ModFlags & Modifiers.NEW) != 0)
5289 WarningNotHiding (container);
5291 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5292 if (this is Indexer)
5293 Report.Error (115, Location,
5294 container.MakeName (Name) +
5295 " no suitable indexers found to override");
5297 Report.Error (115, Location,
5298 container.MakeName (Name) +
5299 " no suitable properties found to override");
5306 public override void Emit (TypeContainer tc)
5309 // The PropertyBuilder can be null for explicit implementations, in that
5310 // case, we do not actually emit the ".property", so there is nowhere to
5311 // put the attribute
5313 if (PropertyBuilder != null && OptAttributes != null)
5314 OptAttributes.Emit (ec, this);
5325 protected override string[] ValidAttributeTargets {
5327 return attribute_targets;
5332 public class Property : PropertyBase, IIteratorContainer {
5333 const int AllowedModifiers =
5336 Modifiers.PROTECTED |
5337 Modifiers.INTERNAL |
5341 Modifiers.OVERRIDE |
5342 Modifiers.ABSTRACT |
5345 Modifiers.METHOD_YIELDS |
5348 const int AllowedInterfaceModifiers =
5351 public Property (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5352 MemberName name, Attributes attrs, Accessor get_block,
5353 Accessor set_block, Location loc)
5354 : base (ds, type, mod_flags,
5355 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5356 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
5359 if (get_block != null)
5360 Get = new GetMethod (this, get_block);
5362 if (set_block != null)
5363 Set = new SetMethod (this, set_block);
5366 public override bool Define (TypeContainer container)
5368 if (!DoDefine (container, container))
5371 if (!CheckBase (container))
5374 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5378 GetBuilder = Get.Define (container);
5379 if (GetBuilder == null)
5383 // Setup iterator if we are one
5385 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
5386 IteratorHandler ih = new IteratorHandler (
5387 "get", container, MemberType,
5388 TypeManager.NoTypes, Get.ParameterInfo, ModFlags, Location);
5390 Block new_block = ih.Setup (block);
5391 if (new_block == null)
5398 SetBuilder = Set.Define (container);
5399 if (SetBuilder == null)
5402 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
5405 // FIXME - PropertyAttributes.HasDefault ?
5407 PropertyAttributes prop_attr = PropertyAttributes.None;
5409 prop_attr |= PropertyAttributes.RTSpecialName |
5410 PropertyAttributes.SpecialName;
5412 if (!IsExplicitImpl){
5413 PropertyBuilder = container.TypeBuilder.DefineProperty (
5414 Name, prop_attr, MemberType, null);
5417 PropertyBuilder.SetGetMethod (GetBuilder);
5420 PropertyBuilder.SetSetMethod (SetBuilder);
5423 // HACK for the reasons exposed above
5425 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
5428 "Class `" + container.Name +
5429 "' already contains a definition for the property `" +
5437 public void SetYields ()
5439 ModFlags |= Modifiers.METHOD_YIELDS;
5444 /// Gigantic workaround for lameness in SRE follows :
5445 /// This class derives from EventInfo and attempts to basically
5446 /// wrap around the EventBuilder so that FindMembers can quickly
5447 /// return this in it search for members
5449 public class MyEventBuilder : EventInfo {
5452 // We use this to "point" to our Builder which is
5453 // not really a MemberInfo
5455 EventBuilder MyBuilder;
5458 // We "catch" and wrap these methods
5460 MethodInfo raise, remove, add;
5462 EventAttributes attributes;
5463 Type declaring_type, reflected_type, event_type;
5468 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
5470 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
5472 // And now store the values in our own fields.
5474 declaring_type = type_builder;
5476 reflected_type = type_builder;
5478 attributes = event_attr;
5481 this.event_type = event_type;
5485 // Methods that you have to override. Note that you only need
5486 // to "implement" the variants that take the argument (those are
5487 // the "abstract" methods, the others (GetAddMethod()) are
5490 public override MethodInfo GetAddMethod (bool nonPublic)
5495 public override MethodInfo GetRemoveMethod (bool nonPublic)
5500 public override MethodInfo GetRaiseMethod (bool nonPublic)
5506 // These methods make "MyEventInfo" look like a Builder
5508 public void SetRaiseMethod (MethodBuilder raiseMethod)
5510 raise = raiseMethod;
5511 MyBuilder.SetRaiseMethod (raiseMethod);
5514 public void SetRemoveOnMethod (MethodBuilder removeMethod)
5516 remove = removeMethod;
5517 MyBuilder.SetRemoveOnMethod (removeMethod);
5520 public void SetAddOnMethod (MethodBuilder addMethod)
5523 MyBuilder.SetAddOnMethod (addMethod);
5526 public void SetCustomAttribute (CustomAttributeBuilder cb)
5528 MyBuilder.SetCustomAttribute (cb);
5531 public override object [] GetCustomAttributes (bool inherit)
5533 // FIXME : There's nothing which can be seemingly done here because
5534 // we have no way of getting at the custom attribute objects of the
5539 public override object [] GetCustomAttributes (Type t, bool inherit)
5541 // FIXME : Same here !
5545 public override bool IsDefined (Type t, bool b)
5550 public override EventAttributes Attributes {
5556 public override string Name {
5562 public override Type DeclaringType {
5564 return declaring_type;
5568 public override Type ReflectedType {
5570 return reflected_type;
5574 public Type EventType {
5580 public void SetUsed ()
5582 if (my_event != null)
5583 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
5588 /// For case when event is declared like property (with add and remove accessors).
5590 public class EventProperty: Event {
5592 static string[] attribute_targets = new string [] { "event", "property" };
5594 public EventProperty (DeclSpace ds, Expression type, int mod_flags,
5595 bool is_iface, MemberName name, Object init,
5596 Attributes attrs, Accessor add, Accessor remove,
5598 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5600 Add = new AddDelegateMethod (this, add);
5601 Remove = new RemoveDelegateMethod (this, remove);
5604 protected override string[] ValidAttributeTargets {
5606 return attribute_targets;
5612 /// Event is declared like field.
5614 public class EventField: Event {
5616 static string[] attribute_targets = new string [] { "method", "field", "event" };
5618 public EventField (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5619 MemberName name, Object init, Attributes attrs, Location loc)
5620 : base (ds, type, mod_flags, is_iface, name, init, attrs, loc)
5622 Add = new AddDelegateMethod (this);
5623 Remove = new RemoveDelegateMethod (this);
5626 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5628 if (a.Target == "field") {
5629 FieldBuilder.SetCustomAttribute (cb);
5633 if (a.Target == "method") {
5634 AddBuilder.SetCustomAttribute (cb);
5635 RemoveBuilder.SetCustomAttribute (cb);
5639 base.ApplyAttributeBuilder (a, cb);
5642 protected override string[] ValidAttributeTargets {
5644 return attribute_targets;
5649 public abstract class Event : FieldBase {
5651 protected sealed class AddDelegateMethod: DelegateMethod
5653 public AddDelegateMethod (Event method):
5658 public AddDelegateMethod (Event method, Accessor accessor):
5659 base (method, accessor)
5663 public override string MethodName {
5665 return "add_" + method.ShortName;
5669 protected override MethodInfo DelegateMethodInfo {
5671 return TypeManager.delegate_remove_delegate_delegate;
5677 protected sealed class RemoveDelegateMethod: DelegateMethod
5679 public RemoveDelegateMethod (Event method):
5684 public RemoveDelegateMethod (Event method, Accessor accessor):
5685 base (method, accessor)
5689 public override string MethodName {
5691 return "remove_" + method.ShortName;
5695 protected override MethodInfo DelegateMethodInfo {
5697 return TypeManager.delegate_combine_delegate_delegate;
5703 public abstract class DelegateMethod: Attributable, IMethodData
5705 protected readonly Event method;
5706 protected MethodData method_data;
5708 ReturnParameter return_attributes;
5709 ImplicitParameter param_attr;
5711 static string[] attribute_targets = new string [] { "method", "param", "return" };
5713 public DelegateMethod (Event method):
5716 this.method = method;
5719 public DelegateMethod (Event method, Accessor accessor):
5720 base (accessor.Attributes)
5722 this.method = method;
5723 this.block = accessor.Block;
5726 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5728 if (a.Target == "return") {
5729 if (return_attributes == null)
5730 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5732 return_attributes.ApplyAttributeBuilder (a, cb);
5736 if (a.Target == "param") {
5737 if (param_attr == null)
5738 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5740 param_attr.ApplyAttributeBuilder (a, cb);
5744 method_data.MethodBuilder.SetCustomAttribute (cb);
5747 public override AttributeTargets AttributeTargets {
5749 return AttributeTargets.Method;
5753 public override bool IsClsCompliaceRequired(DeclSpace ds)
5755 return method.IsClsCompliaceRequired (ds);
5758 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
5760 method_data = new MethodData (method, ip, method.ModFlags,
5761 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, false, this);
5763 if (!method_data.Define (container))
5766 MethodBuilder mb = method_data.MethodBuilder;
5767 mb.DefineParameter (1, ParameterAttributes.None, "value");
5771 #region IMethodData Members
5773 public Block Block {
5779 public CallingConventions CallingConventions {
5781 return CallingConventions.Standard;
5785 public void Emit (TypeContainer tc)
5787 if (block != null) {
5788 method_data.Emit (tc, this);
5793 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
5794 EmitContext ec = CreateEmitContext (tc, ig);
5795 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
5797 if ((method.ModFlags & Modifiers.STATIC) != 0) {
5798 ig.Emit (OpCodes.Ldsfld, field_info);
5799 ig.Emit (OpCodes.Ldarg_0);
5800 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5801 ig.Emit (OpCodes.Castclass, method.MemberType);
5802 ig.Emit (OpCodes.Stsfld, field_info);
5804 ig.Emit (OpCodes.Ldarg_0);
5805 ig.Emit (OpCodes.Ldarg_0);
5806 ig.Emit (OpCodes.Ldfld, field_info);
5807 ig.Emit (OpCodes.Ldarg_1);
5808 ig.Emit (OpCodes.Call, DelegateMethodInfo);
5809 ig.Emit (OpCodes.Castclass, method.MemberType);
5810 ig.Emit (OpCodes.Stfld, field_info);
5812 ig.Emit (OpCodes.Ret);
5815 protected abstract MethodInfo DelegateMethodInfo { get; }
5817 public Type[] ParameterTypes {
5819 return new Type[] { method.MemberType };
5823 public Type ReturnType {
5825 return TypeManager.void_type;
5829 public Location Location {
5831 return method.Location;
5835 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
5837 return new EmitContext (tc, method.ds, Location, ig, ReturnType, method.ModFlags, false);
5840 public abstract string MethodName { get; }
5844 protected override string[] ValidAttributeTargets {
5846 return attribute_targets;
5852 const int AllowedModifiers =
5855 Modifiers.PROTECTED |
5856 Modifiers.INTERNAL |
5861 Modifiers.OVERRIDE |
5865 const int AllowedInterfaceModifiers =
5868 protected DelegateMethod Add, Remove;
5869 public MyEventBuilder EventBuilder;
5870 public MethodBuilder AddBuilder, RemoveBuilder;
5871 public DeclSpace ds;
5873 MethodData AddData, RemoveData;
5875 public Event (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
5876 MemberName name, Object init, Attributes attrs, Location loc)
5877 : base (type, mod_flags,
5878 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
5879 name, init, attrs, loc)
5881 IsInterface = is_iface;
5885 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5887 EventBuilder.SetCustomAttribute (cb);
5890 public override AttributeTargets AttributeTargets {
5892 return AttributeTargets.Event;
5896 public override bool Define (TypeContainer container)
5898 EventAttributes e_attr;
5900 e_attr = EventAttributes.None;
5902 e_attr = EventAttributes.RTSpecialName |
5903 EventAttributes.SpecialName;
5905 if (!DoDefine (container, container))
5908 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
5909 Report.Error (74, Location, "'" + container.Name + "." + Name +
5910 "': abstract event can not have an initializer");
5914 if (!TypeManager.IsDelegateType (MemberType)) {
5915 Report.Error (66, Location, "'" + container.Name + "." + Name +
5916 "' : event must be of a delegate type");
5920 Parameter [] parms = new Parameter [1];
5921 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
5922 InternalParameters ip = new InternalParameters (
5923 container, new Parameters (parms, null, Location));
5925 if (!CheckBase (container))
5929 // Now define the accessors
5932 AddBuilder = Add.Define (container, ip);
5933 if (AddBuilder == null)
5936 RemoveBuilder = Remove.Define (container, ip);
5937 if (RemoveBuilder == null)
5940 if (!IsExplicitImpl){
5941 EventBuilder = new MyEventBuilder (this,
5942 container.TypeBuilder, Name, e_attr, MemberType);
5944 if (Add.Block == null && Remove.Block == null &&
5946 FieldBuilder = container.TypeBuilder.DefineField (
5948 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
5949 TypeManager.RegisterPrivateFieldOfEvent (
5950 (EventInfo) EventBuilder, FieldBuilder);
5951 TypeManager.RegisterFieldBase (FieldBuilder, this);
5954 EventBuilder.SetAddOnMethod (AddBuilder);
5955 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
5957 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
5958 Report.Error (111, Location,
5959 "Class `" + container.Name +
5960 "' already contains a definition for the event `" +
5969 public override void Emit (TypeContainer tc)
5971 if (OptAttributes != null) {
5972 EmitContext ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
5973 OptAttributes.Emit (ec, this);
5986 // FIXME: This does not handle:
5988 // int INTERFACENAME [ args ]
5993 // int this [ args ]
5995 public class Indexer : PropertyBase {
5997 class GetIndexerMethod: GetMethod
5999 public GetIndexerMethod (MethodCore method, Accessor accessor):
6000 base (method, accessor)
6004 public override Type[] ParameterTypes {
6006 return method.ParameterTypes;
6011 class SetIndexerMethod: SetMethod
6013 readonly Parameters parameters;
6015 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
6016 base (method, accessor)
6018 this.parameters = parameters;
6021 public override Type[] ParameterTypes {
6023 int top = method.ParameterTypes.Length;
6024 Type [] set_pars = new Type [top + 1];
6025 method.ParameterTypes.CopyTo (set_pars, 0);
6026 set_pars [top] = method.MemberType;
6031 protected override InternalParameters GetParameterInfo (TypeContainer container)
6033 Parameter [] fixed_parms = parameters.FixedParameters;
6035 if (fixed_parms == null){
6036 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
6037 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6038 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6040 // Here is the problem: the `value' parameter has
6041 // to come *after* the array parameter in the declaration
6043 // X (object [] x, Type value)
6046 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6047 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6051 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
6053 fixed_parms.CopyTo (tmp, 0);
6054 tmp [fixed_parms.Length] = new Parameter (
6055 method.Type, "value", Parameter.Modifier.NONE, null);
6057 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
6059 return new InternalParameters (container, set_formal_params);
6065 const int AllowedModifiers =
6068 Modifiers.PROTECTED |
6069 Modifiers.INTERNAL |
6073 Modifiers.OVERRIDE |
6078 const int AllowedInterfaceModifiers =
6081 public string IndexerName;
6082 public string InterfaceIndexerName;
6085 // Are we implementing an interface ?
6087 public Indexer (DeclSpace ds, Expression type, int mod_flags, bool is_iface,
6088 MemberName name, Parameters parameters, Attributes attrs,
6089 Accessor get_block, Accessor set_block, Location loc)
6090 : base (ds, type, mod_flags,
6091 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6092 is_iface, name, parameters, attrs, loc)
6094 if (get_block != null)
6095 Get = new GetIndexerMethod (this, get_block);
6097 if (set_block != null)
6098 Set = new SetIndexerMethod (this, parameters, set_block);
6101 public override bool Define (TypeContainer container)
6103 PropertyAttributes prop_attr =
6104 PropertyAttributes.RTSpecialName |
6105 PropertyAttributes.SpecialName;
6107 if (!DoDefine (container, container))
6110 if (OptAttributes != null)
6111 IndexerName = OptAttributes.ScanForIndexerName (ec);
6113 if (IndexerName == null)
6114 IndexerName = "Item";
6116 if (! Tokenizer.IsValidIdentifier (IndexerName)) {
6117 Report.Error (633, Location, "The IndexerName specified is an invalid identifier");
6121 if (IsExplicitImpl) {
6122 Report.Error (592, Location,
6123 "Attribute 'IndexerName' is not valid on explicit implementations.");
6128 ShortName = IndexerName;
6129 if (IsExplicitImpl) {
6130 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6131 Name = InterfaceType.FullName + "." + IndexerName;
6133 InterfaceIndexerName = IndexerName;
6137 if (!CheckNameCollision (container))
6140 if (!CheckBase (container))
6143 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6145 GetBuilder = Get.Define (container);
6146 if (GetBuilder == null)
6151 SetBuilder = Set.Define (container);
6152 if (SetBuilder == null)
6157 // Now name the parameters
6159 Parameter [] p = Parameters.FixedParameters;
6163 for (i = 0; i < p.Length; ++i) {
6165 GetBuilder.DefineParameter (
6166 i + 1, p [i].Attributes, p [i].Name);
6169 SetBuilder.DefineParameter (
6170 i + 1, p [i].Attributes, p [i].Name);
6174 SetBuilder.DefineParameter (
6175 i + 1, ParameterAttributes.None, "value");
6177 if (i != ParameterTypes.Length) {
6178 Parameter array_param = Parameters.ArrayParameter;
6180 SetBuilder.DefineParameter (
6181 i + 1, array_param.Attributes, array_param.Name);
6186 // Define the PropertyBuilder if one of the following conditions are met:
6187 // a) we're not implementing an interface indexer.
6188 // b) the indexer has a different IndexerName and this is no
6189 // explicit interface implementation.
6191 if (!IsExplicitImpl) {
6192 PropertyBuilder = container.TypeBuilder.DefineProperty (
6193 IndexerName, prop_attr, MemberType, ParameterTypes);
6196 PropertyBuilder.SetGetMethod (GetBuilder);
6199 PropertyBuilder.SetSetMethod (SetBuilder);
6201 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6208 bool CheckNameCollision (TypeContainer container) {
6209 switch (VerifyName (container)){
6210 case DeclSpace.AdditionResult.NameExists:
6211 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6214 case DeclSpace.AdditionResult.Success:
6217 throw new NotImplementedException ();
6220 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6221 if (!AddIndexer (container, container.Name + "." + Name))
6222 return DeclSpace.AdditionResult.NameExists;
6225 if (!AddIndexer (container, container.Name + ".get_" + Name))
6226 return DeclSpace.AdditionResult.NameExists;
6230 if (!AddIndexer (container, container.Name + ".set_" + Name))
6231 return DeclSpace.AdditionResult.NameExists;
6233 return DeclSpace.AdditionResult.Success;
6236 bool AddIndexer (TypeContainer container, string fullname)
6238 object value = container.GetDefinition (fullname);
6240 if (value != null) {
6241 return value.GetType () != GetType () ? false : true;
6244 container.DefineName (fullname, this);
6248 public override string GetSignatureForError ()
6250 return TypeManager.CSharpSignature (PropertyBuilder, true);
6253 protected override string RealMethodName {
6260 public class Operator : MemberBase, IIteratorContainer {
6262 const int AllowedModifiers =
6268 const int RequiredModifiers =
6272 public enum OpType : byte {
6282 // Unary and Binary operators
6305 // Implicit and Explicit
6310 public readonly OpType OperatorType;
6311 public readonly Expression ReturnType;
6312 public readonly Expression FirstArgType, SecondArgType;
6313 public readonly string FirstArgName, SecondArgName;
6315 public MethodBuilder OperatorMethodBuilder;
6317 public string MethodName;
6318 public Method OperatorMethod;
6320 static string[] attribute_targets = new string [] { "param" };
6322 public Operator (OpType type, Expression ret_type, int mod_flags,
6323 Expression arg1type, string arg1name,
6324 Expression arg2type, string arg2name,
6325 Block block, Attributes attrs, Location loc)
6326 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC,
6327 MemberName.Null, attrs, loc)
6329 OperatorType = type;
6330 Name = "op_" + OperatorType;
6331 ReturnType = ret_type;
6332 FirstArgType = arg1type;
6333 FirstArgName = arg1name;
6334 SecondArgType = arg2type;
6335 SecondArgName = arg2name;
6339 string Prototype (TypeContainer container)
6341 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
6342 SecondArgType + ")";
6345 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6347 OperatorMethod.ApplyAttributeBuilder (a, cb);
6350 public override AttributeTargets AttributeTargets {
6352 return AttributeTargets.Method;
6356 protected override bool CheckGenericOverride (MethodInfo method, string name)
6361 public override bool Define (TypeContainer container)
6364 MethodName = "op_" + OperatorType;
6366 if (SecondArgType != null)
6369 Parameter [] param_list = new Parameter [length];
6371 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
6374 "User defined operators `" +
6375 Prototype (container) +
6376 "' must be declared static and public");
6380 param_list[0] = new Parameter (FirstArgType, FirstArgName,
6381 Parameter.Modifier.NONE, null);
6382 if (SecondArgType != null)
6383 param_list[1] = new Parameter (SecondArgType, SecondArgName,
6384 Parameter.Modifier.NONE, null);
6386 OperatorMethod = new Method (
6387 container, ReturnType, ModFlags, false,
6388 new MemberName (MethodName),
6389 new Parameters (param_list, null, Location),
6390 OptAttributes, Location);
6392 OperatorMethod.Block = Block;
6393 OperatorMethod.IsOperator = true;
6394 OperatorMethod.Define (container);
6396 if (OperatorMethod.MethodBuilder == null)
6399 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
6401 Type [] param_types = OperatorMethod.ParameterTypes;
6402 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
6403 Type return_type = OperatorMethod.GetReturnType ();
6404 Type first_arg_type = param_types [0];
6406 // Rules for conversion operators
6408 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
6409 if (first_arg_type == return_type && first_arg_type == declaring_type){
6412 "User-defined conversion cannot take an object of the " +
6413 "enclosing type and convert to an object of the enclosing" +
6418 if (first_arg_type != declaring_type && return_type != declaring_type){
6421 "User-defined conversion must convert to or from the " +
6426 if (first_arg_type == TypeManager.object_type ||
6427 return_type == TypeManager.object_type){
6430 "User-defined conversion cannot convert to or from " +
6435 if (first_arg_type.IsInterface || return_type.IsInterface){
6438 "User-defined conversion cannot convert to or from an " +
6443 if (first_arg_type.IsSubclassOf (return_type) ||
6444 return_type.IsSubclassOf (first_arg_type)){
6447 "User-defined conversion cannot convert between types " +
6448 "that derive from each other");
6451 } else if (SecondArgType == null) {
6452 // Checks for Unary operators
6454 if (first_arg_type != declaring_type){
6457 "The parameter of a unary operator must be the " +
6462 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
6463 if (return_type != declaring_type){
6466 "The parameter and return type for ++ and -- " +
6467 "must be the containing type");
6473 if (OperatorType == OpType.True || OperatorType == OpType.False) {
6474 if (return_type != TypeManager.bool_type){
6477 "The return type of operator True or False " +
6484 // Checks for Binary operators
6486 if (first_arg_type != declaring_type &&
6487 param_types [1] != declaring_type){
6490 "One of the parameters of a binary operator must " +
6491 "be the containing type");
6499 public override void Emit (TypeContainer container)
6502 // abstract or extern methods have no bodies
6504 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
6507 OperatorMethod.Emit (container);
6511 public static string GetName (OpType ot)
6514 case OpType.LogicalNot:
6516 case OpType.OnesComplement:
6518 case OpType.Increment:
6520 case OpType.Decrement:
6526 case OpType.Addition:
6528 case OpType.Subtraction:
6530 case OpType.UnaryPlus:
6532 case OpType.UnaryNegation:
6534 case OpType.Multiply:
6536 case OpType.Division:
6538 case OpType.Modulus:
6540 case OpType.BitwiseAnd:
6542 case OpType.BitwiseOr:
6544 case OpType.ExclusiveOr:
6546 case OpType.LeftShift:
6548 case OpType.RightShift:
6550 case OpType.Equality:
6552 case OpType.Inequality:
6554 case OpType.GreaterThan:
6556 case OpType.LessThan:
6558 case OpType.GreaterThanOrEqual:
6560 case OpType.LessThanOrEqual:
6562 case OpType.Implicit:
6564 case OpType.Explicit:
6570 public override string ToString ()
6572 Type return_type = OperatorMethod.GetReturnType();
6573 Type [] param_types = OperatorMethod.ParameterTypes;
6575 if (SecondArgType == null)
6576 return String.Format (
6577 "{0} operator {1}({2})",
6578 TypeManager.CSharpName (return_type),
6579 GetName (OperatorType),
6582 return String.Format (
6583 "{0} operator {1}({2}, {3})",
6584 TypeManager.CSharpName (return_type),
6585 GetName (OperatorType),
6586 param_types [0], param_types [1]);
6589 protected override string[] ValidAttributeTargets {
6591 return attribute_targets;
6595 public void SetYields ()
6597 ModFlags |= Modifiers.METHOD_YIELDS;
6602 // This is used to compare method signatures
6604 struct MethodSignature {
6606 public Type RetType;
6607 public Type [] Parameters;
6610 /// This delegate is used to extract methods which have the
6611 /// same signature as the argument
6613 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
6615 public MethodSignature (string name, Type ret_type, Type [] parameters)
6620 if (parameters == null)
6621 Parameters = TypeManager.NoTypes;
6623 Parameters = parameters;
6626 public override string ToString ()
6629 if (Parameters.Length != 0){
6630 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
6631 for (int i = 0; i < Parameters.Length; i++){
6632 sb.Append (Parameters [i]);
6633 if (i+1 < Parameters.Length)
6636 pars = sb.ToString ();
6639 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
6642 public override int GetHashCode ()
6644 return Name.GetHashCode ();
6647 public override bool Equals (Object o)
6649 MethodSignature other = (MethodSignature) o;
6651 if (other.Name != Name)
6654 if (other.RetType != RetType)
6657 if (Parameters == null){
6658 if (other.Parameters == null)
6663 if (other.Parameters == null)
6666 int c = Parameters.Length;
6667 if (other.Parameters.Length != c)
6670 for (int i = 0; i < c; i++)
6671 if (other.Parameters [i] != Parameters [i])
6677 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
6679 MethodSignature sig = (MethodSignature) filter_criteria;
6681 if (m.Name != sig.Name)
6685 MethodInfo mi = m as MethodInfo;
6686 PropertyInfo pi = m as PropertyInfo;
6689 ReturnType = mi.ReturnType;
6690 else if (pi != null)
6691 ReturnType = pi.PropertyType;
6696 // we use sig.RetType == null to mean `do not check the
6697 // method return value.
6699 if (sig.RetType != null)
6700 if (ReturnType != sig.RetType)
6705 args = TypeManager.GetArgumentTypes (mi);
6707 args = TypeManager.GetArgumentTypes (pi);
6708 Type [] sigp = sig.Parameters;
6710 if (args.Length != sigp.Length)
6713 for (int i = args.Length; i > 0; ){
6715 if (args [i] != sigp [i])