2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
7 // Licensed under the terms of the GNU GPL
9 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
12 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
14 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
15 // have fixed a remaining problem: not every AddXXXX was adding a
16 // fully qualified name.
18 // Now everyone registers a fully qualified name in the DeclSpace as
19 // being defined instead of the partial name.
21 // Downsides: we are slower than we need to be due to the excess
22 // copies and the names being registered this way.
24 // The reason for this is that we currently depend (on the corlib
25 // bootstrap for instance) that types are fully qualified, because
26 // we dump all the types in the namespace, and we should really have
27 // types inserted into the proper namespace, so we can only store the
28 // basenames in the defined_names array.
33 using System.Collections;
34 using System.Reflection;
35 using System.Reflection.Emit;
36 using System.Runtime.CompilerServices;
38 namespace Mono.CSharp {
41 /// This is the base class for structs and classes.
43 public class TypeContainer : DeclSpace, IMemberContainer {
44 // Holds a list of classes and structures
47 // Holds the list of properties
50 // Holds the list of enumerations
53 // Holds the list of delegates
56 // Holds the list of constructors
57 ArrayList instance_constructors;
59 // Holds the list of fields
62 // Holds a list of fields that have initializers
63 ArrayList initialized_fields;
65 // Holds a list of static fields that have initializers
66 ArrayList initialized_static_fields;
68 // Holds the list of constants
74 // Holds order in which interfaces must be closed
75 ArrayList interface_order;
86 // Holds the operators
89 // The emit context for toplevel objects.
93 // Pointers to the default constructor and the default static constructor
95 Constructor default_constructor;
96 Constructor default_static_constructor;
99 // Whether we have seen a static constructor for this class or not
101 bool have_static_constructor = false;
104 // Whether we have at least one non-static field
106 bool have_nonstatic_fields = false;
109 // This one is computed after we can distinguish interfaces
110 // from classes from the arraylist `type_bases'
112 string base_class_name;
114 ArrayList type_bases;
116 // Attributes for this type
117 protected Attributes attributes;
119 // Information in the case we are an attribute type
121 public AttributeTargets Targets = AttributeTargets.All;
122 public bool AllowMultiple = false;
123 public bool Inherited;
125 // The interfaces we implement.
128 // The parent member container and our member cache
129 IMemberContainer parent_container;
130 MemberCache member_cache;
133 // The indexer name for this class
135 public string IndexerName;
137 public TypeContainer (NamespaceEntry ns, TypeContainer parent, string name, Location l)
138 : base (ns, parent, name, l)
141 types = new ArrayList ();
148 base_class_name = null;
150 //Console.WriteLine ("New class " + name + " inside " + n);
153 public AdditionResult AddConstant (Const constant)
156 string basename = constant.Name;
157 string fullname = Name + "." + basename;
159 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
162 if (constants == null)
163 constants = new ArrayList ();
165 constants.Add (constant);
166 DefineName (fullname, constant);
168 return AdditionResult.Success;
171 public AdditionResult AddEnum (Mono.CSharp.Enum e)
175 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
179 enums = new ArrayList ();
182 DefineName (e.Name, e);
184 return AdditionResult.Success;
187 public AdditionResult AddClass (Class c)
190 string name = c.Basename;
192 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
195 DefineName (c.Name, c);
198 return AdditionResult.Success;
201 public AdditionResult AddStruct (Struct s)
204 string name = s.Basename;
206 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
209 DefineName (s.Name, s);
212 return AdditionResult.Success;
215 public AdditionResult AddDelegate (Delegate d)
218 string name = d.Basename;
220 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
223 if (delegates == null)
224 delegates = new ArrayList ();
226 DefineName (d.Name, d);
229 return AdditionResult.Success;
232 public AdditionResult AddMethod (Method method)
234 string basename = method.Name;
235 string fullname = Name + "." + basename;
237 Object value = defined_names [fullname];
239 if (value != null && (!(value is Method)))
240 return AdditionResult.NameExists;
242 if (basename == Basename)
243 return AdditionResult.EnclosingClash;
246 methods = new ArrayList ();
248 if (method.Name.IndexOf (".") != -1)
249 methods.Insert (0, method);
251 methods.Add (method);
254 DefineName (fullname, method);
256 return AdditionResult.Success;
259 public AdditionResult AddConstructor (Constructor c)
261 if (c.Name != Basename)
262 return AdditionResult.NotAConstructor;
264 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
267 have_static_constructor = true;
268 if (default_static_constructor != null){
269 Console.WriteLine ("I have a static constructor already");
270 Console.WriteLine (" " + default_static_constructor);
271 return AdditionResult.MethodExists;
274 default_static_constructor = c;
277 if (default_constructor != null)
278 return AdditionResult.MethodExists;
279 default_constructor = c;
282 if (instance_constructors == null)
283 instance_constructors = new ArrayList ();
285 instance_constructors.Add (c);
288 return AdditionResult.Success;
291 public AdditionResult AddInterface (Interface iface)
294 string name = iface.Basename;
296 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
299 if (interfaces == null)
300 interfaces = new ArrayList ();
301 interfaces.Add (iface);
302 DefineName (iface.Name, iface);
304 return AdditionResult.Success;
307 public AdditionResult AddField (Field field)
310 string basename = field.Name;
311 string fullname = Name + "." + basename;
313 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
317 fields = new ArrayList ();
321 if (field.HasInitializer){
322 if ((field.ModFlags & Modifiers.STATIC) != 0){
323 if (initialized_static_fields == null)
324 initialized_static_fields = new ArrayList ();
326 initialized_static_fields.Add (field);
329 // We have not seen a static constructor,
330 // but we will provide static initialization of fields
332 have_static_constructor = true;
334 if (initialized_fields == null)
335 initialized_fields = new ArrayList ();
337 initialized_fields.Add (field);
341 if ((field.ModFlags & Modifiers.STATIC) == 0)
342 have_nonstatic_fields = true;
344 DefineName (fullname, field);
345 return AdditionResult.Success;
348 public AdditionResult AddProperty (Property prop)
351 string basename = prop.Name;
352 string fullname = Name + "." + basename;
354 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
357 if (properties == null)
358 properties = new ArrayList ();
360 if (prop.Name.IndexOf (".") != -1)
361 properties.Insert (0, prop);
363 properties.Add (prop);
364 DefineName (fullname, prop);
366 return AdditionResult.Success;
369 public AdditionResult AddEvent (Event e)
372 string basename = e.Name;
373 string fullname = Name + "." + basename;
375 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
379 events = new ArrayList ();
382 DefineName (fullname, e);
384 return AdditionResult.Success;
387 public AdditionResult AddIndexer (Indexer i)
389 if (indexers == null)
390 indexers = new ArrayList ();
392 if (i.InterfaceType != null)
393 indexers.Insert (0, i);
397 return AdditionResult.Success;
400 public AdditionResult AddOperator (Operator op)
402 if (operators == null)
403 operators = new ArrayList ();
407 return AdditionResult.Success;
410 public void RegisterOrder (Interface iface)
412 if (interface_order == null)
413 interface_order = new ArrayList ();
415 interface_order.Add (iface);
418 public ArrayList Types {
424 public ArrayList Methods {
430 public ArrayList Constants {
436 public ArrayList Interfaces {
444 return base_class_name;
448 public ArrayList Bases {
458 public ArrayList Fields {
468 public ArrayList InstanceConstructors {
470 return instance_constructors;
474 public ArrayList Properties {
480 public ArrayList Events {
486 public ArrayList Enums {
492 public ArrayList Indexers {
498 public ArrayList Operators {
504 public ArrayList Delegates {
510 public Attributes OptAttributes {
516 public bool HaveStaticConstructor {
518 return have_static_constructor;
522 public virtual TypeAttributes TypeAttr {
524 return Modifiers.TypeAttr (ModFlags, this);
529 // Emits the instance field initializers
531 public bool EmitFieldInitializers (EmitContext ec)
534 ILGenerator ig = ec.ig;
535 Expression instance_expr;
538 fields = initialized_static_fields;
539 instance_expr = null;
541 fields = initialized_fields;
542 instance_expr = new This (Location.Null).Resolve (ec);
548 foreach (Field f in fields){
549 Expression e = f.GetInitializerExpression (ec);
553 Location l = f.Location;
554 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
555 fe.InstanceExpression = instance_expr;
556 ExpressionStatement a = new Assign (fe, e, l);
558 a = a.ResolveStatement (ec);
562 a.EmitStatement (ec);
569 // Defines the default constructors
571 void DefineDefaultConstructor (bool is_static)
576 c = new Constructor (this, Basename, Parameters.EmptyReadOnlyParameters,
577 new ConstructorBaseInitializer (
578 null, Parameters.EmptyReadOnlyParameters,
583 mods = Modifiers.STATIC;
589 c.Block = new Block (null);
593 public void ReportStructInitializedInstanceError ()
595 string n = TypeBuilder.FullName;
597 foreach (Field f in initialized_fields){
600 "`" + n + "." + f.Name + "': can not have " +
601 "instance field initializers in structs");
605 void Error_TypeParameterAsBase (TypeParameterExpr e)
609 String.Format ("Type parameter `{0}' can not be used t as a base class or interface", e.Name));
613 /// The pending methods that need to be implemented (interfaces or abstract methods)
615 public PendingImplementation Pending;
618 /// This function computes the Base class and also the
619 /// list of interfaces that the class or struct @c implements.
621 /// The return value is an array (might be null) of
622 /// interfaces implemented (as Types).
624 /// The @parent argument is set to the parent object or null
625 /// if this is `System.Object'.
627 Type [] GetClassBases (bool is_class, out TypeExpr parent, out bool error)
629 ArrayList bases = Bases;
638 parent = new TypeExpr (TypeManager.value_type, Location);
642 if (RootContext.StdLib)
643 parent = new TypeExpr (TypeManager.object_type, Location);
644 else if (Name != "System.Object")
645 parent = new TypeExpr (TypeManager.object_type, Location);
648 // If we are compiling our runtime,
649 // and we are defining ValueType, then our
650 // parent is `System.Object'.
652 if (!RootContext.StdLib && Name == "System.ValueType")
653 parent = new TypeExpr (TypeManager.object_type, Location);
660 // Bases should be null if there are no bases at all
665 Expression name = (Expression) bases [0];
666 name = ResolveTypeExpr (name, false, Location);
673 if (name is TypeParameterExpr){
674 Error_TypeParameterAsBase ((TypeParameterExpr) name);
679 if (name is ConstructedType){
680 parent = (TypeExpr) name;
684 Type first = name.Type;
688 parent = (TypeExpr) name;
692 ptype = TypeManager.object_type;
693 parent = new TypeExpr (ptype, Location);
699 if (first.IsValueType)
700 detail = " (a class can not inherit from a struct/enum)";
702 Report.Error (509, Location,"class `{0}': Cannot inherit from " +
703 "sealed class `{1}'{2}", Name, first, detail);
708 if (ptype == TypeManager.enum_type ||
709 (ptype == TypeManager.value_type && RootContext.StdLib) ||
710 ptype == TypeManager.delegate_type ||
711 ptype == TypeManager.array_type){
712 Report.Error (644, Location,
713 "`{0}' cannot inherit from special class `{1}'",
714 Name, TypeManager.CSharpName (ptype));
719 if (IsGeneric && (ptype == TypeManager.attribute_type ||
720 ptype.IsSubclassOf (TypeManager.attribute_type))){
721 Report.Error (-214, Location,
722 "Generic type can not derive from Attribute");
727 if (!AsAccessible (ptype, ModFlags))
728 Report.Error (60, Location,
729 "Inconsistent accessibility: base class `{0}' " +
730 "is less accessible than class `{1}'",
731 TypeManager.CSharpName (ptype), Name);
738 base_class_name = parent.Name;
740 Type [] ifaces = new Type [count-start];
742 for (i = start, j = 0; i < count; i++, j++){
743 Expression name = (Expression) bases [i];
744 Expression resolved = ResolveTypeExpr (name, false, Location);
745 if (resolved == null)
748 bases [i] = resolved;
749 Type t = resolved.Type;
756 if (is_class == false && !t.IsInterface){
757 Report.Error (527, "In Struct `" + Name + "', type `"+
758 name +"' is not an interface");
765 Report.Error (527, "In Class `" + Name + "', type `"+
766 name+"' is not an interface");
772 for (int x = 0; x < j; x++) {
773 if (t == ifaces [x]) {
774 Report.Error (528, "`" + name + "' is already listed in interface list");
783 return TypeManager.ExpandInterfaces (ifaces);
789 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
791 public override TypeBuilder DefineType ()
796 if (TypeBuilder != null)
803 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
815 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
817 ifaces = GetClassBases (is_class, out parent, out error);
823 foreach (TypeParameter type_param in TypeParameters)
824 if (!type_param.Resolve (this)) {
830 if (!is_class && TypeManager.value_type == null)
831 throw new Exception ();
833 TypeAttributes type_attributes = TypeAttr;
836 if (TypeManager.NamespaceClash (Name, Location)) {
841 ModuleBuilder builder = CodeGen.ModuleBuilder;
842 TypeBuilder = builder.DefineType (
843 Name, type_attributes, parent.Type, ifaces);
846 TypeBuilder builder = Parent.DefineType ();
850 TypeBuilder = builder.DefineNestedType (
851 Basename, type_attributes, parent.Type, ifaces);
855 foreach (TypeParameter type_param in TypeParameters)
856 type_param.Define (TypeBuilder);
859 ConstructedType constructed = parent as ConstructedType;
860 if (constructed != null) {
861 Type ptype = constructed.Resolve (ec, TypeBuilder);
865 TypeBuilder.SetParent (ptype);
869 // Structs with no fields need to have at least one byte.
870 // The right thing would be to set the PackingSize in a DefineType
871 // but there are no functions that allow interfaces *and* the size to
875 if (!is_class && !have_nonstatic_fields){
876 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
877 FieldAttributes.Private);
878 // add interfaces that were not added at type creation
879 if (ifaces != null) {
880 foreach (Type i in ifaces)
881 TypeBuilder.AddInterfaceImplementation (i);
886 // Finish the setup for the EmitContext
888 ec.ContainerType = TypeBuilder;
890 TypeManager.AddUserType (Name, TypeBuilder, this, ifaces);
892 if ((parent != null) && (parent.Type != null) &&
893 (parent.Type == TypeManager.attribute_type ||
894 parent.Type.IsSubclassOf (TypeManager.attribute_type))) {
895 RootContext.RegisterAttribute (this);
896 TypeManager.RegisterAttrType (TypeBuilder, this);
898 RootContext.RegisterOrder (this);
900 if (Interfaces != null) {
901 foreach (Interface iface in Interfaces)
902 if (iface.DefineType () == null) {
909 foreach (TypeContainer tc in Types)
910 if (tc.DefineType () == null) {
916 if (Delegates != null) {
917 foreach (Delegate d in Delegates)
918 if (d.DefineType () == null) {
925 foreach (Enum en in Enums)
926 if (en.DefineType () == null) {
938 /// Defines the MemberCore objects that are in the `list' Arraylist
940 /// The `defined_names' array contains a list of members defined in
943 static ArrayList remove_list = new ArrayList ();
944 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
948 remove_list.Clear ();
950 foreach (MemberCore mc in list){
952 if (defined_names != null)
953 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
958 if (RootContext.WarningLevel >= 4){
959 if ((mc.ModFlags & Modifiers.NEW) != 0)
960 Warning_KeywordNewNotRequired (mc.Location, mc);
962 } else if (mc is MethodCore)
963 ((MethodCore) mc).OverridesSomething = true;
965 if (!mc.Define (this)){
966 remove_list.Add (mc);
973 MemberInfo match = defined_names [idx];
975 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
979 // If we are both methods, let the method resolution emit warnings
981 if (match is MethodBase && mc is MethodCore)
984 if ((mc.ModFlags & Modifiers.NEW) == 0) {
986 if (!(match is EventInfo)) {
987 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
991 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
995 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
999 foreach (object o in remove_list)
1002 remove_list.Clear ();
1006 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1007 // class is consisten. Either it is `Item' or it is the name defined by all the
1008 // indexers with the `IndexerName' attribute.
1010 // Turns out that the IndexerNameAttribute is applied to each indexer,
1011 // but it is never emitted, instead a DefaultName attribute is attached
1014 void DefineIndexers ()
1016 string class_indexer_name = null;
1019 // If there's both an explicit and an implicit interface implementation, the
1020 // explicit one actually implements the interface while the other one is just
1021 // a normal indexer. See bug #37714.
1023 ArrayList list = new ArrayList ();
1024 foreach (Indexer i in Indexers){
1025 if (i.ExplicitInterfaceName != null)
1028 foreach (Indexer i in Indexers){
1029 if (i.ExplicitInterfaceName == null)
1033 foreach (Indexer i in list){
1038 name = i.IndexerName;
1040 if (i.InterfaceType != null)
1043 if (class_indexer_name == null){
1044 class_indexer_name = name;
1048 if (name == class_indexer_name)
1052 668, "Two indexers have different names, " +
1053 " you should use the same name for all your indexers");
1055 if (class_indexer_name == null)
1056 class_indexer_name = "Item";
1057 IndexerName = class_indexer_name;
1060 static void Error_KeywordNotAllowed (Location loc)
1062 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1066 /// Populates our TypeBuilder with fields and methods
1068 public override bool DefineMembers (TypeContainer container)
1070 MemberInfo [] defined_names = null;
1072 if (interface_order != null){
1073 foreach (Interface iface in interface_order)
1074 if ((iface.ModFlags & Modifiers.NEW) == 0)
1075 iface.DefineMembers (this);
1077 Error_KeywordNotAllowed (iface.Location);
1080 if (RootContext.WarningLevel > 1){
1084 // This code throws an exception in the comparer
1085 // I guess the string is not an object?
1087 ptype = TypeBuilder.BaseType;
1089 defined_names = (MemberInfo []) FindMembers (
1090 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1091 BindingFlags.Public | BindingFlags.Instance |
1092 BindingFlags.Static, null, null);
1094 Array.Sort (defined_names, mif_compare);
1098 Class pclass = Parent as Class;
1099 if (pclass != null) {
1100 string pname = null;
1102 Type t = pclass.TypeBuilder.BaseType;
1103 while ((t != null) && (ptype == null)) {
1104 pname = t.FullName + "." + Basename;
1105 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1109 if ((ModFlags & Modifiers.NEW) != 0) {
1111 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1112 "inherited member. The keyword new is not required.");
1113 } else if (ptype != null) {
1114 Report.Warning (108, Location, "The keyword new is required on `" +
1115 Name + "' because it hides inherited member '" +
1118 } else if ((ModFlags & Modifiers.NEW) != 0)
1119 Error_KeywordNotAllowed (Location);
1121 if (constants != null)
1122 DefineMembers (constants, defined_names);
1125 DefineMembers (fields, defined_names);
1127 if ((RootContext.WarningLevel >= 4) && (fields != null)) {
1128 foreach (Field f in fields) {
1129 if (((f.ModFlags & Modifiers.READONLY) != 0) && !f.IsAssigned)
1130 Report.Warning (649, "Field `" + MakeFQN (Name, f.Name) + "; is never " +
1131 "assigned and will ever have its default value");
1136 if (instance_constructors == null){
1137 if (default_constructor == null)
1138 DefineDefaultConstructor (false);
1141 if (initialized_static_fields != null &&
1142 default_static_constructor == null)
1143 DefineDefaultConstructor (true);
1146 if (this is Struct){
1148 // Structs can not have initialized instance
1151 if (initialized_static_fields != null &&
1152 default_static_constructor == null)
1153 DefineDefaultConstructor (true);
1155 if (initialized_fields != null)
1156 ReportStructInitializedInstanceError ();
1159 Pending = PendingImplementation.GetPendingImplementations (this);
1162 // Constructors are not in the defined_names array
1164 if (instance_constructors != null)
1165 DefineMembers (instance_constructors, null);
1167 if (default_static_constructor != null)
1168 default_static_constructor.Define (this);
1170 if (methods != null)
1171 DefineMembers (methods, defined_names);
1173 if (properties != null)
1174 DefineMembers (properties, defined_names);
1177 DefineMembers (events, defined_names);
1179 if (indexers != null) {
1182 IndexerName = "Item";
1184 if (operators != null){
1185 DefineMembers (operators, null);
1187 CheckPairedOperators ();
1191 DefineMembers (enums, defined_names);
1193 if (delegates != null)
1194 DefineMembers (delegates, defined_names);
1197 if (TypeBuilder.BaseType != null)
1198 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1200 member_cache = new MemberCache (this);
1207 public override bool Define (TypeContainer container)
1209 if (interface_order != null){
1210 foreach (Interface iface in interface_order)
1211 if ((iface.ModFlags & Modifiers.NEW) == 0)
1212 iface.Define (this);
1219 /// This function is based by a delegate to the FindMembers routine
1221 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1227 /// This filter is used by FindMembers, and we just keep
1228 /// a global for the filter to `AlwaysAccept'
1230 static MemberFilter accepting_filter;
1234 /// A member comparission method based on name only
1236 static IComparer mif_compare;
1238 static TypeContainer ()
1240 accepting_filter = new MemberFilter (AlwaysAccept);
1241 mif_compare = new MemberInfoCompare ();
1245 /// This method returns the members of this type just like Type.FindMembers would
1246 /// Only, we need to use this for types which are _being_ defined because MS'
1247 /// implementation can't take care of that.
1250 // FIXME: return an empty static array instead of null, that cleans up
1251 // some code and is consistent with some coding conventions I just found
1255 // Notice that in various cases we check if our field is non-null,
1256 // something that would normally mean that there was a bug elsewhere.
1258 // The problem happens while we are defining p-invoke methods, as those
1259 // will trigger a FindMembers, but this happens before things are defined
1261 // Since the whole process is a no-op, it is fine to check for null here.
1263 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1264 MemberFilter filter, object criteria)
1266 ArrayList members = new ArrayList ();
1269 if ((bf & BindingFlags.Public) != 0)
1270 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1272 if ((bf & BindingFlags.NonPublic) != 0)
1273 modflags |= Modifiers.PRIVATE;
1275 int static_mask = 0, static_flags = 0;
1276 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1277 case BindingFlags.Static:
1278 static_mask = static_flags = Modifiers.STATIC;
1281 case BindingFlags.Instance:
1282 static_mask = Modifiers.STATIC;
1287 static_mask = static_flags = 0;
1291 Timer.StartTimer (TimerType.TcFindMembers);
1294 filter = accepting_filter;
1296 if ((mt & MemberTypes.Field) != 0) {
1297 if (fields != null) {
1298 foreach (Field f in fields) {
1299 if ((f.ModFlags & modflags) == 0)
1301 if ((f.ModFlags & static_mask) != static_flags)
1304 FieldBuilder fb = f.FieldBuilder;
1305 if (fb != null && filter (fb, criteria) == true)
1310 if (constants != null) {
1311 foreach (Const con in constants) {
1312 if ((con.ModFlags & modflags) == 0)
1314 if ((con.ModFlags & static_mask) != static_flags)
1317 FieldBuilder fb = con.FieldBuilder;
1318 if (fb != null && filter (fb, criteria) == true)
1324 if ((mt & MemberTypes.Method) != 0) {
1325 if (methods != null) {
1326 foreach (Method m in methods) {
1327 if ((m.ModFlags & modflags) == 0)
1329 if ((m.ModFlags & static_mask) != static_flags)
1332 MethodBuilder mb = m.MethodBuilder;
1334 if (mb != null && filter (mb, criteria) == true)
1339 if (operators != null){
1340 foreach (Operator o in operators) {
1341 if ((o.ModFlags & modflags) == 0)
1343 if ((o.ModFlags & static_mask) != static_flags)
1346 MethodBuilder ob = o.OperatorMethodBuilder;
1347 if (ob != null && filter (ob, criteria) == true)
1352 if (properties != null){
1353 foreach (Property p in properties){
1354 if ((p.ModFlags & modflags) == 0)
1356 if ((p.ModFlags & static_mask) != static_flags)
1362 if (b != null && filter (b, criteria) == true)
1366 if (b != null && filter (b, criteria) == true)
1371 if (indexers != null){
1372 foreach (Indexer ix in indexers){
1373 if ((ix.ModFlags & modflags) == 0)
1375 if ((ix.ModFlags & static_mask) != static_flags)
1381 if (b != null && filter (b, criteria) == true)
1385 if (b != null && filter (b, criteria) == true)
1391 if ((mt & MemberTypes.Event) != 0) {
1393 foreach (Event e in events) {
1394 if ((e.ModFlags & modflags) == 0)
1396 if ((e.ModFlags & static_mask) != static_flags)
1399 MemberInfo eb = e.EventBuilder;
1400 if (eb != null && filter (eb, criteria) == true)
1401 members.Add (e.EventBuilder);
1405 if ((mt & MemberTypes.Property) != 0){
1406 if (properties != null)
1407 foreach (Property p in properties) {
1408 if ((p.ModFlags & modflags) == 0)
1410 if ((p.ModFlags & static_mask) != static_flags)
1413 MemberInfo pb = p.PropertyBuilder;
1414 if (pb != null && filter (pb, criteria) == true) {
1415 members.Add (p.PropertyBuilder);
1419 if (indexers != null)
1420 foreach (Indexer ix in indexers) {
1421 if ((ix.ModFlags & modflags) == 0)
1423 if ((ix.ModFlags & static_mask) != static_flags)
1426 MemberInfo ib = ix.PropertyBuilder;
1427 if (ib != null && filter (ib, criteria) == true) {
1428 members.Add (ix.PropertyBuilder);
1433 if ((mt & MemberTypes.NestedType) != 0) {
1435 foreach (TypeContainer t in types) {
1436 if ((t.ModFlags & modflags) == 0)
1439 TypeBuilder tb = t.TypeBuilder;
1440 if (tb != null && (filter (tb, criteria) == true))
1446 foreach (Enum en in enums){
1447 if ((en.ModFlags & modflags) == 0)
1450 TypeBuilder tb = en.TypeBuilder;
1451 if (tb != null && (filter (tb, criteria) == true))
1456 if (delegates != null){
1457 foreach (Delegate d in delegates){
1458 if ((d.ModFlags & modflags) == 0)
1461 TypeBuilder tb = d.TypeBuilder;
1462 if (tb != null && (filter (tb, criteria) == true))
1467 if (interfaces != null){
1468 foreach (Interface iface in interfaces){
1469 if ((iface.ModFlags & modflags) == 0)
1472 TypeBuilder tb = iface.TypeBuilder;
1473 if (tb != null && (filter (tb, criteria) == true))
1479 if ((mt & MemberTypes.Constructor) != 0){
1480 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1481 foreach (Constructor c in instance_constructors){
1482 ConstructorBuilder cb = c.ConstructorBuilder;
1484 if (filter (cb, criteria) == true)
1489 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1490 ConstructorBuilder cb =
1491 default_static_constructor.ConstructorBuilder;
1494 if (filter (cb, criteria) == true)
1500 // Lookup members in parent if requested.
1502 if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
1503 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1504 members.AddRange (list);
1507 Timer.StopTimer (TimerType.TcFindMembers);
1509 return new MemberList (members);
1512 public override MemberCache MemberCache {
1514 return member_cache;
1518 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1519 MemberFilter filter, object criteria)
1521 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1524 return ds.FindMembers (mt, bf, filter, criteria);
1526 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1530 // FindMethods will look for methods not only in the type `t', but in
1531 // any interfaces implemented by the type.
1533 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
1534 MemberFilter filter, object criteria)
1540 /// Emits the values for the constants
1542 public void EmitConstants ()
1544 if (constants != null)
1545 foreach (Const con in constants)
1546 con.EmitConstant (this);
1551 /// Emits the code, this step is performed after all
1552 /// the types, enumerations, constructors
1556 if (instance_constructors != null)
1557 foreach (Constructor c in instance_constructors)
1560 if (default_static_constructor != null)
1561 default_static_constructor.Emit (this);
1563 if (methods != null)
1564 foreach (Method m in methods)
1567 if (operators != null)
1568 foreach (Operator o in operators)
1571 if (properties != null)
1572 foreach (Property p in properties)
1575 if (indexers != null){
1576 foreach (Indexer ix in indexers)
1579 CustomAttributeBuilder cb = Interface.EmitDefaultMemberAttr (
1580 this, IndexerName, ModFlags, Location);
1581 TypeBuilder.SetCustomAttribute (cb);
1585 foreach (Field f in fields)
1588 if (events != null){
1589 foreach (Event e in Events)
1593 if (Pending != null)
1594 if (Pending.VerifyPendingMethods ())
1597 Attribute.ApplyAttributes (ec, TypeBuilder, this, OptAttributes);
1600 // Check for internal or private fields that were never assigned
1602 if (RootContext.WarningLevel >= 3) {
1603 if (fields != null){
1604 foreach (Field f in fields) {
1605 if ((f.ModFlags & Modifiers.PUBLIC) != 0)
1610 169, f.Location, "Private field " +
1611 MakeName (f.Name) + " is never used");
1616 // Only report 649 on level 4
1618 if (RootContext.WarningLevel < 4)
1621 if ((f.status & Field.Status.ASSIGNED) != 0)
1626 "Field " + MakeName (f.Name) + " is never assigned " +
1627 " to and will always have its default value");
1631 if (events != null){
1632 foreach (Event e in events){
1634 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
1639 // if (types != null)
1640 // foreach (TypeContainer tc in types)
1644 public override void CloseType ()
1649 TypeBuilder.CreateType ();
1651 } catch (TypeLoadException){
1653 // This is fine, the code still created the type
1655 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
1656 // Console.WriteLine (e.Message);
1658 Console.WriteLine ("In type: " + Name);
1663 foreach (Enum en in Enums)
1666 if (interface_order != null){
1667 foreach (Interface iface in interface_order)
1672 foreach (TypeContainer tc in Types)
1676 foreach (TypeContainer tc in Types)
1677 if (!(tc is Struct))
1681 if (Delegates != null)
1682 foreach (Delegate d in Delegates)
1686 public string MakeName (string n)
1688 return "`" + Name + "." + n + "'";
1691 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
1694 108, l, "The keyword new is required on " +
1695 MakeName (mi.Name) + " because it hides `" +
1696 mi.ReflectedType.Name + "." + mi.Name + "'");
1699 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
1702 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
1703 "inherited member, the keyword new is not required");
1706 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
1709 72, l, MakeName (mi.Name) + " : cannot override; `" +
1710 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
1713 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
1719 // Performs the validation on a Method's modifiers (properties have
1720 // the same properties).
1722 public bool MethodModifiersValid (int flags, string n, Location loc)
1724 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
1725 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
1726 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
1730 // At most one of static, virtual or override
1732 if ((flags & Modifiers.STATIC) != 0){
1733 if ((flags & vao) != 0){
1735 112, loc, "static method " + MakeName (n) + "can not be marked " +
1736 "as virtual, abstract or override");
1741 if (this is Struct){
1742 if ((flags & va) != 0){
1743 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
1748 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
1750 113, loc, MakeName (n) +
1751 " marked as override cannot be marked as new or virtual");
1756 // If the declaration includes the abstract modifier, then the
1757 // declaration does not include static, virtual or extern
1759 if ((flags & Modifiers.ABSTRACT) != 0){
1760 if ((flags & Modifiers.EXTERN) != 0){
1762 180, loc, MakeName (n) + " can not be both abstract and extern");
1766 if ((flags & Modifiers.VIRTUAL) != 0){
1768 503, loc, MakeName (n) + " can not be both abstract and virtual");
1772 if ((ModFlags & Modifiers.ABSTRACT) == 0){
1774 513, loc, MakeName (n) +
1775 " is abstract but its container class is not");
1781 if ((flags & Modifiers.PRIVATE) != 0){
1782 if ((flags & vao) != 0){
1784 621, loc, MakeName (n) +
1785 " virtual or abstract members can not be private");
1790 if ((flags & Modifiers.SEALED) != 0){
1791 if ((flags & Modifiers.OVERRIDE) == 0){
1793 238, loc, MakeName (n) +
1794 " cannot be sealed because it is not an override");
1802 Hashtable builder_and_args;
1804 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
1806 if (builder_and_args == null)
1807 builder_and_args = new Hashtable ();
1812 /// Performs checks for an explicit interface implementation. First it
1813 /// checks whether the `interface_type' is a base inteface implementation.
1814 /// Then it checks whether `name' exists in the interface type.
1816 public bool VerifyImplements (Type interface_type, string full, string name, Location loc)
1820 if (ifaces != null){
1821 foreach (Type t in ifaces){
1822 if (t == interface_type){
1830 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
1837 public static void Error_ExplicitInterfaceNotMemberInterface (Location loc, string name)
1839 Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
1846 string IMemberContainer.Name {
1852 Type IMemberContainer.Type {
1858 IMemberContainer IMemberContainer.Parent {
1860 return parent_container;
1864 MemberCache IMemberContainer.MemberCache {
1866 return member_cache;
1870 bool IMemberContainer.IsInterface {
1876 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
1878 return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
1882 // Operator pair checking
1885 class OperatorEntry {
1887 public Type ret_type;
1888 public Type type1, type2;
1890 public Operator.OpType ot;
1892 public OperatorEntry (int f, Operator o)
1896 ret_type = o.OperatorMethod.GetReturnType ();
1897 Type [] pt = o.OperatorMethod.ParameterTypes;
1901 ot = o.OperatorType;
1904 public override int GetHashCode ()
1906 return ret_type.GetHashCode ();
1909 public override bool Equals (object o)
1911 OperatorEntry other = (OperatorEntry) o;
1913 if (other.ret_type != ret_type)
1915 if (other.type1 != type1)
1917 if (other.type2 != type2)
1924 // Checks that some operators come in pairs:
1930 // They are matched based on the return type and the argument types
1932 void CheckPairedOperators ()
1934 Hashtable pairs = new Hashtable (null, null);
1935 Operator true_op = null;
1936 Operator false_op = null;
1937 bool has_equality_or_inequality = false;
1939 // Register all the operators we care about.
1940 foreach (Operator op in operators){
1943 switch (op.OperatorType){
1944 case Operator.OpType.Equality:
1946 has_equality_or_inequality = true;
1948 case Operator.OpType.Inequality:
1950 has_equality_or_inequality = true;
1953 case Operator.OpType.True:
1956 case Operator.OpType.False:
1960 case Operator.OpType.GreaterThan:
1962 case Operator.OpType.LessThan:
1965 case Operator.OpType.GreaterThanOrEqual:
1967 case Operator.OpType.LessThanOrEqual:
1973 OperatorEntry oe = new OperatorEntry (reg, op);
1975 object o = pairs [oe];
1979 oe = (OperatorEntry) o;
1984 if (true_op != null){
1985 if (false_op == null)
1986 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
1987 } else if (false_op != null)
1988 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
1991 // Look for the mistakes.
1993 foreach (DictionaryEntry de in pairs){
1994 OperatorEntry oe = (OperatorEntry) de.Key;
2001 case Operator.OpType.Equality:
2004 case Operator.OpType.Inequality:
2007 case Operator.OpType.GreaterThan:
2010 case Operator.OpType.LessThan:
2013 case Operator.OpType.GreaterThanOrEqual:
2016 case Operator.OpType.LessThanOrEqual:
2020 Report.Error (216, oe.op.Location,
2021 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2024 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2025 MethodSignature equals_ms = new MethodSignature (
2026 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2027 MethodSignature hash_ms = new MethodSignature (
2028 "GetHashCode", TypeManager.int32_type, new Type [0]);
2030 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2031 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2033 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2034 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2037 bool equals_ok = false;
2038 if ((equals_ml != null) && (equals_ml.Count == 1))
2039 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2040 bool hash_ok = false;
2041 if ((hash_ml != null) && (hash_ml.Count == 1))
2042 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2045 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2046 "not override Object.Equals (object o)");
2048 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2049 "not override Object.GetHashCode ()");
2055 public class Class : TypeContainer {
2057 // Modifiers allowed in a class declaration
2059 public const int AllowedModifiers =
2062 Modifiers.PROTECTED |
2063 Modifiers.INTERNAL |
2065 Modifiers.ABSTRACT |
2069 public Class (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2070 : base (ns, parent, name, l)
2074 if (parent.Parent == null)
2075 accmods = Modifiers.INTERNAL;
2077 accmods = Modifiers.PRIVATE;
2079 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2080 this.attributes = attrs;
2084 // FIXME: How do we deal with the user specifying a different
2087 public override TypeAttributes TypeAttr {
2089 return base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2094 public class Struct : TypeContainer {
2096 // Modifiers allowed in a struct declaration
2098 public const int AllowedModifiers =
2101 Modifiers.PROTECTED |
2102 Modifiers.INTERNAL |
2106 public Struct (NamespaceEntry ns, TypeContainer parent, string name, int mod, Attributes attrs, Location l)
2107 : base (ns, parent, name, l)
2111 if (parent.Parent == null)
2112 accmods = Modifiers.INTERNAL;
2114 accmods = Modifiers.PRIVATE;
2116 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2118 this.ModFlags |= Modifiers.SEALED;
2119 this.attributes = attrs;
2124 // FIXME: Allow the user to specify a different set of attributes
2125 // in some cases (Sealed for example is mandatory for a class,
2126 // but what SequentialLayout can be changed
2128 public override TypeAttributes TypeAttr {
2130 return base.TypeAttr |
2131 TypeAttributes.SequentialLayout |
2132 TypeAttributes.Sealed |
2133 TypeAttributes.BeforeFieldInit;
2138 public abstract class MethodCore : MemberBase {
2139 public readonly Parameters Parameters;
2140 protected Block block;
2141 protected DeclSpace ds;
2144 // Parameters, cached for semantic analysis.
2146 protected InternalParameters parameter_info;
2147 protected Type [] parameter_types;
2150 // This is set from TypeContainer.DefineMembers if this method overrides something.
2152 public bool OverridesSomething;
2154 public MethodCore (DeclSpace ds, Expression type, int mod, int allowed_mod,
2155 string name, Attributes attrs, Parameters parameters, Location loc)
2156 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
2158 Parameters = parameters;
2163 // Returns the System.Type array for the parameters of this method
2165 public Type [] ParameterTypes {
2167 return parameter_types;
2171 public InternalParameters ParameterInfo
2174 return parameter_info;
2178 public Block Block {
2188 protected virtual bool DoDefineParameters ()
2190 // Check if arguments were correct
2191 parameter_types = Parameters.GetParameterInfo (ds);
2192 if ((parameter_types == null) || !CheckParameters (ds, parameter_types))
2195 parameter_info = new InternalParameters (ds, Parameters);
2197 Parameter array_param = Parameters.ArrayParameter;
2198 if ((array_param != null) &&
2199 (!array_param.ParameterType.IsArray ||
2200 (array_param.ParameterType.GetArrayRank () != 1))) {
2201 Report.Error (225, Location, "params parameter has to be a single dimensional array");
2208 public CallingConventions GetCallingConvention (bool is_class)
2210 CallingConventions cc = 0;
2212 cc = Parameters.GetCallingConvention ();
2215 if ((ModFlags & Modifiers.STATIC) == 0)
2216 cc |= CallingConventions.HasThis;
2218 // FIXME: How is `ExplicitThis' used in C#?
2224 // The method's attributes are passed in because we need to extract
2225 // the "return:" attribute from there to apply on the return type
2227 static public void LabelParameters (EmitContext ec,
2229 Parameters parameters,
2230 Attributes method_attrs,
2234 // Define each type attribute (in/out/ref) and
2235 // the argument names.
2237 Parameter [] p = parameters.FixedParameters;
2240 MethodBuilder mb = null;
2241 ConstructorBuilder cb = null;
2243 if (builder is MethodBuilder)
2244 mb = (MethodBuilder) builder;
2246 cb = (ConstructorBuilder) builder;
2249 for (i = 0; i < p.Length; i++) {
2250 ParameterBuilder pb;
2251 ParameterAttributes par_attr = p [i].Attributes;
2254 pb = cb.DefineParameter (
2255 i + 1, par_attr, p [i].Name);
2257 pb = mb.DefineParameter (
2258 i + 1, par_attr, p [i].Name);
2260 Attributes attr = p [i].OptAttributes;
2262 Attribute.ApplyAttributes (ec, pb, pb, attr);
2264 if (par_attr == ParameterAttributes.Out){
2265 if (attr.Contains (TypeManager.in_attribute_type))
2266 Report.Error (36, loc,
2267 "Can not use [In] attribute on out parameter");
2273 if (parameters.ArrayParameter != null){
2274 ParameterBuilder pb;
2275 Parameter array_param = parameters.ArrayParameter;
2278 pb = cb.DefineParameter (
2279 i + 1, array_param.Attributes,
2282 pb = mb.DefineParameter (
2283 i + 1, array_param.Attributes,
2286 CustomAttributeBuilder a = new CustomAttributeBuilder (
2287 TypeManager.cons_param_array_attribute, new object [0]);
2289 pb.SetCustomAttribute (a);
2293 // And now for the return type attribute decoration
2295 ParameterBuilder ret_pb;
2296 Attributes ret_attrs = null;
2298 if (mb == null || method_attrs == null)
2301 foreach (AttributeSection asec in method_attrs.AttributeSections) {
2303 if (asec.Target != "return")
2306 if (ret_attrs == null)
2307 ret_attrs = new Attributes (asec);
2309 ret_attrs.AddAttributeSection (asec);
2312 if (ret_attrs != null) {
2314 ret_pb = mb.DefineParameter (0, ParameterAttributes.None, "");
2315 Attribute.ApplyAttributes (ec, ret_pb, ret_pb, ret_attrs);
2317 } catch (ArgumentOutOfRangeException) {
2320 ".NET SDK 1.0 does not permit setting custom attributes" +
2321 " on the return type of a method");
2327 public class Method : MethodCore, IIteratorContainer {
2328 public MethodBuilder MethodBuilder;
2329 public MethodData MethodData;
2330 public readonly GenericMethod GenericMethod;
2333 /// Modifiers allowed in a class declaration
2335 const int AllowedModifiers =
2338 Modifiers.PROTECTED |
2339 Modifiers.INTERNAL |
2344 Modifiers.OVERRIDE |
2345 Modifiers.ABSTRACT |
2350 // return_type can be "null" for VOID values.
2352 public Method (DeclSpace ds, Expression return_type, int mod, string name,
2353 Parameters parameters, Attributes attrs, Location l)
2354 : base (ds, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2357 public Method (GenericMethod generic, Expression return_type, int mod, string name,
2358 Parameters parameters, Attributes attrs, Location l)
2359 : base (generic, return_type, mod, AllowedModifiers, name, attrs, parameters, l)
2361 GenericMethod = generic;
2365 // Returns the `System.Type' for the ReturnType of this
2366 // function. Provides a nice cache. (used between semantic analysis
2367 // and actual code generation
2369 public Type GetReturnType ()
2374 // Whether this is an operator method.
2375 public bool IsOperator;
2377 void DuplicateEntryPoint (MethodInfo b, Location location)
2381 "Program `" + CodeGen.FileName +
2382 "' has more than one entry point defined: `" +
2383 TypeManager.CSharpSignature(b) + "'");
2386 void Report28 (MethodInfo b)
2390 "`" + TypeManager.CSharpSignature(b) +
2391 "' has the wrong signature to be an entry point");
2394 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
2396 if (b.ReturnType != TypeManager.void_type &&
2397 b.ReturnType != TypeManager.int32_type)
2400 if (pinfo.Count == 0)
2403 if (pinfo.Count > 1)
2406 Type t = pinfo.ParameterType(0);
2408 (t.GetArrayRank() == 1) &&
2409 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
2410 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
2417 // Checks our base implementation if any
2419 protected override bool CheckBase (TypeContainer container)
2421 base.CheckBase (container);
2423 // Check whether arguments were correct.
2424 if (!DoDefineParameters ())
2427 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
2429 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
2433 mi_this = TypeContainer.FindMembers (
2434 container.TypeBuilder, MemberTypes.Method,
2435 BindingFlags.NonPublic | BindingFlags.Public |
2436 BindingFlags.Static | BindingFlags.Instance |
2437 BindingFlags.DeclaredOnly,
2438 MethodSignature.method_signature_filter, ms);
2440 if (mi_this.Count > 0) {
2441 Report.Error (111, Location, "Class `" + container.Name + "' " +
2442 "already defines a member called `" + Name + "' " +
2443 "with the same parameter types");
2449 // Verify if the parent has a type with the same name, and then
2450 // check whether we have to create a new slot for it or not.
2452 Type ptype = container.TypeBuilder.BaseType;
2454 // ptype is only null for System.Object while compiling corlib.
2456 MemberList mi, mi_static, mi_instance;
2458 mi_instance = TypeContainer.FindMembers (
2459 ptype, MemberTypes.Method,
2460 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
2461 MethodSignature.inheritable_method_signature_filter,
2464 if (mi_instance.Count > 0){
2467 mi_static = TypeContainer.FindMembers (
2468 ptype, MemberTypes.Method,
2469 BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
2470 MethodSignature.inheritable_method_signature_filter, ms);
2472 if (mi_static.Count > 0)
2478 if (mi != null && mi.Count > 0){
2479 parent_method = (MethodInfo) mi [0];
2480 string name = parent_method.DeclaringType.Name + "." +
2483 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
2486 if ((ModFlags & Modifiers.NEW) == 0) {
2487 Type parent_ret = TypeManager.TypeToCoreType (
2488 parent_method.ReturnType);
2490 if (parent_ret != MemberType) {
2492 508, Location, container.MakeName (Name) + ": cannot " +
2493 "change return type when overriding " +
2494 "inherited member " + name);
2499 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
2500 WarningNotHiding (container);
2502 if ((ModFlags & Modifiers.OVERRIDE) != 0){
2503 Report.Error (115, Location,
2504 container.MakeName (Name) +
2505 " no suitable methods found to override");
2508 } else if ((ModFlags & Modifiers.NEW) != 0)
2509 WarningNotHiding (container);
2517 public override bool Define (TypeContainer container)
2519 if (!DoDefine (container))
2522 MethodBuilder mb = null;
2523 if (GenericMethod != null) {
2524 mb = container.TypeBuilder.DefineGenericMethod (Name, flags);
2525 if (!GenericMethod.Define (mb))
2529 if (!CheckBase (container))
2532 CallingConventions cc = GetCallingConvention (container is Class);
2534 MethodData = new MethodData (ds, this, null, MemberType,
2535 ParameterTypes, ParameterInfo, cc,
2536 OptAttributes, ModFlags, flags, true, mb);
2538 if (!MethodData.Define (container))
2542 // Setup iterator if we are one
2544 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
2545 IteratorHandler ih = new IteratorHandler (
2546 Name, container, MemberType,
2547 ParameterTypes, ParameterInfo,
2548 ModFlags, Location);
2550 Block new_block = ih.Setup (block);
2551 if (new_block == null)
2556 MethodBuilder = MethodData.MethodBuilder;
2559 // This is used to track the Entry Point,
2561 if (Name == "Main" &&
2562 ((ModFlags & Modifiers.STATIC) != 0) &&
2563 (RootContext.MainClass == null ||
2564 RootContext.MainClass == container.TypeBuilder.FullName)){
2565 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
2566 if (RootContext.EntryPoint == null) {
2567 if (container.IsGeneric){
2568 Report.Error (-201, Location,
2569 "Entry point can not be defined in a generic class");
2572 RootContext.EntryPoint = MethodBuilder;
2573 RootContext.EntryPointLocation = Location;
2575 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
2576 DuplicateEntryPoint (MethodBuilder, Location);
2579 Report28(MethodBuilder);
2588 public void Emit (TypeContainer container)
2590 MethodData.Emit (container, Block, this);
2594 void IIteratorContainer.SetYields ()
2596 ModFlags |= Modifiers.METHOD_YIELDS;
2600 public abstract class ConstructorInitializer {
2601 ArrayList argument_list;
2602 ConstructorInfo parent_constructor;
2603 Parameters parameters;
2606 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
2609 this.argument_list = argument_list;
2610 this.parameters = parameters;
2614 public ArrayList Arguments {
2616 return argument_list;
2620 public bool Resolve (EmitContext ec)
2622 Expression parent_constructor_group;
2625 ec.CurrentBlock = new Block (null, Block.Flags.Implicit, parameters);
2627 if (argument_list != null){
2628 foreach (Argument a in argument_list){
2629 if (!a.Resolve (ec, loc))
2633 ec.CurrentBlock = null;
2635 if (this is ConstructorBaseInitializer) {
2636 if (ec.ContainerType.BaseType == null)
2639 t = ec.ContainerType.BaseType;
2640 if (ec.ContainerType.IsValueType) {
2641 Report.Error (522, loc,
2642 "structs cannot call base class constructors");
2646 t = ec.ContainerType;
2648 parent_constructor_group = Expression.MemberLookup (
2649 ec, t, null, t, ".ctor",
2650 MemberTypes.Constructor,
2651 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
2654 if (parent_constructor_group == null){
2655 Report.Error (1501, loc,
2656 "Can not find a constructor for this argument list");
2660 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
2661 (MethodGroupExpr) parent_constructor_group, argument_list, loc);
2663 if (parent_constructor == null){
2664 Report.Error (1501, loc,
2665 "Can not find a constructor for this argument list");
2672 public void Emit (EmitContext ec)
2674 if (parent_constructor != null){
2675 ec.Mark (loc, false);
2677 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
2679 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
2684 public class ConstructorBaseInitializer : ConstructorInitializer {
2685 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
2686 base (argument_list, pars, l)
2691 public class ConstructorThisInitializer : ConstructorInitializer {
2692 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
2693 base (argument_list, pars, l)
2698 public class Constructor : MethodCore {
2699 public ConstructorBuilder ConstructorBuilder;
2700 public ConstructorInitializer Initializer;
2701 new public Attributes OptAttributes;
2704 // Modifiers allowed for a constructor.
2706 public const int AllowedModifiers =
2708 Modifiers.PROTECTED |
2709 Modifiers.INTERNAL |
2716 // The spec claims that static is not permitted, but
2717 // my very own code has static constructors.
2719 public Constructor (DeclSpace ds, string name, Parameters args,
2720 ConstructorInitializer init, Location l)
2721 : base (ds, null, 0, AllowedModifiers, name, null, args, l)
2727 // Returns true if this is a default constructor
2729 public bool IsDefault ()
2731 if ((ModFlags & Modifiers.STATIC) != 0)
2732 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2733 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
2736 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
2737 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
2738 (Initializer is ConstructorBaseInitializer) &&
2739 (Initializer.Arguments == null);
2743 // Creates the ConstructorBuilder
2745 public override bool Define (TypeContainer container)
2747 MethodAttributes ca = (MethodAttributes.RTSpecialName |
2748 MethodAttributes.SpecialName);
2750 // Check if arguments were correct.
2751 if (!DoDefineParameters ())
2754 if ((ModFlags & Modifiers.STATIC) != 0){
2755 ca |= MethodAttributes.Static | MethodAttributes.Private;
2757 if (container is Struct && ParameterTypes.Length == 0){
2760 "Structs can not contain explicit parameterless " +
2764 ca |= MethodAttributes.HideBySig;
2766 if ((ModFlags & Modifiers.PUBLIC) != 0)
2767 ca |= MethodAttributes.Public;
2768 else if ((ModFlags & Modifiers.PROTECTED) != 0){
2769 if ((ModFlags & Modifiers.INTERNAL) != 0)
2770 ca |= MethodAttributes.FamORAssem;
2772 ca |= MethodAttributes.Family;
2773 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
2774 ca |= MethodAttributes.Assembly;
2775 else if (IsDefault ())
2776 ca |= MethodAttributes.Public;
2778 ca |= MethodAttributes.Private;
2781 ConstructorBuilder = container.TypeBuilder.DefineConstructor (
2782 ca, GetCallingConvention (container is Class), ParameterTypes);
2784 if ((ModFlags & Modifiers.UNSAFE) != 0)
2785 ConstructorBuilder.InitLocals = false;
2788 // HACK because System.Reflection.Emit is lame
2790 if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
2793 "Class `" +container.Name+ "' already contains a definition with the " +
2794 "same return value and parameter types for constructor `" + Name
2805 public void Emit (TypeContainer container)
2807 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
2808 EmitContext ec = new EmitContext (container, Location, ig, null, ModFlags, true);
2811 // extern methods have no bodies
2813 if ((ModFlags & Modifiers.EXTERN) != 0) {
2814 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
2816 179, Location, "External constructor `" +
2817 TypeManager.CSharpSignature (ConstructorBuilder) +
2818 "' can not have a body");
2821 } else if (block == null) {
2823 501, Location, "Constructor `" +
2824 TypeManager.CSharpSignature (ConstructorBuilder) +
2825 "' must declare a body since it is not marked extern");
2829 if ((ModFlags & Modifiers.STATIC) == 0){
2830 if (container is Class && Initializer == null)
2831 Initializer = new ConstructorBaseInitializer (
2832 null, Parameters.EmptyReadOnlyParameters, Location);
2836 // Spec mandates that Initializers will not have
2840 if (Initializer != null && !Initializer.Resolve (ec))
2842 ec.IsStatic = false;
2845 MethodCore.LabelParameters (ec, ConstructorBuilder,
2846 Parameters, OptAttributes, Location);
2848 SymbolWriter sw = CodeGen.SymbolWriter;
2849 bool generate_debugging = false;
2851 if ((sw != null) && (block != null) &&
2852 !Location.IsNull (Location) &&
2853 !Location.IsNull (block.EndLocation)) {
2855 sw.OpenMethod (container, ConstructorBuilder, Location, block.EndLocation);
2857 generate_debugging = true;
2861 // Classes can have base initializers and instance field initializers.
2863 if (container is Class){
2864 if ((ModFlags & Modifiers.STATIC) == 0){
2867 // If we use a "this (...)" constructor initializer, then
2868 // do not emit field initializers, they are initialized in the other constructor
2870 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
2871 container.EmitFieldInitializers (ec);
2874 if (Initializer != null)
2875 Initializer.Emit (ec);
2877 if ((ModFlags & Modifiers.STATIC) != 0)
2878 container.EmitFieldInitializers (ec);
2880 Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes);
2882 // If this is a non-static `struct' constructor and doesn't have any
2883 // initializer, it must initialize all of the struct's fields.
2884 if ((container is Struct) && ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
2885 Block.AddThisVariable (container, Location);
2887 ec.EmitTopBlock (block, ParameterInfo, Location);
2889 if (generate_debugging)
2897 // Encapsulates most of the Method's state
2899 public class MethodData {
2901 // The return type of this method
2903 public readonly Type ReturnType;
2904 public readonly Type[] ParameterTypes;
2905 public readonly InternalParameters ParameterInfo;
2906 public readonly CallingConventions CallingConventions;
2907 public readonly Attributes OptAttributes;
2908 public readonly Location Location;
2911 // Are we implementing an interface ?
2913 public bool IsImplementing = false;
2918 protected DeclSpace ds;
2919 protected MemberBase member;
2920 protected int modifiers;
2921 protected MethodAttributes flags;
2922 protected bool is_method;
2923 protected string accessor_name;
2926 // It can either hold a string with the condition, or an arraylist of conditions.
2927 object conditionals;
2929 MethodBuilder builder = null;
2930 public MethodBuilder MethodBuilder {
2936 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
2937 Type [] parameter_types, InternalParameters parameters,
2938 CallingConventions cc, Attributes opt_attrs,
2939 int modifiers, MethodAttributes flags, bool is_method)
2942 this.member = member;
2943 this.accessor_name = name;
2944 this.ReturnType = return_type;
2945 this.ParameterTypes = parameter_types;
2946 this.ParameterInfo = parameters;
2947 this.CallingConventions = cc;
2948 this.OptAttributes = opt_attrs;
2949 this.modifiers = modifiers;
2951 this.is_method = is_method;
2952 this.Location = member.Location;
2953 this.conditionals = null;
2956 public MethodData (DeclSpace ds, MemberBase member, string name, Type return_type,
2957 Type [] parameter_types, InternalParameters parameters,
2958 CallingConventions cc, Attributes opt_attrs,
2959 int modifiers, MethodAttributes flags, bool is_method,
2960 MethodBuilder builder)
2961 : this (ds, member, name, return_type, parameter_types, parameters,
2962 cc, opt_attrs, modifiers, flags, is_method)
2964 this.builder = builder;
2970 Attribute dllimport_attribute = null;
2971 string obsolete = null;
2972 bool obsolete_error = false;
2974 public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
2976 if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
2979 foreach (AttributeSection asec in opt_attrs.AttributeSections) {
2980 if (asec.Attributes == null)
2983 foreach (Attribute a in asec.Attributes) {
2984 if (a.Name == "Conditional") {
2985 if (!ApplyConditionalAttribute (a))
2987 } else if (a.Name == "Obsolete") {
2988 if (!ApplyObsoleteAttribute (a))
2990 } else if (a.Name.IndexOf ("DllImport") != -1) {
2992 a.Type = TypeManager.dllimport_type;
2993 Attribute.Error_AttributeNotValidForElement (a, Location);
2996 if (!ApplyDllImportAttribute (a))
3006 // Applies the `DllImport' attribute to the method.
3008 protected virtual bool ApplyDllImportAttribute (Attribute a)
3010 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3011 if ((modifiers & extern_static) != extern_static) {
3012 Report.Error (601, Location,
3013 "The DllImport attribute must be specified on a method " +
3014 "marked `static' and `extern'.");
3018 flags |= MethodAttributes.PinvokeImpl;
3019 dllimport_attribute = a;
3024 // Applies the `Obsolete' attribute to the method.
3026 protected virtual bool ApplyObsoleteAttribute (Attribute a)
3028 if (obsolete != null) {
3029 Report.Error (579, Location, "Duplicate `Obsolete' attribute");
3033 obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
3034 return obsolete != null;
3038 // Applies the `Conditional' attribute to the method.
3040 protected virtual bool ApplyConditionalAttribute (Attribute a)
3042 // The Conditional attribute is only valid on methods.
3044 Attribute.Error_AttributeNotValidForElement (a, Location);
3048 string condition = a.Conditional_GetConditionName ();
3050 if (condition == null)
3053 if (ReturnType != TypeManager.void_type) {
3054 Report.Error (578, Location,
3055 "Conditional not valid on `" + member.Name + "' " +
3056 "because its return type is not void");
3060 if ((modifiers & Modifiers.OVERRIDE) != 0) {
3061 Report.Error (243, Location,
3062 "Conditional not valid on `" + member.Name + "' " +
3063 "because it is an override method");
3067 if (member.IsExplicitImpl) {
3068 Report.Error (577, Location,
3069 "Conditional not valid on `" + member.Name + "' " +
3070 "because it is an explicit interface implementation");
3074 if (IsImplementing) {
3075 Report.Error (623, Location,
3076 "Conditional not valid on `" + member.Name + "' " +
3077 "because it is an interface method");
3082 // The likelyhood that the conditional will be more than 1 is very slim
3084 if (conditionals == null)
3085 conditionals = condition;
3086 else if (conditionals is string){
3087 string s = (string) conditionals;
3088 conditionals = new ArrayList ();
3089 ((ArrayList)conditionals).Add (s);
3091 ((ArrayList)conditionals).Add (condition);
3097 // Checks whether this method should be ignored due to its Conditional attributes.
3099 bool ShouldIgnore (Location loc)
3101 // When we're overriding a virtual method, we implicitly inherit the
3102 // Conditional attributes from our parent.
3103 if (member.ParentMethod != null) {
3104 TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
3105 member.ParentMethod, loc);
3107 if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
3111 if (conditionals != null){
3112 if (conditionals is string){
3113 if (RootContext.AllDefines [conditionals] == null)
3116 foreach (string condition in (ArrayList) conditionals)
3117 if (RootContext.AllDefines [condition] == null)
3125 // Returns the TypeManager.MethodFlags for this method.
3126 // This emits an error 619 / warning 618 if the method is obsolete.
3127 // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
3129 public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
3131 TypeManager.MethodFlags flags = 0;
3133 if (obsolete != null) {
3134 if (obsolete_error) {
3135 Report.Error (619, loc, "Method `" + member.Name +
3136 "' is obsolete: `" + obsolete + "'");
3137 return TypeManager.MethodFlags.IsObsoleteError;
3139 Report.Warning (618, loc, "Method `" + member.Name +
3140 "' is obsolete: `" + obsolete + "'");
3142 flags |= TypeManager.MethodFlags.IsObsolete;
3145 if (ShouldIgnore (loc))
3146 flags |= TypeManager.MethodFlags.ShouldIgnore;
3151 public virtual bool Define (TypeContainer container)
3153 MethodInfo implementing = null;
3154 string method_name, name, prefix;
3156 if (OptAttributes != null)
3157 if (!ApplyAttributes (OptAttributes, is_method))
3160 if (member.IsExplicitImpl)
3161 prefix = member.InterfaceType.FullName + ".";
3165 if (accessor_name != null)
3166 name = accessor_name + "_" + member.ShortName;
3168 name = member.ShortName;
3169 method_name = prefix + name;
3171 if (container.Pending != null){
3172 if (member is Indexer)
3173 implementing = container.Pending.IsInterfaceIndexer (
3174 member.InterfaceType, ReturnType, ParameterTypes);
3176 implementing = container.Pending.IsInterfaceMethod (
3177 member.InterfaceType, name, ReturnType, ParameterTypes);
3179 if (member.InterfaceType != null && implementing == null){
3180 TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
3187 // For implicit implementations, make sure we are public, for
3188 // explicit implementations, make sure we are private.
3190 if (implementing != null){
3192 // Setting null inside this block will trigger a more
3193 // verbose error reporting for missing interface implementations
3195 // The "candidate" function has been flagged already
3196 // but it wont get cleared
3198 if (member.IsExplicitImpl){
3199 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
3200 Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
3201 implementing = null;
3203 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
3204 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
3206 // If this is an interface method implementation,
3207 // check for public accessibility
3209 implementing = null;
3210 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
3211 // We may never be private.
3212 implementing = null;
3213 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
3215 // We may be protected if we're overriding something.
3217 implementing = null;
3222 // Static is not allowed
3224 if ((modifiers & Modifiers.STATIC) != 0){
3225 implementing = null;
3226 Modifiers.Error_InvalidModifier (Location, "static");
3231 // If implementing is still valid, set flags
3233 if (implementing != null){
3235 // When implementing interface methods, set NewSlot
3236 // unless, we are overwriting a method.
3238 if (implementing.DeclaringType.IsInterface){
3239 if ((modifiers & Modifiers.OVERRIDE) == 0)
3240 flags |= MethodAttributes.NewSlot;
3243 MethodAttributes.Virtual |
3244 MethodAttributes.HideBySig;
3246 // Set Final unless we're virtual, abstract or already overriding a method.
3247 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
3248 flags |= MethodAttributes.Final;
3250 // Get the method name from the explicit interface.
3251 if (member.InterfaceType != null) {
3252 name = implementing.Name;
3253 method_name = prefix + name;
3256 IsImplementing = true;
3260 // Create the MethodBuilder for the method
3262 if ((flags & MethodAttributes.PinvokeImpl) != 0) {
3263 if ((modifiers & Modifiers.STATIC) == 0) {
3264 Report.Error (601, Location,
3265 "The DllImport attribute must be specified on " +
3266 "a method marked 'static' and 'extern'.");
3270 EmitContext ec = new EmitContext (
3271 container, ds, Location, null, ReturnType, modifiers, false);
3273 builder = dllimport_attribute.DefinePInvokeMethod (
3274 ec, container.TypeBuilder, method_name, flags,
3275 ReturnType, ParameterTypes);
3276 } else if (builder == null)
3277 builder = container.TypeBuilder.DefineMethod (
3278 method_name, flags, CallingConventions,
3279 ReturnType, ParameterTypes);
3281 builder.SetGenericMethodSignature (ReturnType, ParameterTypes);
3283 if (builder == null)
3286 if ((modifiers & Modifiers.UNSAFE) != 0)
3287 builder.InitLocals = false;
3289 if (IsImplementing){
3291 // clear the pending implemntation flag
3293 if (member is Indexer) {
3294 container.Pending.ImplementIndexer (
3295 member.InterfaceType, builder, ReturnType,
3296 ParameterTypes, true);
3298 container.Pending.ImplementMethod (
3299 member.InterfaceType, name, ReturnType,
3300 ParameterTypes, member.IsExplicitImpl);
3302 if (member.IsExplicitImpl)
3303 container.TypeBuilder.DefineMethodOverride (
3304 builder, implementing);
3308 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
3309 Report.Error (111, Location,
3310 "Class `" + container.Name +
3311 "' already contains a definition with the " +
3312 "same return value and parameter types as the " +
3313 "'get' method of property `" + member.Name + "'");
3317 TypeManager.AddMethod (builder, this);
3325 public virtual void Emit (TypeContainer container, Block block, object kind)
3330 if ((flags & MethodAttributes.PinvokeImpl) == 0)
3331 ig = builder.GetILGenerator ();
3335 ec = new EmitContext (container, ds, Location, ig, ReturnType, modifiers, false);
3337 if (OptAttributes != null)
3338 Attribute.ApplyAttributes (ec, builder, kind, OptAttributes);
3340 if (member is MethodCore)
3341 MethodCore.LabelParameters (ec, MethodBuilder,
3342 ((MethodCore) member).Parameters,
3347 // abstract or extern methods have no bodies
3349 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
3350 if (block == null) {
3351 SymbolWriter sw = CodeGen.SymbolWriter;
3353 if ((sw != null) && ((modifiers & Modifiers.EXTERN) != 0)) {
3354 sw.OpenMethod (container, MethodBuilder, Location, Location);
3362 // abstract or extern methods have no bodies.
3364 if ((modifiers & Modifiers.ABSTRACT) != 0)
3366 500, Location, "Abstract method `" +
3367 TypeManager.CSharpSignature (builder) +
3368 "' can not have a body");
3370 if ((modifiers & Modifiers.EXTERN) != 0)
3372 179, Location, "External method `" +
3373 TypeManager.CSharpSignature (builder) +
3374 "' can not have a body");
3380 // Methods must have a body unless they're extern or abstract
3382 if (block == null) {
3384 501, Location, "Method `" +
3385 TypeManager.CSharpSignature (builder) +
3386 "' must declare a body since it is not marked " +
3387 "abstract or extern");
3392 // Handle destructors specially
3394 // FIXME: This code generates buggy code
3396 if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
3397 EmitDestructor (ec, block);
3399 SymbolWriter sw = CodeGen.SymbolWriter;
3401 if ((sw != null) && !Location.IsNull (Location) &&
3402 !Location.IsNull (block.EndLocation)) {
3403 sw.OpenMethod (container, MethodBuilder, Location, block.EndLocation);
3405 ec.EmitTopBlock (block, ParameterInfo, Location);
3409 ec.EmitTopBlock (block, ParameterInfo, Location);
3413 void EmitDestructor (EmitContext ec, Block block)
3415 ILGenerator ig = ec.ig;
3417 Label finish = ig.DefineLabel ();
3418 bool old_in_try = ec.InTry;
3420 ig.BeginExceptionBlock ();
3422 ec.ReturnLabel = finish;
3423 ec.HasReturnLabel = true;
3424 ec.EmitTopBlock (block, null, Location);
3425 ec.InTry = old_in_try;
3427 // ig.MarkLabel (finish);
3428 bool old_in_finally = ec.InFinally;
3429 ec.InFinally = true;
3430 ig.BeginFinallyBlock ();
3432 if (ec.ContainerType.BaseType != null) {
3433 Expression member_lookup = Expression.MemberLookup (
3434 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
3435 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, Location);
3437 if (member_lookup != null){
3438 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
3440 ig.Emit (OpCodes.Ldarg_0);
3441 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
3444 ec.InFinally = old_in_finally;
3446 ig.EndExceptionBlock ();
3447 //ig.MarkLabel (ec.ReturnLabel);
3448 ig.Emit (OpCodes.Ret);
3452 abstract public class MemberBase : MemberCore {
3453 public Expression Type;
3454 public readonly Attributes OptAttributes;
3456 protected MethodAttributes flags;
3459 // The "short" name of this property / indexer / event. This is the
3460 // name without the explicit interface.
3462 public string ShortName;
3465 // The type of this property / indexer / event
3467 public Type MemberType;
3470 // If true, this is an explicit interface implementation
3472 public bool IsExplicitImpl = false;
3475 // The name of the interface we are explicitly implementing
3477 public string ExplicitInterfaceName = null;
3480 // If true, the interface type we are explicitly implementing
3482 public Type InterfaceType = null;
3485 // The method we're overriding if this is an override method.
3487 protected MethodInfo parent_method = null;
3488 public MethodInfo ParentMethod {
3490 return parent_method;
3495 // The constructor is only exposed to our children
3497 protected MemberBase (Expression type, int mod, int allowed_mod, int def_mod, string name,
3498 Attributes attrs, Location loc)
3502 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
3503 OptAttributes = attrs;
3506 protected virtual bool CheckBase (TypeContainer container)
3508 if ((container is Struct) || (RootContext.WarningLevel > 3)){
3509 if ((ModFlags & Modifiers.PROTECTED) != 0 && (container.ModFlags & Modifiers.SEALED) != 0){
3510 if (container is Struct){
3511 Report.Error (666, Location, "Protected member in struct declaration");
3514 Report.Warning (628, Location, "Member " + container.MakeName (Name) + " protected in sealed class");
3520 protected void WarningNotHiding (TypeContainer parent)
3524 "The member " + parent.MakeName (Name) + " does not hide an " +
3525 "inherited member. The keyword new is not required");
3529 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
3533 // FIXME: report the old/new permissions?
3536 507, Location, parent.MakeName (Name) +
3537 ": can't change the access modifiers when overriding inherited " +
3538 "member `" + name + "'");
3542 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3543 // that have been defined.
3545 // `name' is the user visible name for reporting errors (this is used to
3546 // provide the right name regarding method names and properties)
3548 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
3549 MethodInfo mb, string name)
3553 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3554 if (!(mb.IsAbstract || mb.IsVirtual)){
3556 506, Location, parent.MakeName (Name) +
3557 ": cannot override inherited member `" +
3558 name + "' because it is not " +
3559 "virtual, abstract or override");
3563 // Now we check that the overriden method is not final
3566 // This happens when implementing interface methods.
3567 if (mb.IsHideBySig && mb.IsVirtual) {
3569 506, Location, parent.MakeName (Name) +
3570 ": cannot override inherited member `" +
3571 name + "' because it is not " +
3572 "virtual, abstract or override");
3574 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
3575 "override inherited member `" + name +
3576 "' because it is sealed.");
3580 // Check that the permissions are not being changed
3582 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
3583 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
3586 // special case for "protected internal"
3589 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3591 // when overriding protected internal, the method can be declared
3592 // protected internal only within the same assembly
3595 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3596 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
3598 // assemblies differ - report an error
3601 Error_CannotChangeAccessModifiers (parent, mb, name);
3603 } else if (thisp != parentp) {
3605 // same assembly, but other attributes differ - report an error
3608 Error_CannotChangeAccessModifiers (parent, mb, name);
3611 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3613 // if it's not "protected internal", it must be "protected"
3616 Error_CannotChangeAccessModifiers (parent, mb, name);
3618 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
3620 // protected within the same assembly - an error
3622 Error_CannotChangeAccessModifiers (parent, mb, name);
3624 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3625 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3627 // protected ok, but other attributes differ - report an error
3629 Error_CannotChangeAccessModifiers (parent, mb, name);
3633 if (thisp != parentp){
3634 Error_CannotChangeAccessModifiers (parent, mb, name);
3640 if (mb.IsVirtual || mb.IsAbstract){
3641 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3642 if (Name != "Finalize"){
3644 114, 2, Location, parent.MakeName (Name) +
3645 " hides inherited member `" + name +
3646 "'. To make the current member override that " +
3647 "implementation, add the override keyword, " +
3648 "otherwise use the new keyword");
3649 ModFlags |= Modifiers.NEW;
3653 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
3654 if (Name != "Finalize"){
3656 108, 1, Location, "The keyword new is required on " +
3657 parent.MakeName (Name) + " because it hides " +
3658 "inherited member `" + name + "'");
3659 ModFlags |= Modifiers.NEW;
3667 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
3671 foreach (Type partype in parameters){
3672 if (partype.IsPointer){
3675 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
3679 if (ds.AsAccessible (partype, ModFlags))
3682 if (this is Indexer)
3683 Report.Error (55, Location,
3684 "Inconsistent accessibility: parameter type `" +
3685 TypeManager.CSharpName (partype) + "' is less " +
3686 "accessible than indexer `" + Name + "'");
3687 else if ((this is Method) && ((Method) this).IsOperator)
3688 Report.Error (57, Location,
3689 "Inconsistent accessibility: parameter type `" +
3690 TypeManager.CSharpName (partype) + "' is less " +
3691 "accessible than operator `" + Name + "'");
3693 Report.Error (51, Location,
3694 "Inconsistent accessibility: parameter type `" +
3695 TypeManager.CSharpName (partype) + "' is less " +
3696 "accessible than method `" + Name + "'");
3703 protected virtual bool DoDefine (TypeContainer container)
3708 if (!container.MethodModifiersValid (ModFlags, Name, Location))
3711 flags = Modifiers.MethodAttr (ModFlags);
3713 // Lookup Type, verify validity
3714 MemberType = container.ResolveType (Type, false, Location);
3715 if (MemberType == null)
3718 if ((container.ModFlags & Modifiers.SEALED) != 0){
3719 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
3720 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
3725 // verify accessibility
3726 if (!container.AsAccessible (MemberType, ModFlags)) {
3727 if (this is Property)
3728 Report.Error (53, Location,
3729 "Inconsistent accessibility: property type `" +
3730 TypeManager.CSharpName (MemberType) + "' is less " +
3731 "accessible than property `" + Name + "'");
3732 else if (this is Indexer)
3733 Report.Error (54, Location,
3734 "Inconsistent accessibility: indexer return type `" +
3735 TypeManager.CSharpName (MemberType) + "' is less " +
3736 "accessible than indexer `" + Name + "'");
3737 else if (this is Method) {
3738 if (((Method) this).IsOperator)
3739 Report.Error (56, Location,
3740 "Inconsistent accessibility: return type `" +
3741 TypeManager.CSharpName (MemberType) + "' is less " +
3742 "accessible than operator `" + Name + "'");
3744 Report.Error (50, Location,
3745 "Inconsistent accessibility: return type `" +
3746 TypeManager.CSharpName (MemberType) + "' is less " +
3747 "accessible than method `" + Name + "'");
3749 Report.Error (52, Location,
3750 "Inconsistent accessibility: field type `" +
3751 TypeManager.CSharpName (MemberType) + "' is less " +
3752 "accessible than field `" + Name + "'");
3756 if (MemberType.IsPointer && !UnsafeOK (container))
3760 // Check for explicit interface implementation
3762 if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
3763 int pos = Name.LastIndexOf (".");
3765 ExplicitInterfaceName = Name.Substring (0, pos);
3766 ShortName = Name.Substring (pos + 1);
3770 if (ExplicitInterfaceName != null) {
3771 InterfaceType = RootContext.LookupType (
3772 container, ExplicitInterfaceName, false, Location);
3773 if (InterfaceType == null)
3776 // Compute the full name that we need to export.
3777 Name = InterfaceType.FullName + "." + ShortName;
3779 if (!container.VerifyImplements (InterfaceType, ShortName, Name, Location))
3782 IsExplicitImpl = true;
3784 IsExplicitImpl = false;
3791 // Fields and Events both generate FieldBuilders, we use this to share
3792 // their common bits. This is also used to flag usage of the field
3794 abstract public class FieldBase : MemberBase {
3795 public FieldBuilder FieldBuilder;
3796 public Status status;
3799 public enum Status : byte { ASSIGNED = 1, USED = 2 }
3802 // The constructor is only exposed to our children
3804 protected FieldBase (Expression type, int mod, int allowed_mod, string name,
3805 object init, Attributes attrs, Location loc)
3806 : base (type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs, loc)
3812 // Whether this field has an initializer.
3814 public bool HasInitializer {
3816 return init != null;
3820 public bool IsAssigned;
3822 protected readonly Object init;
3824 Expression init_expr;
3825 bool init_expr_initialized = false;
3828 // Resolves and returns the field initializer.
3830 public Expression GetInitializerExpression (EmitContext ec)
3832 if (init_expr_initialized)
3836 if (init is Expression)
3837 e = (Expression) init;
3839 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
3841 ec.IsFieldInitializer = true;
3842 e = e.DoResolve (ec);
3843 ec.IsFieldInitializer = false;
3846 init_expr_initialized = true;
3853 // The Field class is used to represents class/struct fields during parsing.
3855 public class Field : FieldBase {
3857 // Modifiers allowed in a class declaration
3859 const int AllowedModifiers =
3862 Modifiers.PROTECTED |
3863 Modifiers.INTERNAL |
3866 Modifiers.VOLATILE |
3870 public Field (Expression type, int mod, string name, Object expr_or_array_init,
3871 Attributes attrs, Location loc)
3872 : base (type, mod, AllowedModifiers, name, expr_or_array_init, attrs, loc)
3876 public override bool Define (TypeContainer container)
3878 Type t = container.ResolveType (Type, false, Location);
3883 CheckBase (container);
3885 if (!container.AsAccessible (t, ModFlags)) {
3886 Report.Error (52, Location,
3887 "Inconsistent accessibility: field type `" +
3888 TypeManager.CSharpName (t) + "' is less " +
3889 "accessible than field `" + Name + "'");
3893 if (t.IsPointer && !UnsafeOK (container))
3896 if (RootContext.WarningLevel > 1){
3897 Type ptype = container.TypeBuilder.BaseType;
3899 // ptype is only null for System.Object while compiling corlib.
3901 TypeContainer.FindMembers (
3902 ptype, MemberTypes.Method,
3903 BindingFlags.Public |
3904 BindingFlags.Static | BindingFlags.Instance,
3905 System.Type.FilterName, Name);
3909 if ((ModFlags & Modifiers.VOLATILE) != 0){
3913 if (TypeManager.IsEnumType (vt))
3914 vt = TypeManager.EnumToUnderlying (t);
3916 if (!((vt == TypeManager.bool_type) ||
3917 (vt == TypeManager.sbyte_type) ||
3918 (vt == TypeManager.byte_type) ||
3919 (vt == TypeManager.short_type) ||
3920 (vt == TypeManager.ushort_type) ||
3921 (vt == TypeManager.int32_type) ||
3922 (vt == TypeManager.uint32_type) ||
3923 (vt == TypeManager.char_type) ||
3924 (vt == TypeManager.float_type))){
3926 677, Location, container.MakeName (Name) +
3927 " A volatile field can not be of type `" +
3928 TypeManager.CSharpName (vt) + "'");
3933 if ((ModFlags & Modifiers.READONLY) != 0){
3936 "A field can not be both volatile and readonly");
3941 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
3943 if (container is Struct &&
3944 ((fa & FieldAttributes.Static) == 0) &&
3945 t == container.TypeBuilder &&
3946 !TypeManager.IsBuiltinType (t)){
3947 Report.Error (523, Location, "Struct member `" + container.Name + "." + Name +
3948 "' causes a cycle in the structure layout");
3952 FieldBuilder = container.TypeBuilder.DefineField (
3953 Name, t, Modifiers.FieldAttr (ModFlags));
3955 TypeManager.RegisterFieldBase (FieldBuilder, this);
3959 public void Emit (TypeContainer tc)
3961 EmitContext ec = new EmitContext (tc, Location, null,
3962 FieldBuilder.FieldType, ModFlags);
3964 Attribute.ApplyAttributes (ec, FieldBuilder, this, OptAttributes);
3969 // `set' and `get' accessors are represented with an Accessor.
3971 public class Accessor {
3973 // Null if the accessor is empty, or a Block if not
3976 public Attributes OptAttributes;
3978 public Accessor (Block b, Attributes attrs)
3981 OptAttributes = attrs;
3986 // Properties and Indexers both generate PropertyBuilders, we use this to share
3987 // their common bits.
3989 abstract public class PropertyBase : MethodCore {
3990 public Accessor Get, Set;
3991 public PropertyBuilder PropertyBuilder;
3992 public MethodBuilder GetBuilder, SetBuilder;
3993 public MethodData GetData, SetData;
3995 protected EmitContext ec;
3997 public PropertyBase (DeclSpace ds, Expression type, string name, int mod_flags,
3998 int allowed_mod, Parameters parameters,
3999 Accessor get_block, Accessor set_block,
4000 Attributes attrs, Location loc)
4001 : base (ds, type, mod_flags, allowed_mod, name, attrs, parameters, loc)
4007 protected override bool DoDefine (TypeContainer container)
4009 if (!base.DoDefine (container))
4012 ec = new EmitContext (container, Location, null, MemberType, ModFlags);
4018 // Checks our base implementation if any
4020 protected override bool CheckBase (TypeContainer container)
4022 base.CheckBase (container);
4024 // Check whether arguments were correct.
4025 if (!DoDefineParameters ())
4032 MethodSignature ms, base_ms;
4033 if (this is Indexer) {
4034 string name, base_name;
4036 report_name = "this";
4037 name = TypeManager.IndexerPropertyName (container.TypeBuilder);
4038 ms = new MethodSignature (name, null, ParameterTypes);
4039 base_name = TypeManager.IndexerPropertyName (container.TypeBuilder.BaseType);
4040 base_ms = new MethodSignature (base_name, null, ParameterTypes);
4043 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
4047 // Verify if the parent has a type with the same name, and then
4048 // check whether we have to create a new slot for it or not.
4050 Type ptype = container.TypeBuilder.BaseType;
4052 // ptype is only null for System.Object while compiling corlib.
4053 if (ptype == null) {
4054 if ((ModFlags & Modifiers.NEW) != 0)
4055 WarningNotHiding (container);
4060 MemberList props_this;
4062 props_this = TypeContainer.FindMembers (
4063 container.TypeBuilder, MemberTypes.Property,
4064 BindingFlags.NonPublic | BindingFlags.Public |
4065 BindingFlags.Static | BindingFlags.Instance |
4066 BindingFlags.DeclaredOnly,
4067 MethodSignature.method_signature_filter, ms);
4069 if (props_this.Count > 0) {
4070 Report.Error (111, Location, "Class `" + container.Name + "' " +
4071 "already defines a member called `" + report_name + "' " +
4072 "with the same parameter types");
4076 MemberList mi_props;
4078 mi_props = TypeContainer.FindMembers (
4079 ptype, MemberTypes.Property,
4080 BindingFlags.NonPublic | BindingFlags.Public |
4081 BindingFlags.Instance | BindingFlags.Static,
4082 MethodSignature.inheritable_method_signature_filter, base_ms);
4084 if (mi_props.Count > 0){
4085 PropertyInfo parent_property = (PropertyInfo) mi_props [0];
4086 string name = parent_property.DeclaringType.Name + "." +
4087 parent_property.Name;
4089 MethodInfo get, set, parent_method;
4090 get = parent_property.GetGetMethod (true);
4091 set = parent_property.GetSetMethod (true);
4094 parent_method = get;
4095 else if (set != null)
4096 parent_method = set;
4098 throw new Exception ("Internal error!");
4100 if (!CheckMethodAgainstBase (container, flags, parent_method, name))
4103 if ((ModFlags & Modifiers.NEW) == 0) {
4104 Type parent_type = TypeManager.TypeToCoreType (
4105 parent_property.PropertyType);
4107 if (parent_type != MemberType) {
4109 508, Location, container.MakeName (Name) + ": cannot " +
4110 "change return type when overriding " +
4111 "inherited member " + name);
4116 if ((ModFlags & Modifiers.NEW) != 0)
4117 WarningNotHiding (container);
4119 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4120 if (this is Indexer)
4121 Report.Error (115, Location,
4122 container.MakeName (Name) +
4123 " no suitable indexers found to override");
4125 Report.Error (115, Location,
4126 container.MakeName (Name) +
4127 " no suitable properties found to override");
4134 public void Emit (TypeContainer tc)
4137 // The PropertyBuilder can be null for explicit implementations, in that
4138 // case, we do not actually emit the ".property", so there is nowhere to
4139 // put the attribute
4141 if (PropertyBuilder != null)
4142 Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes);
4144 if (GetData != null) {
4145 GetData.Emit (tc, Get.Block, Get);
4149 if (SetData != null) {
4150 SetData.Emit (tc, Set.Block, Set);
4156 public class Property : PropertyBase {
4157 const int AllowedModifiers =
4160 Modifiers.PROTECTED |
4161 Modifiers.INTERNAL |
4165 Modifiers.OVERRIDE |
4166 Modifiers.ABSTRACT |
4171 public Property (DeclSpace ds, Expression type, string name, int mod_flags,
4172 Accessor get_block, Accessor set_block,
4173 Attributes attrs, Location loc)
4174 : base (ds, type, name, mod_flags, AllowedModifiers,
4175 Parameters.EmptyReadOnlyParameters,
4176 get_block, set_block, attrs, loc)
4180 public override bool Define (TypeContainer container)
4182 if (!DoDefine (container))
4185 if (!CheckBase (container))
4188 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4191 Type [] parameters = TypeManager.NoTypes;
4193 InternalParameters ip = new InternalParameters (
4194 container, Parameters.EmptyReadOnlyParameters);
4196 GetData = new MethodData (container, this, "get", MemberType,
4197 parameters, ip, CallingConventions.Standard,
4198 Get.OptAttributes, ModFlags, flags, false);
4200 if (!GetData.Define (container))
4203 GetBuilder = GetData.MethodBuilder;
4207 Type [] parameters = new Type [1];
4208 parameters [0] = MemberType;
4210 Parameter [] parms = new Parameter [1];
4211 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4212 InternalParameters ip = new InternalParameters (
4213 container, new Parameters (parms, null, Location));
4215 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4216 parameters, ip, CallingConventions.Standard,
4217 Set.OptAttributes, ModFlags, flags, false);
4219 if (!SetData.Define (container))
4222 SetBuilder = SetData.MethodBuilder;
4223 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4226 // FIXME - PropertyAttributes.HasDefault ?
4228 PropertyAttributes prop_attr =
4229 PropertyAttributes.RTSpecialName |
4230 PropertyAttributes.SpecialName;
4232 if (!IsExplicitImpl){
4233 PropertyBuilder = container.TypeBuilder.DefineProperty (
4234 Name, prop_attr, MemberType, null);
4237 PropertyBuilder.SetGetMethod (GetBuilder);
4240 PropertyBuilder.SetSetMethod (SetBuilder);
4243 // HACK for the reasons exposed above
4245 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
4248 "Class `" + container.Name +
4249 "' already contains a definition for the property `" +
4259 /// Gigantic workaround for lameness in SRE follows :
4260 /// This class derives from EventInfo and attempts to basically
4261 /// wrap around the EventBuilder so that FindMembers can quickly
4262 /// return this in it search for members
4264 public class MyEventBuilder : EventInfo {
4267 // We use this to "point" to our Builder which is
4268 // not really a MemberInfo
4270 EventBuilder MyBuilder;
4273 // We "catch" and wrap these methods
4275 MethodInfo raise, remove, add;
4277 EventAttributes attributes;
4278 Type declaring_type, reflected_type, event_type;
4283 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4285 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4287 // And now store the values in our own fields.
4289 declaring_type = type_builder;
4291 reflected_type = type_builder;
4293 attributes = event_attr;
4296 this.event_type = event_type;
4300 // Methods that you have to override. Note that you only need
4301 // to "implement" the variants that take the argument (those are
4302 // the "abstract" methods, the others (GetAddMethod()) are
4305 public override MethodInfo GetAddMethod (bool nonPublic)
4310 public override MethodInfo GetRemoveMethod (bool nonPublic)
4315 public override MethodInfo GetRaiseMethod (bool nonPublic)
4321 // These methods make "MyEventInfo" look like a Builder
4323 public void SetRaiseMethod (MethodBuilder raiseMethod)
4325 raise = raiseMethod;
4326 MyBuilder.SetRaiseMethod (raiseMethod);
4329 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4331 remove = removeMethod;
4332 MyBuilder.SetRemoveOnMethod (removeMethod);
4335 public void SetAddOnMethod (MethodBuilder addMethod)
4338 MyBuilder.SetAddOnMethod (addMethod);
4341 public void SetCustomAttribute (CustomAttributeBuilder cb)
4343 MyBuilder.SetCustomAttribute (cb);
4346 public override object [] GetCustomAttributes (bool inherit)
4348 // FIXME : There's nothing which can be seemingly done here because
4349 // we have no way of getting at the custom attribute objects of the
4354 public override object [] GetCustomAttributes (Type t, bool inherit)
4356 // FIXME : Same here !
4360 public override bool IsDefined (Type t, bool b)
4365 public override EventAttributes Attributes {
4371 public override string Name {
4377 public override Type DeclaringType {
4379 return declaring_type;
4383 public override Type ReflectedType {
4385 return reflected_type;
4389 public Type EventType {
4395 public void SetUsed ()
4397 if (my_event != null)
4398 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
4402 public class Event : FieldBase {
4403 const int AllowedModifiers =
4406 Modifiers.PROTECTED |
4407 Modifiers.INTERNAL |
4412 Modifiers.OVERRIDE |
4416 public readonly Accessor Add;
4417 public readonly Accessor Remove;
4418 public MyEventBuilder EventBuilder;
4420 MethodBuilder AddBuilder, RemoveBuilder;
4421 MethodData AddData, RemoveData;
4423 public Event (Expression type, string name, Object init, int mod, Accessor add,
4424 Accessor remove, Attributes attrs, Location loc)
4425 : base (type, mod, AllowedModifiers, name, init, attrs, loc)
4431 public override bool Define (TypeContainer container)
4433 EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
4434 MethodAttributes m_attr = MethodAttributes.HideBySig | MethodAttributes.SpecialName
4436 if (!DoDefine (container))
4439 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
4440 Report.Error (74, Location, "'" + container.Name + "." + Name +
4441 "': abstract event can not have an initializer");
4445 if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
4446 Report.Error (66, Location, "'" + container.Name + "." + Name +
4447 "' : event must be of a delegate type");
4451 Type [] parameter_types = new Type [1];
4452 parameter_types [0] = MemberType;
4454 Parameter [] parms = new Parameter [1];
4455 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
4456 InternalParameters ip = new InternalParameters (
4457 container, new Parameters (parms, null, Location));
4459 if (!CheckBase (container))
4463 // Now define the accessors
4465 AddData = new MethodData (container, this, "add", TypeManager.void_type,
4466 parameter_types, ip, CallingConventions.Standard,
4467 (Add != null) ? Add.OptAttributes : null,
4468 ModFlags, flags | m_attr, false);
4470 if (!AddData.Define (container))
4473 AddBuilder = AddData.MethodBuilder;
4474 AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4476 RemoveData = new MethodData (container, this, "remove", TypeManager.void_type,
4477 parameter_types, ip, CallingConventions.Standard,
4478 (Remove != null) ? Remove.OptAttributes : null,
4479 ModFlags, flags | m_attr, false);
4481 if (!RemoveData.Define (container))
4484 RemoveBuilder = RemoveData.MethodBuilder;
4485 RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
4487 if (!IsExplicitImpl){
4488 EventBuilder = new MyEventBuilder (this,
4489 container.TypeBuilder, Name, e_attr, MemberType);
4491 if (Add == null && Remove == null) {
4492 FieldBuilder = container.TypeBuilder.DefineField (
4494 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
4495 TypeManager.RegisterPrivateFieldOfEvent (
4496 (EventInfo) EventBuilder, FieldBuilder);
4497 TypeManager.RegisterFieldBase (FieldBuilder, this);
4500 EventBuilder.SetAddOnMethod (AddBuilder);
4501 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4503 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
4504 Report.Error (111, Location,
4505 "Class `" + container.Name +
4506 "' already contains a definition for the event `" +
4515 void EmitDefaultMethod (EmitContext ec, bool is_add)
4517 ILGenerator ig = ec.ig;
4518 MethodInfo method = null;
4521 method = TypeManager.delegate_combine_delegate_delegate;
4523 method = TypeManager.delegate_remove_delegate_delegate;
4525 if ((ModFlags & Modifiers.STATIC) != 0) {
4526 ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
4527 ig.Emit (OpCodes.Ldarg_0);
4528 ig.Emit (OpCodes.Call, method);
4529 ig.Emit (OpCodes.Castclass, MemberType);
4530 ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
4532 ig.Emit (OpCodes.Ldarg_0);
4533 ig.Emit (OpCodes.Ldarg_0);
4534 ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
4535 ig.Emit (OpCodes.Ldarg_1);
4536 ig.Emit (OpCodes.Call, method);
4537 ig.Emit (OpCodes.Castclass, MemberType);
4538 ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
4540 ig.Emit (OpCodes.Ret);
4543 public void Emit (TypeContainer tc)
4547 ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
4548 Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes);
4551 AddData.Emit (tc, Add.Block, Add);
4554 ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
4555 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4556 EmitDefaultMethod (ec, true);
4559 if (Remove != null) {
4560 RemoveData.Emit (tc, Remove.Block, Remove);
4561 Remove.Block = null;
4563 ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
4564 ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
4565 EmitDefaultMethod (ec, false);
4572 // FIXME: This does not handle:
4574 // int INTERFACENAME [ args ]
4579 // int this [ args ]
4581 public class Indexer : PropertyBase {
4583 const int AllowedModifiers =
4586 Modifiers.PROTECTED |
4587 Modifiers.INTERNAL |
4591 Modifiers.OVERRIDE |
4596 public string IndexerName;
4597 public string InterfaceIndexerName;
4600 // Are we implementing an interface ?
4602 bool IsImplementing = false;
4604 public Indexer (DeclSpace ds, Expression type, string int_type, int flags,
4605 Parameters parameters, Accessor get_block, Accessor set_block,
4606 Attributes attrs, Location loc)
4607 : base (ds, type, "", flags, AllowedModifiers, parameters, get_block, set_block,
4610 ExplicitInterfaceName = int_type;
4613 public override bool Define (TypeContainer container)
4615 PropertyAttributes prop_attr =
4616 PropertyAttributes.RTSpecialName |
4617 PropertyAttributes.SpecialName;
4619 if (!DoDefine (container))
4622 IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
4623 if (IndexerName == null)
4624 IndexerName = "Item";
4625 else if (IsExplicitImpl)
4626 Report.Error (592, Location,
4627 "Attribute 'IndexerName' is not valid on this declaration " +
4628 "type. It is valid on `property' declarations only.");
4630 ShortName = IndexerName;
4631 if (IsExplicitImpl) {
4632 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
4633 Name = InterfaceType.FullName + "." + IndexerName;
4635 InterfaceIndexerName = IndexerName;
4639 if (!CheckBase (container))
4642 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4644 InternalParameters ip = new InternalParameters (container, Parameters);
4646 GetData = new MethodData (container, this, "get", MemberType,
4647 ParameterTypes, ip, CallingConventions.Standard,
4648 Get.OptAttributes, ModFlags, flags, false);
4650 if (!GetData.Define (container))
4653 GetBuilder = GetData.MethodBuilder;
4657 int top = ParameterTypes.Length;
4658 Type [] set_pars = new Type [top + 1];
4659 ParameterTypes.CopyTo (set_pars, 0);
4660 set_pars [top] = MemberType;
4662 Parameter [] fixed_parms = Parameters.FixedParameters;
4664 if (fixed_parms == null){
4665 throw new Exception ("We currently do not support only array arguments in an indexer at: " + Location);
4666 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4667 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4669 // Here is the problem: the `value' parameter has
4670 // to come *after* the array parameter in the declaration
4672 // X (object [] x, Type value)
4675 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4676 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
4680 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
4683 fixed_parms.CopyTo (tmp, 0);
4684 tmp [fixed_parms.Length] = new Parameter (
4685 Type, "value", Parameter.Modifier.NONE, null);
4687 Parameters set_formal_params = new Parameters (tmp, null, Location);
4689 InternalParameters ip = new InternalParameters (container, set_formal_params);
4691 SetData = new MethodData (container, this, "set", TypeManager.void_type,
4692 set_pars, ip, CallingConventions.Standard,
4693 Set.OptAttributes, ModFlags, flags, false);
4695 if (!SetData.Define (container))
4698 SetBuilder = SetData.MethodBuilder;
4702 // Now name the parameters
4704 Parameter [] p = Parameters.FixedParameters;
4708 for (i = 0; i < p.Length; ++i) {
4710 GetBuilder.DefineParameter (
4711 i + 1, p [i].Attributes, p [i].Name);
4714 SetBuilder.DefineParameter (
4715 i + 1, p [i].Attributes, p [i].Name);
4719 SetBuilder.DefineParameter (
4720 i + 1, ParameterAttributes.None, "value");
4722 if (i != ParameterTypes.Length) {
4723 Parameter array_param = Parameters.ArrayParameter;
4725 SetBuilder.DefineParameter (
4726 i + 1, array_param.Attributes, array_param.Name);
4730 if (GetData != null)
4731 IsImplementing = GetData.IsImplementing;
4732 else if (SetData != null)
4733 IsImplementing = SetData.IsImplementing;
4736 // Define the PropertyBuilder if one of the following conditions are met:
4737 // a) we're not implementing an interface indexer.
4738 // b) the indexer has a different IndexerName and this is no
4739 // explicit interface implementation.
4741 if (!IsExplicitImpl) {
4742 PropertyBuilder = container.TypeBuilder.DefineProperty (
4743 IndexerName, prop_attr, MemberType, ParameterTypes);
4745 if (GetData != null)
4746 PropertyBuilder.SetGetMethod (GetBuilder);
4748 if (SetData != null)
4749 PropertyBuilder.SetSetMethod (SetBuilder);
4751 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
4759 public class Operator : MemberBase {
4761 const int AllowedModifiers =
4767 const int RequiredModifiers =
4771 public enum OpType : byte {
4781 // Unary and Binary operators
4804 // Implicit and Explicit
4809 public readonly OpType OperatorType;
4810 public readonly Expression ReturnType;
4811 public readonly Expression FirstArgType, SecondArgType;
4812 public readonly string FirstArgName, SecondArgName;
4814 public MethodBuilder OperatorMethodBuilder;
4816 public string MethodName;
4817 public Method OperatorMethod;
4819 public Operator (OpType type, Expression ret_type, int mod_flags,
4820 Expression arg1type, string arg1name,
4821 Expression arg2type, string arg2name,
4822 Block block, Attributes attrs, Location loc)
4823 : base (ret_type, mod_flags, AllowedModifiers, Modifiers.PUBLIC, "", attrs, loc)
4825 OperatorType = type;
4826 ReturnType = ret_type;
4827 FirstArgType = arg1type;
4828 FirstArgName = arg1name;
4829 SecondArgType = arg2type;
4830 SecondArgName = arg2name;
4834 string Prototype (TypeContainer container)
4836 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
4837 SecondArgType + ")";
4840 public override bool Define (TypeContainer container)
4843 MethodName = "op_" + OperatorType;
4845 if (SecondArgType != null)
4848 Parameter [] param_list = new Parameter [length];
4850 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
4853 "User defined operators `" +
4854 Prototype (container) +
4855 "' must be declared static and public");
4859 param_list[0] = new Parameter (FirstArgType, FirstArgName,
4860 Parameter.Modifier.NONE, null);
4861 if (SecondArgType != null)
4862 param_list[1] = new Parameter (SecondArgType, SecondArgName,
4863 Parameter.Modifier.NONE, null);
4865 OperatorMethod = new Method (container, ReturnType, ModFlags, MethodName,
4866 new Parameters (param_list, null, Location),
4867 OptAttributes, Location);
4869 OperatorMethod.IsOperator = true;
4870 OperatorMethod.Define (container);
4872 if (OperatorMethod.MethodBuilder == null)
4875 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
4877 Type [] param_types = OperatorMethod.ParameterTypes;
4878 Type declaring_type = OperatorMethodBuilder.DeclaringType;
4879 Type return_type = OperatorMethod.GetReturnType ();
4880 Type first_arg_type = param_types [0];
4882 // Rules for conversion operators
4884 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
4885 if (first_arg_type == return_type && first_arg_type == declaring_type){
4888 "User-defined conversion cannot take an object of the " +
4889 "enclosing type and convert to an object of the enclosing" +
4894 if (first_arg_type != declaring_type && return_type != declaring_type){
4897 "User-defined conversion must convert to or from the " +
4902 if (first_arg_type == TypeManager.object_type ||
4903 return_type == TypeManager.object_type){
4906 "User-defined conversion cannot convert to or from " +
4911 if (first_arg_type.IsInterface || return_type.IsInterface){
4914 "User-defined conversion cannot convert to or from an " +
4919 if (first_arg_type.IsSubclassOf (return_type) ||
4920 return_type.IsSubclassOf (first_arg_type)){
4923 "User-defined conversion cannot convert between types " +
4924 "that derive from each other");
4927 } else if (SecondArgType == null) {
4928 // Checks for Unary operators
4930 if (first_arg_type != declaring_type){
4933 "The parameter of a unary operator must be the " +
4938 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
4939 if (return_type != declaring_type){
4942 "The parameter and return type for ++ and -- " +
4943 "must be the containing type");
4949 if (OperatorType == OpType.True || OperatorType == OpType.False) {
4950 if (return_type != TypeManager.bool_type){
4953 "The return type of operator True or False " +
4960 // Checks for Binary operators
4962 if (first_arg_type != declaring_type &&
4963 param_types [1] != declaring_type){
4966 "One of the parameters of a binary operator must " +
4967 "be the containing type");
4975 public void Emit (TypeContainer container)
4978 // abstract or extern methods have no bodies
4980 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
4983 OperatorMethod.Block = Block;
4984 OperatorMethod.Emit (container);
4988 public static string GetName (OpType ot)
4991 case OpType.LogicalNot:
4993 case OpType.OnesComplement:
4995 case OpType.Increment:
4997 case OpType.Decrement:
5003 case OpType.Addition:
5005 case OpType.Subtraction:
5007 case OpType.UnaryPlus:
5009 case OpType.UnaryNegation:
5011 case OpType.Multiply:
5013 case OpType.Division:
5015 case OpType.Modulus:
5017 case OpType.BitwiseAnd:
5019 case OpType.BitwiseOr:
5021 case OpType.ExclusiveOr:
5023 case OpType.LeftShift:
5025 case OpType.RightShift:
5027 case OpType.Equality:
5029 case OpType.Inequality:
5031 case OpType.GreaterThan:
5033 case OpType.LessThan:
5035 case OpType.GreaterThanOrEqual:
5037 case OpType.LessThanOrEqual:
5039 case OpType.Implicit:
5041 case OpType.Explicit:
5047 public override string ToString ()
5049 Type return_type = OperatorMethod.GetReturnType();
5050 Type [] param_types = OperatorMethod.ParameterTypes;
5052 if (SecondArgType == null)
5053 return String.Format (
5054 "{0} operator {1}({2})",
5055 TypeManager.CSharpName (return_type),
5056 GetName (OperatorType),
5059 return String.Format (
5060 "{0} operator {1}({2}, {3})",
5061 TypeManager.CSharpName (return_type),
5062 GetName (OperatorType),
5063 param_types [0], param_types [1]);
5068 // This is used to compare method signatures
5070 struct MethodSignature {
5072 public Type RetType;
5073 public Type [] Parameters;
5076 /// This delegate is used to extract methods which have the
5077 /// same signature as the argument
5079 public static MemberFilter method_signature_filter;
5082 /// This delegate is used to extract inheritable methods which
5083 /// have the same signature as the argument. By inheritable,
5084 /// this means that we have permissions to override the method
5085 /// from the current assembly and class
5087 public static MemberFilter inheritable_method_signature_filter;
5089 static MethodSignature ()
5091 method_signature_filter = new MemberFilter (MemberSignatureCompare);
5092 inheritable_method_signature_filter = new MemberFilter (
5093 InheritableMemberSignatureCompare);
5096 public MethodSignature (string name, Type ret_type, Type [] parameters)
5101 if (parameters == null)
5102 Parameters = TypeManager.NoTypes;
5104 Parameters = parameters;
5107 public override string ToString ()
5110 if (Parameters.Length != 0){
5111 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
5112 for (int i = 0; i < Parameters.Length; i++){
5113 sb.Append (Parameters [i]);
5114 if (i+1 < Parameters.Length)
5117 pars = sb.ToString ();
5120 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
5123 public override int GetHashCode ()
5125 return Name.GetHashCode ();
5128 public override bool Equals (Object o)
5130 MethodSignature other = (MethodSignature) o;
5132 if (other.Name != Name)
5135 if (other.RetType != RetType)
5138 if (Parameters == null){
5139 if (other.Parameters == null)
5144 if (other.Parameters == null)
5147 int c = Parameters.Length;
5148 if (other.Parameters.Length != c)
5151 for (int i = 0; i < c; i++)
5152 if (other.Parameters [i] != Parameters [i])
5158 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
5160 MethodSignature sig = (MethodSignature) filter_criteria;
5162 if (m.Name != sig.Name)
5166 MethodInfo mi = m as MethodInfo;
5167 PropertyInfo pi = m as PropertyInfo;
5170 ReturnType = mi.ReturnType;
5171 else if (pi != null)
5172 ReturnType = pi.PropertyType;
5177 // we use sig.RetType == null to mean `do not check the
5178 // method return value.
5180 if (sig.RetType != null)
5181 if (ReturnType != sig.RetType)
5186 args = TypeManager.GetArgumentTypes (mi);
5188 args = TypeManager.GetArgumentTypes (pi);
5189 Type [] sigp = sig.Parameters;
5191 if (args.Length != sigp.Length)
5194 for (int i = args.Length; i > 0; ){
5196 if (args [i] != sigp [i])
5203 // This filter should be used when we are requesting methods that
5204 // we want to override.
5206 // This makes a number of assumptions, for example
5207 // that the methods being extracted are of a parent
5208 // class (this means we know implicitly that we are
5209 // being called to find out about members by a derived
5212 static bool InheritableMemberSignatureCompare (MemberInfo m, object filter_criteria)
5215 PropertyInfo pi = m as PropertyInfo;
5218 mi = pi.GetGetMethod (true);
5220 mi = pi.GetSetMethod (true);
5222 mi = m as MethodInfo;
5225 Console.WriteLine ("Nothing found");
5228 MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
5230 // If only accessible to the current class.
5231 if (prot == MethodAttributes.Private)
5234 if (!MemberSignatureCompare (m, filter_criteria))
5237 // If only accessible to the defining assembly or
5238 if (prot == MethodAttributes.FamANDAssem ||
5239 prot == MethodAttributes.Assembly){
5240 if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
5246 // Anything else (FamOrAssembly and Public) is fine