2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@gnome.org)
6 // Marek Safar (marek.safar@seznam.cz)
8 // Licensed under the terms of the GNU GPL
10 // (C) 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
13 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
15 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
16 // have fixed a remaining problem: not every AddXXXX was adding a
17 // fully qualified name.
19 // Now everyone registers a fully qualified name in the DeclSpace as
20 // being defined instead of the partial name.
22 // Downsides: we are slower than we need to be due to the excess
23 // copies and the names being registered this way.
25 // The reason for this is that we currently depend (on the corlib
26 // bootstrap for instance) that types are fully qualified, because
27 // we dump all the types in the namespace, and we should really have
28 // types inserted into the proper namespace, so we can only store the
29 // basenames in the defined_names array.
35 using System.Collections;
36 using System.Reflection;
37 using System.Reflection.Emit;
38 using System.Runtime.CompilerServices;
39 using System.Runtime.InteropServices;
41 using Mono.CompilerServices.SymbolWriter;
43 namespace Mono.CSharp {
53 /// This is the base class for structs and classes.
55 public abstract class TypeContainer : DeclSpace, IMemberContainer {
57 // Whether this is a struct, class or interface
58 public readonly Kind Kind;
60 // Holds a list of classes and structures
63 // Holds the list of properties
66 // Holds the list of enumerations
69 // Holds the list of delegates
72 // Holds the list of constructors
73 ArrayList instance_constructors;
75 // Holds the list of fields
78 // Holds a list of fields that have initializers
79 ArrayList initialized_fields;
81 // Holds a list of static fields that have initializers
82 ArrayList initialized_static_fields;
84 // Holds the list of constants
99 // Holds the operators
102 // Holds the iterators
105 // Holds the parts of a partial class;
108 // The emit context for toplevel objects.
112 // Pointers to the default constructor and the default static constructor
114 Constructor default_constructor;
115 Constructor default_static_constructor;
118 // Whether we have seen a static constructor for this class or not
120 public bool UserDefinedStaticConstructor = false;
123 // Whether we have at least one non-static field
125 bool have_nonstatic_fields = false;
128 // This one is computed after we can distinguish interfaces
129 // from classes from the arraylist `type_bases'
131 string base_class_name;
132 TypeExpr parent_type;
134 ArrayList type_bases;
136 bool members_defined;
137 bool members_defined_ok;
139 // The interfaces we implement.
142 // The parent member container and our member cache
143 IMemberContainer parent_container;
144 MemberCache member_cache;
147 // The indexer name for this class
149 public string IndexerName;
153 public TypeContainer (NamespaceEntry ns, TypeContainer parent,
154 MemberName name, Attributes attrs, Kind kind, Location l)
155 : base (ns, parent, name, attrs, l)
159 types = new ArrayList ();
161 base_class_name = null;
165 // Used to report back to the user the result of a declaration
166 // in the current declaration space
168 public void CheckDef (AdditionResult result, string name, Location loc)
170 if (result == AdditionResult.Success)
174 case AdditionResult.NameExists:
175 Report.Error (102, loc, "The container `{0}' already " +
176 "contains a definition for `{1}'",
181 // This is handled only for static Constructors, because
182 // in reality we handle these by the semantic analysis later
184 case AdditionResult.MethodExists:
185 Report.Error (111, loc, "Class `{0}' already defines a " +
186 "member called '{1}' with the same parameter " +
187 "types (more than one default constructor)",
191 case AdditionResult.EnclosingClash:
192 Report.Error (542, loc, "Member names cannot be the same " +
193 "as their enclosing type");
196 case AdditionResult.NotAConstructor:
197 Report.Error (1520, loc, "Class, struct, or interface method " +
198 "must have a return type");
201 case AdditionResult.Error:
202 // Error has already been reported.
207 public AdditionResult AddConstant (Const constant)
210 string basename = constant.Name;
211 string fullname = Name + "." + basename;
213 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
216 if (constants == null)
217 constants = new ArrayList ();
219 constants.Add (constant);
220 DefineName (fullname, constant);
222 return AdditionResult.Success;
225 public AdditionResult AddEnum (Mono.CSharp.Enum e)
229 if ((res = IsValid (e.Basename, e.Name)) != AdditionResult.Success)
233 enums = new ArrayList ();
236 DefineName (e.Name, e);
238 return AdditionResult.Success;
241 public AdditionResult AddClass (TypeContainer c)
244 string name = c.Basename;
246 if ((res = IsValid (name, c.Name)) != AdditionResult.Success)
249 DefineName (c.Name, c);
252 return AdditionResult.Success;
255 public AdditionResult AddStruct (TypeContainer s)
258 string name = s.Basename;
260 if ((res = IsValid (name, s.Name)) != AdditionResult.Success)
263 DefineName (s.Name, s);
266 return AdditionResult.Success;
269 public AdditionResult AddDelegate (Delegate d)
272 string name = d.Basename;
274 if ((res = IsValid (name, d.Name)) != AdditionResult.Success)
277 if (delegates == null)
278 delegates = new ArrayList ();
280 DefineName (d.Name, d);
283 return AdditionResult.Success;
286 public AdditionResult AddMethod (Method method)
288 string basename = method.Name;
289 string fullname = Name + "." + basename;
291 Object value = defined_names [fullname];
293 if (value != null && (!(value is Method)))
294 return AdditionResult.NameExists;
296 if (basename == Basename)
297 return AdditionResult.EnclosingClash;
300 methods = new ArrayList ();
302 if (method.Name.IndexOf ('.') != -1)
303 methods.Insert (0, method);
305 methods.Add (method);
308 DefineName (fullname, method);
310 return AdditionResult.Success;
313 public AdditionResult AddConstructor (Constructor c)
315 if (c.Name != Basename)
316 return AdditionResult.NotAConstructor;
318 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
321 UserDefinedStaticConstructor = true;
322 if (default_static_constructor != null)
323 return AdditionResult.MethodExists;
325 default_static_constructor = c;
328 if (default_constructor != null)
329 return AdditionResult.MethodExists;
330 default_constructor = c;
333 if (instance_constructors == null)
334 instance_constructors = new ArrayList ();
336 instance_constructors.Add (c);
339 return AdditionResult.Success;
342 public AdditionResult AddInterface (TypeContainer iface)
345 string name = iface.Basename;
347 if ((res = IsValid (name, iface.Name)) != AdditionResult.Success)
350 if (interfaces == null)
351 interfaces = new ArrayList ();
352 interfaces.Add (iface);
353 DefineName (iface.Name, iface);
355 return AdditionResult.Success;
358 public AdditionResult AddField (Field field)
361 string basename = field.Name;
362 string fullname = Name + "." + basename;
364 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
368 fields = new ArrayList ();
372 if (field.HasInitializer){
373 if ((field.ModFlags & Modifiers.STATIC) != 0){
374 if (initialized_static_fields == null)
375 initialized_static_fields = new ArrayList ();
377 initialized_static_fields.Add (field);
380 if (initialized_fields == null)
381 initialized_fields = new ArrayList ();
383 initialized_fields.Add (field);
387 if ((field.ModFlags & Modifiers.STATIC) == 0)
388 have_nonstatic_fields = true;
390 DefineName (fullname, field);
391 return AdditionResult.Success;
394 public AdditionResult AddProperty (Property prop)
398 if ((res = AddProperty (prop, prop.Name)) != AdditionResult.Success)
401 if (prop.Get != null) {
402 if ((res = AddProperty (prop, "get_" + prop.Name)) != AdditionResult.Success)
406 if (prop.Set != null) {
407 if ((res = AddProperty (prop, "set_" + prop.Name)) != AdditionResult.Success)
411 if (properties == null)
412 properties = new ArrayList ();
414 if (prop.Name.IndexOf ('.') != -1)
415 properties.Insert (0, prop);
417 properties.Add (prop);
419 return AdditionResult.Success;
422 AdditionResult AddProperty (Property prop, string basename)
425 string fullname = Name + "." + basename;
427 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
430 DefineName (fullname, prop);
432 return AdditionResult.Success;
435 public AdditionResult AddEvent (Event e)
438 string basename = e.Name;
439 string fullname = Name + "." + basename;
441 if ((res = IsValid (basename, fullname)) != AdditionResult.Success)
445 events = new ArrayList ();
448 DefineName (fullname, e);
450 return AdditionResult.Success;
453 public void AddIndexer (Indexer i)
455 if (indexers == null)
456 indexers = new ArrayList ();
458 if (i.MemberName.Left != null)
459 indexers.Insert (0, i);
464 public AdditionResult AddOperator (Operator op)
466 if (operators == null)
467 operators = new ArrayList ();
471 string basename = op.Name;
472 string fullname = Name + "." + basename;
473 if (!defined_names.Contains (fullname))
475 DefineName (fullname, op);
477 return AdditionResult.Success;
480 public void AddIterator (Iterator i)
482 if (iterators == null)
483 iterators = new ArrayList ();
488 public void AddType (TypeContainer tc)
493 public void AddPart (ClassPart part)
496 parts = new ArrayList ();
501 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
503 if (a.Type == TypeManager.default_member_type) {
504 if (Indexers != null) {
505 Report.Error (646, a.Location,
506 "Cannot specify the DefaultMember attribute on" +
507 " a type containing an indexer");
512 base.ApplyAttributeBuilder (a, cb);
515 public override AttributeTargets AttributeTargets {
517 throw new NotSupportedException ();
521 public ArrayList Types {
527 public ArrayList Methods {
533 public ArrayList Constants {
539 public ArrayList Interfaces {
545 public ArrayList Iterators {
553 return base_class_name;
557 public ArrayList Bases {
567 public ArrayList Fields {
577 public ArrayList InstanceConstructors {
579 return instance_constructors;
583 public ArrayList Properties {
589 public ArrayList Events {
595 public ArrayList Enums {
601 public ArrayList Indexers {
607 public ArrayList Operators {
613 public ArrayList Delegates {
619 public ArrayList Parts {
625 public virtual TypeAttributes TypeAttr {
627 return Modifiers.TypeAttr (ModFlags, this);
632 // Emits the instance field initializers
634 public bool EmitFieldInitializers (EmitContext ec)
637 Expression instance_expr;
640 fields = initialized_static_fields;
641 instance_expr = null;
643 fields = initialized_fields;
644 instance_expr = new This (Location.Null).Resolve (ec);
650 foreach (Field f in fields){
651 Expression e = f.GetInitializerExpression (ec);
655 Location l = f.Location;
656 FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
657 fe.InstanceExpression = instance_expr;
658 fe.IsFieldInitializer = true;
660 ExpressionStatement a = new Assign (fe, e, l);
662 a = a.ResolveStatement (ec);
666 a.EmitStatement (ec);
673 // Defines the default constructors
675 void DefineDefaultConstructor (bool is_static)
679 // The default constructor is public
680 // If the class is abstract, the default constructor is protected
681 // The default static constructor is private
683 int mods = Modifiers.PUBLIC;
685 mods = Modifiers.STATIC | Modifiers.PRIVATE;
686 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
687 mods = Modifiers.PROTECTED;
689 c = new Constructor (this, Basename, mods, Parameters.EmptyReadOnlyParameters,
690 new ConstructorBaseInitializer (
691 null, Parameters.EmptyReadOnlyParameters,
697 c.Block = new ToplevelBlock (null, Location);
701 public void ReportStructInitializedInstanceError ()
703 string n = TypeBuilder.FullName;
705 foreach (Field f in initialized_fields){
708 "`" + n + "." + f.Name + "': can not have " +
709 "instance field initializers in structs");
714 /// The pending methods that need to be implemented
715 // (interfaces or abstract methods)
717 public PendingImplementation Pending;
719 public abstract void Register ();
721 public abstract PendingImplementation GetPendingImplementations ();
723 TypeExpr[] GetPartialBases (out TypeExpr parent, out bool error)
725 ArrayList ifaces = new ArrayList ();
728 Location parent_loc = Location.Null;
730 foreach (ClassPart part in parts) {
732 TypeExpr[] new_ifaces;
734 new_ifaces = part.GetClassBases (out new_parent, out error);
738 if ((parent != null) && (new_parent != null) &&
739 !parent.Equals (new_parent)) {
740 Report.Error (263, part.Location,
741 "Partial declarations of `{0}' must " +
742 "not specify different base classes",
745 if (!Location.IsNull (parent_loc))
746 Report.LocationOfPreviousError (parent_loc);
752 if ((parent == null) && (new_parent != null)) {
754 parent_loc = part.Location;
757 if (new_ifaces == null)
760 foreach (TypeExpr iface in new_ifaces) {
762 foreach (TypeExpr old_iface in ifaces) {
763 if (old_iface.Equals (iface)) {
776 TypeExpr[] retval = new TypeExpr [ifaces.Count];
777 ifaces.CopyTo (retval, 0);
781 TypeExpr[] GetNormalBases (out TypeExpr parent, out bool error)
785 int count = Bases.Count;
788 if (Kind == Kind.Class){
789 TypeExpr name = ResolveTypeExpr (
790 (Expression) Bases [0], false, Location);
807 TypeExpr [] ifaces = new TypeExpr [count-start];
809 for (i = start, j = 0; i < count; i++, j++){
810 Expression name = (Expression) Bases [i];
811 TypeExpr resolved = ResolveTypeExpr (name, false, Location);
812 if (resolved == null) {
817 ifaces [j] = resolved;
825 /// This function computes the Base class and also the
826 /// list of interfaces that the class or struct @c implements.
828 /// The return value is an array (might be null) of
829 /// interfaces implemented (as Types).
831 /// The @parent argument is set to the parent object or null
832 /// if this is `System.Object'.
834 TypeExpr [] GetClassBases (out TypeExpr parent, out bool error)
836 ArrayList bases = Bases;
844 ifaces = GetPartialBases (out parent, out error);
845 else if (Bases == null){
849 ifaces = GetNormalBases (out parent, out error);
854 if ((parent != null) && (Kind == Kind.Class)){
855 if (parent is TypeParameterExpr){
857 689, parent.Location,
858 "Type parameter `{0}' can not be used as a " +
859 "base class or interface", parent.Name);
864 if (IsGeneric && parent.IsAttribute){
866 698, parent.Location,
867 "A generic type cannot derive from `{0}' " +
868 "because it is an attribute class",
874 if (parent.IsSealed){
877 if (parent.IsValueType)
878 detail = " (a class can not inherit from a struct/enum)";
880 Report.Error (509, "class `"+ Name +
881 "': Cannot inherit from sealed class `"+
882 parent.Name + "'" + detail);
887 if (!parent.CanInheritFrom ()){
888 Report.Error (644, Location,
889 "`{0}' cannot inherit from special class `{1}'",
890 Name, parent_type.Name);
895 if (!parent.AsAccessible (this, ModFlags))
896 Report.Error (60, Location,
897 "Inconsistent accessibility: base class `" +
898 parent.Name + "' is less accessible than class `" +
903 base_class_name = parent.Name;
908 int count = ifaces != null ? ifaces.Length : 0;
910 for (i = 0; i < count; i++) {
911 TypeExpr iface = (TypeExpr) ifaces [i];
913 if ((Kind != Kind.Class) && !iface.IsInterface){
914 string what = Kind == Kind.Struct ?
915 "Struct" : "Interface";
917 Report.Error (527, Location,
918 "In {0} `{1}', type `{2}' is not "+
919 "an interface", what, Name, iface.Name);
926 Report.Error (527, Location,
927 "In Class `{0}', `{1}' is not " +
928 "an interface", Name, iface.Name);
934 for (int x = 0; x < i; x++) {
935 if (iface.Equals (ifaces [x])) {
936 Report.Error (528, Location,
937 "`{0}' is already listed in " +
938 "interface list", iface.Name);
944 if ((Kind == Kind.Interface) &&
945 !iface.AsAccessible (Parent, ModFlags))
946 Report.Error (61, Location,
947 "Inconsistent accessibility: base " +
948 "interface `{0}' is less accessible " +
949 "than interface `{1}'", iface.Name,
956 bool CheckGenericInterfaces (Type[] ifaces)
958 ArrayList already_checked = new ArrayList ();
960 for (int i = 0; i < ifaces.Length; i++) {
961 Type iface = ifaces [i];
962 foreach (Type t in already_checked) {
966 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t))
971 "`{0}' cannot implement both `{1}' and `{2}' " +
972 "because they may unify for some type " +
973 "parameter substitutions",
974 TypeManager.GetFullName (TypeBuilder),
979 already_checked.Add (iface);
988 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
990 public override TypeBuilder DefineType ()
994 if (TypeBuilder != null)
1001 Report.Error (146, Location, "Class definition is circular: `{0}'", Name);
1008 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
1010 TypeExpr[] iface_exprs = GetClassBases (out parent_type, out error);
1014 if (parent_type == null) {
1015 if (Kind == Kind.Class){
1016 if (RootContext.StdLib)
1017 parent_type = TypeManager.system_object_expr;
1018 else if (Name != "System.Object")
1019 parent_type = TypeManager.system_object_expr;
1020 } else if (Kind == Kind.Struct){
1022 // If we are compiling our runtime,
1023 // and we are defining ValueType, then our
1024 // parent is `System.Object'.
1026 if (!RootContext.StdLib && Name == "System.ValueType")
1027 parent_type = TypeManager.system_object_expr;
1028 else if (Kind == Kind.Struct)
1029 parent_type = TypeManager.system_valuetype_expr;
1034 foreach (TypeParameter type_param in TypeParameters)
1035 if (!type_param.Resolve (this)) {
1041 if ((Kind == Kind.Struct) && TypeManager.value_type == null)
1042 throw new Exception ();
1044 TypeAttributes type_attributes = TypeAttr;
1047 ConstructedType constructed = parent_type as ConstructedType;
1048 if ((constructed == null) && (parent_type != null))
1049 ptype = parent_type.ResolveType (ec);
1054 if (TypeManager.NamespaceClash (Name, Location)) {
1059 ModuleBuilder builder = CodeGen.Module.Builder;
1060 TypeBuilder = builder.DefineType (
1061 Name, type_attributes, ptype, null);
1063 TypeBuilder builder = Parent.DefineType ();
1064 if (builder == null) {
1069 TypeBuilder = builder.DefineNestedType (
1070 MemberName.Basename, type_attributes, ptype, null);
1073 TypeManager.AddUserType (Name, TypeBuilder, this);
1076 CurrentType = new ConstructedType (
1077 Name, TypeParameters, Location);
1079 string[] param_names = new string [TypeParameters.Length];
1080 for (int i = 0; i < TypeParameters.Length; i++)
1081 param_names [i] = TypeParameters [i].Name;
1083 GenericTypeParameterBuilder[] gen_params;
1085 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1087 for (int i = 0; i < gen_params.Length; i++)
1088 TypeParameters [i].Define (gen_params [i]);
1091 if (constructed != null) {
1092 ptype = constructed.ResolveType (ec);
1093 if (ptype == null) {
1098 TypeBuilder.SetParent (ptype);
1102 foreach (TypeParameter type_param in TypeParameters)
1103 if (!type_param.DefineType (ec))
1111 // Structs with no fields need to have at least one byte.
1112 // The right thing would be to set the PackingSize in a DefineType
1113 // but there are no functions that allow interfaces *and* the size to
1117 if ((Kind == Kind.Struct) && !have_nonstatic_fields){
1118 TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
1119 FieldAttributes.Private);
1122 // add interfaces that were not added at type creation
1123 if (iface_exprs != null) {
1124 ifaces = TypeManager.ExpandInterfaces (ec, iface_exprs);
1125 if (ifaces == null) {
1130 foreach (Type itype in ifaces)
1131 TypeBuilder.AddInterfaceImplementation (itype);
1133 if (!CheckGenericInterfaces (ifaces)) {
1138 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1142 // Finish the setup for the EmitContext
1144 ec.ContainerType = TypeBuilder;
1146 if ((parent_type != null) && parent_type.IsAttribute) {
1147 RootContext.RegisterAttribute (this);
1148 } else if (!(this is Iterator))
1149 RootContext.RegisterOrder (this);
1151 if (!DefineNestedTypes ()) {
1160 protected virtual bool DefineNestedTypes ()
1162 if (Interfaces != null) {
1163 foreach (TypeContainer iface in Interfaces)
1164 if (iface.DefineType () == null)
1168 if (Types != null) {
1169 foreach (TypeContainer tc in Types)
1170 if (tc.DefineType () == null)
1174 if (Delegates != null) {
1175 foreach (Delegate d in Delegates)
1176 if (d.DefineType () == null)
1180 if (Enums != null) {
1181 foreach (Enum en in Enums)
1182 if (en.DefineType () == null)
1186 if (Parts != null) {
1187 foreach (ClassPart part in Parts) {
1188 part.TypeBuilder = TypeBuilder;
1189 part.parent_type = parent_type;
1198 /// Defines the MemberCore objects that are in the `list' Arraylist
1200 /// The `defined_names' array contains a list of members defined in
1203 static ArrayList remove_list = new ArrayList ();
1204 void DefineMembers (ArrayList list, MemberInfo [] defined_names)
1208 remove_list.Clear ();
1210 foreach (MemberCore mc in list){
1212 if (defined_names != null)
1213 idx = Array.BinarySearch (defined_names, mc.Name, mif_compare);
1218 if (RootContext.WarningLevel >= 4){
1219 if ((mc.ModFlags & Modifiers.NEW) != 0)
1220 Warning_KeywordNewNotRequired (mc.Location, mc);
1222 } else if (mc is MethodCore)
1223 ((MethodCore) mc).OverridesSomething = true;
1226 remove_list.Add (mc);
1233 MemberInfo match = defined_names [idx];
1235 if (match is PropertyInfo && ((mc.ModFlags & Modifiers.OVERRIDE) != 0))
1239 // If we are both methods, let the method resolution emit warnings
1241 if (match is MethodBase && mc is MethodCore)
1244 if ((mc.ModFlags & Modifiers.NEW) == 0) {
1246 if (!(match is EventInfo)) {
1247 Error_EventCanOnlyOverrideEvent (mc.Location, defined_names [idx]);
1251 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
1255 Warning_KeywordNewRequired (mc.Location, defined_names [idx]);
1259 foreach (object o in remove_list)
1262 remove_list.Clear ();
1266 // Defines the indexers, and also verifies that the IndexerNameAttribute in the
1267 // class is consistent. Either it is `Item' or it is the name defined by all the
1268 // indexers with the `IndexerName' attribute.
1270 // Turns out that the IndexerNameAttribute is applied to each indexer,
1271 // but it is never emitted, instead a DefaultMember attribute is attached
1274 void DefineIndexers ()
1276 string class_indexer_name = null;
1279 // If there's both an explicit and an implicit interface implementation, the
1280 // explicit one actually implements the interface while the other one is just
1281 // a normal indexer. See bug #37714.
1284 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1285 bool seen_normal_indexers = false;
1286 foreach (Indexer i in Indexers) {
1291 name = i.IndexerName;
1293 if (i.InterfaceType != null) {
1294 if (seen_normal_indexers)
1295 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1299 seen_normal_indexers = true;
1301 if (class_indexer_name == null)
1302 class_indexer_name = name;
1303 else if (name != class_indexer_name)
1304 Report.Error (668, i.Location, "Two indexers have different names, " +
1305 " you should use the same name for all your indexers");
1308 if (seen_normal_indexers && class_indexer_name == null)
1309 class_indexer_name = "Item";
1310 IndexerName = class_indexer_name;
1313 static void Error_KeywordNotAllowed (Location loc)
1315 Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
1319 /// Populates our TypeBuilder with fields and methods
1321 public override bool DefineMembers (TypeContainer container)
1323 if (members_defined)
1324 return members_defined_ok;
1326 members_defined_ok = DoDefineMembers ();
1327 members_defined = true;
1329 return members_defined_ok;
1332 bool DoDefineMembers ()
1334 MemberInfo [] defined_names = null;
1337 // We need to be able to use the member cache while we are checking/defining
1340 if (TypeBuilder.BaseType != null)
1341 parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
1344 if (RootContext.WarningLevel > 1){
1348 // This code throws an exception in the comparer
1349 // I guess the string is not an object?
1351 ptype = TypeBuilder.BaseType;
1353 defined_names = (MemberInfo []) FindMembers (
1354 ptype, MemberTypes.All & ~MemberTypes.Constructor,
1355 BindingFlags.Public | BindingFlags.Instance |
1356 BindingFlags.Static, null, null);
1358 Array.Sort (defined_names, mif_compare);
1362 Class pclass = Parent as Class;
1363 if (pclass != null) {
1364 string pname = null;
1365 TypeExpr ptype = null;
1366 Type t = pclass.TypeBuilder.BaseType;
1367 while ((t != null) && (ptype == null)) {
1368 pname = t.FullName + "." + Basename;
1369 ptype = RootContext.LookupType (this, pname, true, Location.Null);
1373 if ((ModFlags & Modifiers.NEW) != 0) {
1375 Report.Warning (109, Location, "The member '" + Name + "' does not hide an " +
1376 "inherited member. The keyword new is not required.");
1377 } else if (ptype != null) {
1378 Report.Warning (108, Location, "The keyword new is required on `" +
1379 Name + "' because it hides inherited member '" +
1382 } else if ((ModFlags & Modifiers.NEW) != 0)
1383 Error_KeywordNotAllowed (Location);
1385 if (constants != null)
1386 DefineMembers (constants, defined_names);
1389 DefineMembers (fields, defined_names);
1391 if ((Kind == Kind.Class) && !(this is ClassPart)){
1392 if (instance_constructors == null){
1393 if (default_constructor == null)
1394 DefineDefaultConstructor (false);
1397 if (initialized_static_fields != null &&
1398 default_static_constructor == null)
1399 DefineDefaultConstructor (true);
1402 if (Kind == Kind.Struct){
1404 // Structs can not have initialized instance
1407 if (initialized_static_fields != null &&
1408 default_static_constructor == null)
1409 DefineDefaultConstructor (true);
1411 if (initialized_fields != null)
1412 ReportStructInitializedInstanceError ();
1415 Pending = GetPendingImplementations ();
1417 if (parts != null) {
1418 foreach (ClassPart part in parts) {
1419 if (!part.DefineMembers (this))
1425 // Constructors are not in the defined_names array
1427 if (instance_constructors != null)
1428 DefineMembers (instance_constructors, null);
1430 if (default_static_constructor != null)
1431 default_static_constructor.Define ();
1433 if (methods != null)
1434 DefineMembers (methods, defined_names);
1436 if (properties != null)
1437 DefineMembers (properties, defined_names);
1440 DefineMembers (events, defined_names);
1442 if (indexers != null)
1445 if (operators != null){
1446 DefineMembers (operators, null);
1448 CheckPairedOperators ();
1452 DefineMembers (enums, defined_names);
1454 if (delegates != null)
1455 DefineMembers (delegates, defined_names);
1457 if (CurrentType != null) {
1458 GenericType = CurrentType.ResolveType (ec);
1460 ec.ContainerType = GenericType;
1465 if (!(this is ClassPart))
1466 member_cache = new MemberCache (this);
1469 if (parts != null) {
1470 foreach (ClassPart part in parts)
1471 part.member_cache = member_cache;
1474 if (iterators != null) {
1475 foreach (Iterator iterator in iterators) {
1476 if (iterator.DefineType () == null)
1480 foreach (Iterator iterator in iterators) {
1481 if (!iterator.DefineMembers (this))
1489 public override bool Define ()
1491 if (parts != null) {
1492 foreach (ClassPart part in parts) {
1493 if (!part.Define ())
1502 /// This function is based by a delegate to the FindMembers routine
1504 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1510 /// This filter is used by FindMembers, and we just keep
1511 /// a global for the filter to `AlwaysAccept'
1513 static MemberFilter accepting_filter;
1517 /// A member comparission method based on name only
1519 static IComparer mif_compare;
1521 static TypeContainer ()
1523 accepting_filter = new MemberFilter (AlwaysAccept);
1524 mif_compare = new MemberInfoCompare ();
1527 public MethodInfo[] GetMethods ()
1529 ArrayList members = new ArrayList ();
1531 DefineMembers (null);
1533 if (methods != null) {
1534 int len = methods.Count;
1535 for (int i = 0; i < len; i++) {
1536 Method m = (Method) methods [i];
1538 members.Add (m.MethodBuilder);
1542 if (operators != null) {
1543 int len = operators.Count;
1544 for (int i = 0; i < len; i++) {
1545 Operator o = (Operator) operators [i];
1547 members.Add (o.OperatorMethodBuilder);
1551 if (properties != null) {
1552 int len = properties.Count;
1553 for (int i = 0; i < len; i++) {
1554 Property p = (Property) properties [i];
1556 if (p.GetBuilder != null)
1557 members.Add (p.GetBuilder);
1558 if (p.SetBuilder != null)
1559 members.Add (p.SetBuilder);
1563 if (indexers != null) {
1564 int len = indexers.Count;
1565 for (int i = 0; i < len; i++) {
1566 Indexer ix = (Indexer) indexers [i];
1568 if (ix.GetBuilder != null)
1569 members.Add (ix.GetBuilder);
1570 if (ix.SetBuilder != null)
1571 members.Add (ix.SetBuilder);
1575 if (events != null) {
1576 int len = events.Count;
1577 for (int i = 0; i < len; i++) {
1578 Event e = (Event) events [i];
1580 if (e.AddBuilder != null)
1581 members.Add (e.AddBuilder);
1582 if (e.RemoveBuilder != null)
1583 members.Add (e.RemoveBuilder);
1587 MethodInfo[] retMethods = new MethodInfo [members.Count];
1588 members.CopyTo (retMethods, 0);
1593 /// This method returns the members of this type just like Type.FindMembers would
1594 /// Only, we need to use this for types which are _being_ defined because MS'
1595 /// implementation can't take care of that.
1598 // FIXME: return an empty static array instead of null, that cleans up
1599 // some code and is consistent with some coding conventions I just found
1603 // Notice that in various cases we check if our field is non-null,
1604 // something that would normally mean that there was a bug elsewhere.
1606 // The problem happens while we are defining p-invoke methods, as those
1607 // will trigger a FindMembers, but this happens before things are defined
1609 // Since the whole process is a no-op, it is fine to check for null here.
1611 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1612 MemberFilter filter, object criteria)
1614 ArrayList members = null;
1617 if ((bf & BindingFlags.Public) != 0)
1618 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1620 if ((bf & BindingFlags.NonPublic) != 0)
1621 modflags |= Modifiers.PRIVATE;
1623 int static_mask = 0, static_flags = 0;
1624 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1625 case BindingFlags.Static:
1626 static_mask = static_flags = Modifiers.STATIC;
1629 case BindingFlags.Instance:
1630 static_mask = Modifiers.STATIC;
1635 static_mask = static_flags = 0;
1639 Timer.StartTimer (TimerType.TcFindMembers);
1642 filter = accepting_filter;
1644 if ((mt & MemberTypes.Field) != 0) {
1645 if (fields != null) {
1646 int len = fields.Count;
1647 for (int i = 0; i < len; i++) {
1648 Field f = (Field) fields [i];
1650 if ((f.ModFlags & modflags) == 0)
1652 if ((f.ModFlags & static_mask) != static_flags)
1655 FieldBuilder fb = f.FieldBuilder;
1656 if (fb != null && filter (fb, criteria) == true) {
1657 if (members == null)
1658 members = new ArrayList ();
1665 if (constants != null) {
1666 int len = constants.Count;
1667 for (int i = 0; i < len; i++) {
1668 Const con = (Const) constants [i];
1670 if ((con.ModFlags & modflags) == 0)
1672 if ((con.ModFlags & static_mask) != static_flags)
1675 FieldBuilder fb = con.FieldBuilder;
1676 if (fb != null && filter (fb, criteria) == true) {
1677 if (members == null)
1678 members = new ArrayList ();
1686 if ((mt & MemberTypes.Method) != 0) {
1687 if (methods != null) {
1688 int len = methods.Count;
1689 for (int i = 0; i < len; i++) {
1690 Method m = (Method) methods [i];
1692 if ((m.ModFlags & modflags) == 0)
1694 if ((m.ModFlags & static_mask) != static_flags)
1697 MethodBuilder mb = m.MethodBuilder;
1699 if (mb != null && filter (mb, criteria) == true) {
1700 if (members == null)
1701 members = new ArrayList ();
1708 if (operators != null) {
1709 int len = operators.Count;
1710 for (int i = 0; i < len; i++) {
1711 Operator o = (Operator) operators [i];
1713 if ((o.ModFlags & modflags) == 0)
1715 if ((o.ModFlags & static_mask) != static_flags)
1718 MethodBuilder ob = o.OperatorMethodBuilder;
1719 if (ob != null && filter (ob, criteria) == true) {
1720 if (members == null)
1721 members = new ArrayList ();
1728 if (properties != null) {
1729 int len = properties.Count;
1730 for (int i = 0; i < len; i++) {
1731 Property p = (Property) properties [i];
1733 if ((p.ModFlags & modflags) == 0)
1735 if ((p.ModFlags & static_mask) != static_flags)
1741 if (b != null && filter (b, criteria) == true) {
1742 if (members == null)
1743 members = new ArrayList ();
1749 if (b != null && filter (b, criteria) == true) {
1750 if (members == null)
1751 members = new ArrayList ();
1758 if (indexers != null) {
1759 int len = indexers.Count;
1760 for (int i = 0; i < len; i++) {
1761 Indexer ix = (Indexer) indexers [i];
1763 if ((ix.ModFlags & modflags) == 0)
1765 if ((ix.ModFlags & static_mask) != static_flags)
1771 if (b != null && filter (b, criteria) == true) {
1772 if (members == null)
1773 members = new ArrayList ();
1779 if (b != null && filter (b, criteria) == true) {
1780 if (members == null)
1781 members = new ArrayList ();
1789 if ((mt & MemberTypes.Event) != 0) {
1790 if (events != null) {
1791 int len = events.Count;
1792 for (int i = 0; i < len; i++) {
1793 Event e = (Event) events [i];
1795 if ((e.ModFlags & modflags) == 0)
1797 if ((e.ModFlags & static_mask) != static_flags)
1800 MemberInfo eb = e.EventBuilder;
1801 if (eb != null && filter (eb, criteria) == true) {
1802 if (members == null)
1803 members = new ArrayList ();
1805 members.Add (e.EventBuilder);
1811 if ((mt & MemberTypes.Property) != 0){
1812 if (properties != null) {
1813 int len = properties.Count;
1814 for (int i = 0; i < len; i++) {
1815 Property p = (Property) properties [i];
1817 if ((p.ModFlags & modflags) == 0)
1819 if ((p.ModFlags & static_mask) != static_flags)
1822 MemberInfo pb = p.PropertyBuilder;
1823 if (pb != null && filter (pb, criteria) == true) {
1824 if (members == null)
1825 members = new ArrayList ();
1827 members.Add (p.PropertyBuilder);
1832 if (indexers != null) {
1833 int len = indexers.Count;
1834 for (int i = 0; i < len; i++) {
1835 Indexer ix = (Indexer) indexers [i];
1837 if ((ix.ModFlags & modflags) == 0)
1839 if ((ix.ModFlags & static_mask) != static_flags)
1842 MemberInfo ib = ix.PropertyBuilder;
1843 if (ib != null && filter (ib, criteria) == true) {
1844 if (members == null)
1845 members = new ArrayList ();
1847 members.Add (ix.PropertyBuilder);
1853 if ((mt & MemberTypes.NestedType) != 0) {
1854 if (types != null) {
1855 int len = types.Count;
1856 for (int i = 0; i < len; i++) {
1857 TypeContainer t = (TypeContainer) types [i];
1859 if ((t.ModFlags & modflags) == 0)
1862 TypeBuilder tb = t.TypeBuilder;
1863 if (tb != null && (filter (tb, criteria) == true)) {
1864 if (members == null)
1865 members = new ArrayList ();
1872 if (enums != null) {
1873 int len = enums.Count;
1874 for (int i = 0; i < len; i++) {
1875 Enum en = (Enum) enums [i];
1877 if ((en.ModFlags & modflags) == 0)
1880 TypeBuilder tb = en.TypeBuilder;
1881 if (tb != null && (filter (tb, criteria) == true)) {
1882 if (members == null)
1883 members = new ArrayList ();
1890 if (delegates != null) {
1891 int len = delegates.Count;
1892 for (int i = 0; i < len; i++) {
1893 Delegate d = (Delegate) delegates [i];
1895 if ((d.ModFlags & modflags) == 0)
1898 TypeBuilder tb = d.TypeBuilder;
1899 if (tb != null && (filter (tb, criteria) == true)) {
1900 if (members == null)
1901 members = new ArrayList ();
1908 if (interfaces != null) {
1909 int len = interfaces.Count;
1910 for (int i = 0; i < len; i++) {
1911 TypeContainer iface = (TypeContainer) interfaces [i];
1913 if ((iface.ModFlags & modflags) == 0)
1916 TypeBuilder tb = iface.TypeBuilder;
1917 if (tb != null && (filter (tb, criteria) == true)) {
1918 if (members == null)
1919 members = new ArrayList ();
1927 if ((mt & MemberTypes.Constructor) != 0){
1928 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1929 int len = instance_constructors.Count;
1930 for (int i = 0; i < len; i++) {
1931 Constructor c = (Constructor) instance_constructors [i];
1933 ConstructorBuilder cb = c.ConstructorBuilder;
1934 if (cb != null && filter (cb, criteria) == true) {
1935 if (members == null)
1936 members = new ArrayList ();
1943 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1944 ConstructorBuilder cb =
1945 default_static_constructor.ConstructorBuilder;
1947 if (cb != null && filter (cb, criteria) == true) {
1948 if (members == null)
1949 members = new ArrayList ();
1957 // Lookup members in parent if requested.
1959 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1960 if (TypeBuilder.BaseType != null) {
1961 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
1962 if (list.Count > 0) {
1963 if (members == null)
1964 members = new ArrayList ();
1966 members.AddRange (list);
1972 Timer.StopTimer (TimerType.TcFindMembers);
1974 if (members == null)
1975 return MemberList.Empty;
1977 return new MemberList (members);
1980 public override MemberCache MemberCache {
1982 return member_cache;
1986 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
1987 MemberFilter filter, object criteria)
1989 DeclSpace ds = TypeManager.LookupDeclSpace (t);
1992 return ds.FindMembers (mt, bf, filter, criteria);
1994 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
1998 // FindMethods will look for methods not only in the type `t', but in
1999 // any interfaces implemented by the type.
2001 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
2002 MemberFilter filter, object criteria)
2008 /// Emits the values for the constants
2010 public void EmitConstants ()
2012 if (constants != null)
2013 foreach (Const con in constants)
2018 protected virtual void VerifyMembers (EmitContext ec)
2021 // Check for internal or private fields that were never assigned
2023 if (RootContext.WarningLevel >= 3) {
2024 if (fields != null){
2025 foreach (Field f in fields) {
2026 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2029 if ((f.status & Field.Status.USED) == 0){
2031 169, f.Location, "Private field " +
2032 MakeName (f.Name) + " is never used");
2037 // Only report 649 on level 4
2039 if (RootContext.WarningLevel < 4)
2042 if ((f.status & Field.Status.ASSIGNED) != 0)
2047 "Field " + MakeName (f.Name) + " is never assigned " +
2048 " to and will always have its default value");
2052 if (events != null){
2053 foreach (Event e in events){
2055 Report.Warning (67, "The event " + MakeName (e.Name) + " is never used");
2062 /// Emits the code, this step is performed after all
2063 /// the types, enumerations, constructors
2065 public void EmitType ()
2067 if (OptAttributes != null)
2068 OptAttributes.Emit (ec, this);
2072 if (instance_constructors != null) {
2073 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && IsClsCompliaceRequired (this)) {
2074 bool has_compliant_args = false;
2076 foreach (Constructor c in instance_constructors) {
2079 if (has_compliant_args)
2082 has_compliant_args = c.HasCompliantArgs;
2084 if (!has_compliant_args)
2085 Report.Error_T (3015, Location, GetSignatureForError ());
2087 foreach (Constructor c in instance_constructors)
2092 if (default_static_constructor != null)
2093 default_static_constructor.Emit ();
2095 if (methods != null)
2096 foreach (Method m in methods)
2099 if (operators != null)
2100 foreach (Operator o in operators)
2103 if (properties != null)
2104 foreach (Property p in properties)
2107 if (indexers != null){
2108 foreach (Indexer ix in indexers)
2110 if (IndexerName != null) {
2111 CustomAttributeBuilder cb = EmitDefaultMemberAttr ();
2112 TypeBuilder.SetCustomAttribute (cb);
2117 foreach (Field f in fields)
2120 if (events != null){
2121 foreach (Event e in Events)
2125 if (delegates != null) {
2126 foreach (Delegate d in Delegates) {
2131 if (enums != null) {
2132 foreach (Enum e in enums) {
2137 if (parts != null) {
2138 foreach (ClassPart part in parts)
2142 if ((Pending != null) && !(this is ClassPart))
2143 if (Pending.VerifyPendingMethods ())
2148 if (iterators != null)
2149 foreach (Iterator iterator in iterators)
2150 iterator.EmitType ();
2152 // if (types != null)
2153 // foreach (TypeContainer tc in types)
2157 CustomAttributeBuilder EmitDefaultMemberAttr ()
2159 EmitContext ec = new EmitContext (this, Location, null, null, ModFlags);
2161 Expression ml = Expression.MemberLookup (ec, TypeManager.default_member_type,
2162 ".ctor", MemberTypes.Constructor,
2163 BindingFlags.Public | BindingFlags.Instance,
2166 MethodGroupExpr mg = (MethodGroupExpr) ml;
2168 MethodBase constructor = mg.Methods [0];
2170 string [] vals = { IndexerName };
2172 CustomAttributeBuilder cb = null;
2174 cb = new CustomAttributeBuilder ((ConstructorInfo) constructor, vals);
2176 Report.Warning (-100, "Can not set the indexer default member attribute");
2182 public override void CloseType ()
2184 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2188 caching_flags |= Flags.CloseTypeCreated;
2189 TypeBuilder.CreateType ();
2190 } catch (TypeLoadException){
2192 // This is fine, the code still created the type
2194 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2195 // Console.WriteLine (e.Message);
2197 Console.WriteLine ("In type: " + Name);
2202 foreach (Enum en in Enums)
2206 foreach (TypeContainer tc in Types)
2207 if (tc.Kind == Kind.Struct)
2210 foreach (TypeContainer tc in Types)
2211 if (tc.Kind != Kind.Struct)
2215 if (Delegates != null)
2216 foreach (Delegate d in Delegates)
2219 if (Iterators != null)
2220 foreach (Iterator i in Iterators)
2228 initialized_fields = null;
2229 initialized_static_fields = null;
2238 default_constructor = null;
2239 default_static_constructor = null;
2241 OptAttributes = null;
2243 parent_container = null;
2244 member_cache = null;
2247 public string MakeName (string n)
2249 return "`" + Name + "." + n + "'";
2252 public void Warning_KeywordNewRequired (Location l, MemberInfo mi)
2255 108, l, "The keyword new is required on " +
2256 MakeName (mi.Name) + " because it hides `" +
2257 mi.ReflectedType.Name + "." + mi.Name + "'");
2260 public void Warning_KeywordNewNotRequired (Location l, MemberCore mc)
2263 109, l, "The member " + MakeName (mc.Name) + " does not hide an " +
2264 "inherited member, the keyword new is not required");
2267 public void Error_EventCanOnlyOverrideEvent (Location l, MemberInfo mi)
2270 72, l, MakeName (mi.Name) + " : cannot override; `" +
2271 mi.ReflectedType.Name + "." + mi.Name + "' is not an event");
2274 public static int CheckMember (string name, MemberInfo mi, int ModFlags)
2280 // Performs the validation on a Method's modifiers (properties have
2281 // the same properties).
2283 public bool MethodModifiersValid (int flags, string n, Location loc)
2285 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2286 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2287 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2291 // At most one of static, virtual or override
2293 if ((flags & Modifiers.STATIC) != 0){
2294 if ((flags & vao) != 0){
2296 112, loc, "static method " + MakeName (n) + "can not be marked " +
2297 "as virtual, abstract or override");
2302 if (Kind == Kind.Struct){
2303 if ((flags & va) != 0){
2304 Modifiers.Error_InvalidModifier (loc, "virtual or abstract");
2309 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2311 113, loc, MakeName (n) +
2312 " marked as override cannot be marked as new or virtual");
2317 // If the declaration includes the abstract modifier, then the
2318 // declaration does not include static, virtual or extern
2320 if ((flags & Modifiers.ABSTRACT) != 0){
2321 if ((flags & Modifiers.EXTERN) != 0){
2323 180, loc, MakeName (n) + " can not be both abstract and extern");
2327 if ((flags & Modifiers.VIRTUAL) != 0){
2329 503, loc, MakeName (n) + " can not be both abstract and virtual");
2333 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2335 513, loc, MakeName (n) +
2336 " is abstract but its container class is not");
2342 if ((flags & Modifiers.PRIVATE) != 0){
2343 if ((flags & vao) != 0){
2345 621, loc, MakeName (n) +
2346 " virtual or abstract members can not be private");
2351 if ((flags & Modifiers.SEALED) != 0){
2352 if ((flags & Modifiers.OVERRIDE) == 0){
2354 238, loc, MakeName (n) +
2355 " cannot be sealed because it is not an override");
2363 Hashtable builder_and_args;
2365 public bool RegisterMethod (MethodBuilder mb, InternalParameters ip, Type [] args)
2367 if (builder_and_args == null)
2368 builder_and_args = new Hashtable ();
2372 protected override bool VerifyClsCompliance (DeclSpace ds)
2374 if (!base.VerifyClsCompliance (ds))
2377 // parent_container is null for System.Object
2378 if (parent_container != null && !AttributeTester.IsClsCompliant (parent_container.Type)) {
2379 Report.Error_T (3009, Location, GetSignatureForError (), TypeManager.CSharpName (parent_container.Type));
2386 /// Performs checks for an explicit interface implementation. First it
2387 /// checks whether the `interface_type' is a base inteface implementation.
2388 /// Then it checks whether `name' exists in the interface type.
2390 public virtual bool VerifyImplements (Type interface_type, string full,
2391 string name, Location loc)
2395 if (ifaces != null){
2396 foreach (Type t in ifaces){
2397 if (t == interface_type){
2405 Report.Error (540, "`" + full + "': containing class does not implement interface `" + interface_type.FullName + "'");
2412 protected override void VerifyObsoleteAttribute()
2414 CheckUsageOfObsoleteAttribute (TypeBuilder.BaseType);
2419 foreach (Type iface in ifaces) {
2420 CheckUsageOfObsoleteAttribute (iface);
2428 string IMemberContainer.Name {
2434 Type IMemberContainer.Type {
2440 IMemberContainer IMemberContainer.Parent {
2442 return parent_container;
2446 MemberCache IMemberContainer.MemberCache {
2448 return member_cache;
2452 bool IMemberContainer.IsInterface {
2454 return Kind == Kind.Interface;
2458 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2460 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2462 if (GenericType != null)
2463 return TypeManager.FindMembers (GenericType, mt, new_bf,
2466 return FindMembers (mt, new_bf, null, null);
2470 // Operator pair checking
2473 class OperatorEntry {
2475 public Type ret_type;
2476 public Type type1, type2;
2478 public Operator.OpType ot;
2480 public OperatorEntry (int f, Operator o)
2484 ret_type = o.OperatorMethod.GetReturnType ();
2485 Type [] pt = o.OperatorMethod.ParameterTypes;
2489 ot = o.OperatorType;
2492 public override int GetHashCode ()
2494 return ret_type.GetHashCode ();
2497 public override bool Equals (object o)
2499 OperatorEntry other = (OperatorEntry) o;
2501 if (other.ret_type != ret_type)
2503 if (other.type1 != type1)
2505 if (other.type2 != type2)
2512 // Checks that some operators come in pairs:
2518 // They are matched based on the return type and the argument types
2520 void CheckPairedOperators ()
2522 Hashtable pairs = new Hashtable (null, null);
2523 Operator true_op = null;
2524 Operator false_op = null;
2525 bool has_equality_or_inequality = false;
2527 // Register all the operators we care about.
2528 foreach (Operator op in operators){
2531 switch (op.OperatorType){
2532 case Operator.OpType.Equality:
2534 has_equality_or_inequality = true;
2536 case Operator.OpType.Inequality:
2538 has_equality_or_inequality = true;
2541 case Operator.OpType.True:
2544 case Operator.OpType.False:
2548 case Operator.OpType.GreaterThan:
2550 case Operator.OpType.LessThan:
2553 case Operator.OpType.GreaterThanOrEqual:
2555 case Operator.OpType.LessThanOrEqual:
2561 OperatorEntry oe = new OperatorEntry (reg, op);
2563 object o = pairs [oe];
2567 oe = (OperatorEntry) o;
2572 if (true_op != null){
2573 if (false_op == null)
2574 Report.Error (216, true_op.Location, "operator true requires a matching operator false");
2575 } else if (false_op != null)
2576 Report.Error (216, false_op.Location, "operator false requires a matching operator true");
2579 // Look for the mistakes.
2581 foreach (DictionaryEntry de in pairs){
2582 OperatorEntry oe = (OperatorEntry) de.Key;
2589 case Operator.OpType.Equality:
2592 case Operator.OpType.Inequality:
2595 case Operator.OpType.GreaterThan:
2598 case Operator.OpType.LessThan:
2601 case Operator.OpType.GreaterThanOrEqual:
2604 case Operator.OpType.LessThanOrEqual:
2608 Report.Error (216, oe.op.Location,
2609 "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
2612 if ((has_equality_or_inequality) && (RootContext.WarningLevel >= 2)) {
2613 MethodSignature equals_ms = new MethodSignature (
2614 "Equals", TypeManager.bool_type, new Type [] { TypeManager.object_type });
2615 MethodSignature hash_ms = new MethodSignature (
2616 "GetHashCode", TypeManager.int32_type, new Type [0]);
2618 MemberList equals_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2619 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2621 MemberList hash_ml = FindMembers (MemberTypes.Method, BindingFlags.Public | BindingFlags.Instance |
2622 BindingFlags.DeclaredOnly, MethodSignature.method_signature_filter,
2625 bool equals_ok = false;
2626 if ((equals_ml != null) && (equals_ml.Count == 1))
2627 equals_ok = equals_ml [0].DeclaringType == TypeBuilder;
2628 bool hash_ok = false;
2629 if ((hash_ml != null) && (hash_ml.Count == 1))
2630 hash_ok = hash_ml [0].DeclaringType == TypeBuilder;
2633 Report.Warning (660, Location, "`" + Name + "' defines operator == or operator != but does " +
2634 "not override Object.Equals (object o)");
2636 Report.Warning (661, Location, "`" + Name + "' defines operator == or operator != but does " +
2637 "not override Object.GetHashCode ()");
2643 public class PartialContainer : TypeContainer {
2645 public readonly Namespace Namespace;
2646 public readonly int OriginalModFlags;
2647 public readonly int AllowedModifiers;
2648 public readonly TypeAttributes DefaultTypeAttributes;
2650 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2651 MemberName name, int mod_flags, Kind kind,
2654 PartialContainer pc;
2655 string full_name = name.GetName (true);
2656 DeclSpace ds = (DeclSpace) RootContext.Tree.Decls [full_name];
2658 pc = ds as PartialContainer;
2662 260, ds.Location, "Missing partial modifier " +
2663 "on declaration of type `{0}'; another " +
2664 "partial implementation of this type exists",
2667 Report.LocationOfPreviousError (loc);
2671 if (pc.Kind != kind) {
2673 261, loc, "Partial declarations of `{0}' " +
2674 "must be all classes, all structs or " +
2675 "all interfaces", name);
2679 if (pc.OriginalModFlags != mod_flags) {
2681 262, loc, "Partial declarations of `{0}' " +
2682 "have conflicting accessibility modifiers",
2690 pc = new PartialContainer (ns, parent, name, mod_flags, kind, loc);
2691 RootContext.Tree.RecordDecl (full_name, pc);
2692 parent.AddType (pc);
2697 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2698 MemberName name, int mod, Attributes attrs,
2699 Kind kind, Location loc)
2701 PartialContainer pc = Create (ns, parent, name, mod, kind, loc);
2703 // An error occured; create a dummy container, but don't
2705 pc = new PartialContainer (ns, parent, name, mod, kind, loc);
2708 ClassPart part = new ClassPart (ns, pc, mod, attrs, kind, loc);
2713 protected PartialContainer (NamespaceEntry ns, TypeContainer parent,
2714 MemberName name, int mod, Kind kind, Location l)
2715 : base (ns, parent, name, null, kind, l)
2717 this.Namespace = ns.NS;
2721 AllowedModifiers = Class.AllowedModifiers;
2722 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2726 AllowedModifiers = Struct.AllowedModifiers;
2727 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2730 case Kind.Interface:
2731 AllowedModifiers = Interface.AllowedModifiers;
2732 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2736 throw new InvalidOperationException ();
2740 if (parent.Parent == null)
2741 accmods = Modifiers.INTERNAL;
2743 accmods = Modifiers.PRIVATE;
2745 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2746 this.OriginalModFlags = mod;
2749 public override void Register ()
2751 if (Kind == Kind.Interface)
2752 Parent.AddInterface (this);
2753 else if (Kind == Kind.Class)
2754 Parent.AddClass (this);
2755 else if (Kind == Kind.Struct)
2756 Parent.AddStruct (this);
2758 throw new InvalidOperationException ();
2761 public override PendingImplementation GetPendingImplementations ()
2763 return PendingImplementation.GetPendingImplementations (this);
2766 public ClassPart AddPart (NamespaceEntry ns, int mod, Attributes attrs,
2769 ClassPart part = new ClassPart (ns, this, mod, attrs, Kind, l);
2774 public override TypeAttributes TypeAttr {
2776 return base.TypeAttr | DefaultTypeAttributes;
2781 public class ClassPart : TypeContainer {
2782 public readonly PartialContainer PartialContainer;
2783 public readonly bool IsPartial;
2785 public ClassPart (NamespaceEntry ns, PartialContainer parent,
2786 int mod, Attributes attrs, Kind kind, Location l)
2787 : base (ns, parent.Parent, parent.MemberName, attrs, kind, l)
2789 this.PartialContainer = parent;
2790 this.IsPartial = true;
2793 if (parent.Parent == null)
2794 accmods = Modifiers.INTERNAL;
2796 accmods = Modifiers.PRIVATE;
2798 this.ModFlags = Modifiers.Check (
2799 parent.AllowedModifiers, mod, accmods, l);
2802 public override void Register ()
2806 public override PendingImplementation GetPendingImplementations ()
2808 return PartialContainer.Pending;
2811 public override bool VerifyImplements (Type interface_type, string full,
2812 string name, Location loc)
2814 return PartialContainer.VerifyImplements (
2815 interface_type, full, name, loc);
2819 public abstract class ClassOrStruct : TypeContainer {
2820 bool hasExplicitLayout = false;
2822 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2823 MemberName name, Attributes attrs, Kind kind,
2825 : base (ns, parent, name, attrs, kind, l)
2829 public override PendingImplementation GetPendingImplementations ()
2831 return PendingImplementation.GetPendingImplementations (this);
2834 protected override void VerifyMembers (EmitContext ec)
2836 if (Fields != null) {
2837 foreach (Field f in Fields) {
2838 if ((f.ModFlags & Modifiers.STATIC) != 0)
2840 if (hasExplicitLayout) {
2841 if (f.OptAttributes == null
2842 || !f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2843 Report.Error (625, f.Location,
2844 "Instance field of type marked with"
2845 + " StructLayout(LayoutKind.Explicit) must have a"
2846 + " FieldOffset attribute.");
2850 if (f.OptAttributes != null
2851 && f.OptAttributes.Contains (TypeManager.field_offset_attribute_type, ec)) {
2852 Report.Error (636, f.Location,
2853 "The FieldOffset attribute can only be placed on members of "
2854 + "types marked with the StructLayout(LayoutKind.Explicit)");
2859 base.VerifyMembers (ec);
2862 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
2864 if (a.Type == TypeManager.struct_layout_attribute_type
2865 && (LayoutKind) a.GetPositionalValue (0) == LayoutKind.Explicit)
2866 hasExplicitLayout = true;
2868 base.ApplyAttributeBuilder (a, cb);
2872 public class Class : ClassOrStruct {
2874 // Modifiers allowed in a class declaration
2876 public const int AllowedModifiers =
2879 Modifiers.PROTECTED |
2880 Modifiers.INTERNAL |
2882 Modifiers.ABSTRACT |
2886 // Information in the case we are an attribute type
2887 AttributeUsageAttribute attribute_usage;
2889 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name,
2890 int mod, Attributes attrs, Location l)
2891 : base (ns, parent, name, attrs, Kind.Class, l)
2895 if (parent.Parent == null)
2896 accmods = Modifiers.INTERNAL;
2898 accmods = Modifiers.PRIVATE;
2900 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2901 attribute_usage = new AttributeUsageAttribute (AttributeTargets.All);
2904 public override AttributeTargets AttributeTargets {
2906 return AttributeTargets.Class;
2910 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
2912 if (a.UsageAttribute != null)
2913 attribute_usage = a.UsageAttribute;
2915 base.ApplyAttributeBuilder (a, cb);
2918 public AttributeUsageAttribute AttributeUsage {
2920 return attribute_usage;
2924 public override void Register ()
2926 CheckDef (Parent.AddClass (this), Name, Location);
2929 public const TypeAttributes DefaultTypeAttributes =
2930 TypeAttributes.AutoLayout | TypeAttributes.Class;
2933 // FIXME: How do we deal with the user specifying a different
2936 public override TypeAttributes TypeAttr {
2938 return base.TypeAttr | DefaultTypeAttributes;
2943 public class Struct : ClassOrStruct {
2945 // Modifiers allowed in a struct declaration
2947 public const int AllowedModifiers =
2950 Modifiers.PROTECTED |
2951 Modifiers.INTERNAL |
2955 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
2956 int mod, Attributes attrs, Location l)
2957 : base (ns, parent, name, attrs, Kind.Struct, l)
2961 if (parent.Parent == null)
2962 accmods = Modifiers.INTERNAL;
2964 accmods = Modifiers.PRIVATE;
2966 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
2968 this.ModFlags |= Modifiers.SEALED;
2971 public override AttributeTargets AttributeTargets {
2973 return AttributeTargets.Struct;
2977 public override void Register ()
2979 CheckDef (Parent.AddStruct (this), Name, Location);
2982 public const TypeAttributes DefaultTypeAttributes =
2983 TypeAttributes.SequentialLayout |
2984 TypeAttributes.Sealed |
2985 TypeAttributes.BeforeFieldInit;
2988 // FIXME: Allow the user to specify a different set of attributes
2989 // in some cases (Sealed for example is mandatory for a class,
2990 // but what SequentialLayout can be changed
2992 public override TypeAttributes TypeAttr {
2994 return base.TypeAttr | DefaultTypeAttributes;
3002 public class Interface : TypeContainer, IMemberContainer {
3004 /// Modifiers allowed in a class declaration
3006 public const int AllowedModifiers =
3009 Modifiers.PROTECTED |
3010 Modifiers.INTERNAL |
3014 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name,
3015 int mod, Attributes attrs, Location l)
3016 : base (ns, parent, name, attrs, Kind.Interface, l)
3020 if (parent.Parent == null)
3021 accmods = Modifiers.INTERNAL;
3023 accmods = Modifiers.PRIVATE;
3025 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, l);
3028 public override void Register ()
3030 CheckDef (Parent.AddInterface (this), Name, Location);
3033 public override PendingImplementation GetPendingImplementations ()
3038 public override AttributeTargets AttributeTargets {
3040 return AttributeTargets.Interface;
3044 public const TypeAttributes DefaultTypeAttributes =
3045 TypeAttributes.AutoLayout |
3046 TypeAttributes.Abstract |
3047 TypeAttributes.Interface;
3049 public override TypeAttributes TypeAttr {
3051 return base.TypeAttr | DefaultTypeAttributes;
3056 public abstract class MethodCore : MemberBase {
3057 public readonly Parameters Parameters;
3058 public readonly GenericMethod GenericMethod;
3059 public readonly DeclSpace ds;
3060 protected Block block;
3063 // Parameters, cached for semantic analysis.
3065 protected InternalParameters parameter_info;
3066 protected Type [] parameter_types;
3069 // This is set from TypeContainer.DefineMembers if this method overrides something.
3071 public bool OverridesSomething;
3073 // Whether this is an operator method.
3074 public bool IsOperator;
3076 static string[] attribute_targets = new string [] { "method", "return" };
3078 public MethodCore (TypeContainer parent, GenericMethod generic,
3079 Expression type, int mod, int allowed_mod, bool is_iface,
3080 MemberName name, Attributes attrs, Parameters parameters,
3082 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name,
3085 Parameters = parameters;
3086 IsInterface = is_iface;
3087 this.GenericMethod = generic;
3089 if (generic != null)
3096 // Returns the System.Type array for the parameters of this method
3098 public Type [] ParameterTypes {
3100 return parameter_types;
3104 public InternalParameters ParameterInfo
3107 return parameter_info;
3111 public Block Block {
3121 protected virtual bool DoDefineParameters ()
3123 // Check if arguments were correct
3124 parameter_types = Parameters.GetParameterInfo (ds);
3125 if ((parameter_types == null) ||
3126 !CheckParameters (ds, parameter_types))
3129 parameter_info = new InternalParameters (ds, Parameters);
3131 Parameter array_param = Parameters.ArrayParameter;
3132 if ((array_param != null) &&
3133 (!array_param.ParameterType.IsArray ||
3134 (array_param.ParameterType.GetArrayRank () != 1))) {
3135 Report.Error (225, Location, "params parameter has to be a single dimensional array");
3142 void error_425 (Type old, Type t, string name)
3144 Report.Error (425, Location,
3145 "The constraints of type parameter `{0}' " +
3146 "of method `{1}' must match the constraints for " +
3147 "type parameter `{2}' of method `{3}'",
3148 TypeManager.CSharpName (old), Name,
3149 TypeManager.CSharpName (t), name);
3152 protected override bool CheckGenericOverride (MethodInfo method, string name)
3154 ParameterData pd = Invocation.GetParameterData (method);
3156 for (int i = 0; i < ParameterTypes.Length; i++) {
3157 GenericConstraints ogc = pd.GenericConstraints (i);
3158 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
3160 if ((gc == null) && (ogc == null))
3163 Type ot = pd.ParameterType (i);
3164 Type t = ParameterTypes [i];
3166 if (!((gc != null) && (ogc != null))) {
3167 error_425 (ot, t, name);
3171 if (gc.HasConstructor != ogc.HasConstructor) {
3172 error_425 (ot, t, name);
3176 if (ogc.HasClassConstraint != gc.HasClassConstraint) {
3177 error_425 (ot, t, name);
3181 if (ogc.HasClassConstraint &&
3182 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
3183 error_425 (ot, t, name);
3187 Type[] oct = ogc.InterfaceConstraints;
3188 Type[] ct = gc.InterfaceConstraints;
3190 if (oct.Length != ct.Length) {
3191 error_425 (ot, t, name);
3195 for (int j = 0; j < oct.Length; j++)
3196 if (!oct [j].Equals (ct [j])) {
3197 error_425 (ot, t, name);
3205 protected override string[] ValidAttributeTargets {
3207 return attribute_targets;
3211 protected override bool VerifyClsCompliance (DeclSpace ds)
3213 if (!base.VerifyClsCompliance (ds)) {
3214 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsCompliaceRequired (ds)) {
3215 Report.Error_T (3011, Location, GetSignatureForError ());
3220 if (Parameters.HasArglist) {
3221 // "Methods with variable arguments are not CLS-compliant"
3222 Report.Error_T (3000, Location);
3225 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3227 if (!AttributeTester.IsClsCompliant (MemberType)) {
3228 Report.Error_T (3002, Location, GetSignatureForError ());
3234 protected bool IsDuplicateImplementation (TypeContainer tc, MethodCore method)
3236 if ((method == this) || (method.Name != Name))
3239 Type[] param_types = method.ParameterTypes;
3240 if (param_types == null)
3243 if (param_types.Length != ParameterTypes.Length)
3246 int type_params = 0;
3247 if (GenericMethod != null)
3248 type_params = GenericMethod.CountTypeParameters;
3250 int m_type_params = 0;
3251 if (method.GenericMethod != null)
3252 m_type_params = method.GenericMethod.CountTypeParameters;
3254 if (type_params != m_type_params)
3260 Type[] infered_types = new Type [param_types.Length];
3261 may_unify = Invocation.InferTypeArguments (
3262 param_types, ParameterTypes, ref infered_types);
3265 infered_types = new Type [param_types.Length];
3266 may_unify = Invocation.InferTypeArguments (
3267 ParameterTypes, param_types, ref infered_types);
3270 for (int i = 0; i < param_types.Length; i++) {
3271 Type a = param_types [i];
3272 Type b = ParameterTypes [i];
3280 // Try to report 663: method only differs on out/ref
3282 ParameterData info = ParameterInfo;
3283 ParameterData other_info = method.ParameterInfo;
3284 for (int i = 0; i < info.Count; i++){
3285 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3286 Report.Error (663, Location,
3287 "Overload method only differs " +
3288 "in parameter modifier");
3293 Report.Error (111, Location,
3294 "Class `{0}' already defines a member called " +
3295 "`{1}' with the same parameter types",
3298 } else if (may_unify) {
3299 Report.Error (408, Location,
3300 "`{0}' cannot define overload members that " +
3301 "may unify for some type parameter substitutions",
3309 public CallingConventions GetCallingConvention (bool is_class)
3311 CallingConventions cc = 0;
3313 cc = Parameters.GetCallingConvention ();
3316 if ((ModFlags & Modifiers.STATIC) == 0)
3317 cc |= CallingConventions.HasThis;
3319 // FIXME: How is `ExplicitThis' used in C#?
3324 protected override void VerifyObsoleteAttribute()
3326 base.VerifyObsoleteAttribute ();
3328 if (parameter_types == null)
3331 foreach (Type type in parameter_types) {
3332 CheckUsageOfObsoleteAttribute (type);
3337 public class SourceMethod : ISourceMethod
3339 TypeContainer container;
3342 protected SourceMethod (TypeContainer container, MethodBase builder,
3343 ISourceFile file, Location start, Location end)
3345 this.container = container;
3346 this.builder = builder;
3348 CodeGen.SymbolWriter.OpenMethod (
3349 file, this, start.Row, 0, end.Row, 0);
3352 public string Name {
3353 get { return builder.Name; }
3356 public int NamespaceID {
3357 get { return container.NamespaceEntry.SymbolFileID; }
3362 if (builder is MethodBuilder)
3363 return ((MethodBuilder) builder).GetToken ().Token;
3364 else if (builder is ConstructorBuilder)
3365 return ((ConstructorBuilder) builder).GetToken ().Token;
3367 throw new NotSupportedException ();
3371 public void CloseMethod ()
3373 if (CodeGen.SymbolWriter != null)
3374 CodeGen.SymbolWriter.CloseMethod ();
3377 public static SourceMethod Create (TypeContainer parent,
3378 MethodBase builder, Block block)
3380 if (CodeGen.SymbolWriter == null)
3385 Location start_loc = block.StartLocation;
3386 if (Location.IsNull (start_loc))
3389 Location end_loc = block.EndLocation;
3390 if (Location.IsNull (end_loc))
3393 ISourceFile file = start_loc.SourceFile;
3397 return new SourceMethod (
3398 parent, builder, file, start_loc, end_loc);
3402 public class Method : MethodCore, IIteratorContainer, IMethodData {
3403 public MethodBuilder MethodBuilder;
3404 public MethodData MethodData;
3405 ReturnParameter return_attributes;
3408 /// Modifiers allowed in a class declaration
3410 const int AllowedModifiers =
3413 Modifiers.PROTECTED |
3414 Modifiers.INTERNAL |
3419 Modifiers.OVERRIDE |
3420 Modifiers.ABSTRACT |
3422 Modifiers.METHOD_YIELDS |
3425 const int AllowedInterfaceModifiers =
3426 Modifiers.NEW | Modifiers.UNSAFE;
3429 // return_type can be "null" for VOID values.
3431 public Method (TypeContainer parent, GenericMethod generic,
3432 Expression return_type, int mod, bool is_iface,
3433 MemberName name, Parameters parameters, Attributes attrs,
3435 : base (parent, generic, return_type, mod,
3436 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
3437 is_iface, name, attrs, parameters, l)
3441 public override AttributeTargets AttributeTargets {
3443 return AttributeTargets.Method | AttributeTargets.ReturnValue;
3448 // Returns the `System.Type' for the ReturnType of this
3449 // function. Provides a nice cache. (used between semantic analysis
3450 // and actual code generation
3452 public Type GetReturnType ()
3457 public override string GetSignatureForError()
3459 return TypeManager.CSharpSignature (MethodBuilder);
3463 /// Use this method when MethodBuilder is null
3465 public override string GetSignatureForError (TypeContainer tc)
3467 // TODO: move to parameters
3468 System.Text.StringBuilder args = new System.Text.StringBuilder ();
3469 if (parameter_info.Parameters.FixedParameters != null) {
3470 for (int i = 0; i < parameter_info.Parameters.FixedParameters.Length; ++i) {
3471 Parameter p = parameter_info.Parameters.FixedParameters [i];
3472 args.Append (p.GetSignatureForError ());
3474 if (i < parameter_info.Parameters.FixedParameters.Length - 1)
3479 return String.Concat (base.GetSignatureForError (tc), "(", args.ToString (), ")");
3482 void DuplicateEntryPoint (MethodInfo b, Location location)
3486 "Program `" + CodeGen.FileName +
3487 "' has more than one entry point defined: `" +
3488 TypeManager.CSharpSignature(b) + "'");
3491 void Report28 (MethodInfo b)
3495 "`" + TypeManager.CSharpSignature(b) +
3496 "' has the wrong signature to be an entry point");
3499 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
3501 if (b.ReturnType != TypeManager.void_type &&
3502 b.ReturnType != TypeManager.int32_type)
3505 if (pinfo.Count == 0)
3508 if (pinfo.Count > 1)
3511 Type t = pinfo.ParameterType(0);
3513 (t.GetArrayRank() == 1) &&
3514 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
3515 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
3521 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3523 if (a.Target == "return") {
3524 if (return_attributes == null)
3525 return_attributes = new ReturnParameter (MethodBuilder, Location);
3527 return_attributes.ApplyAttributeBuilder (a, cb);
3531 if (a.Type == TypeManager.methodimpl_attr_type && a.IsInternalCall) {
3532 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
3535 if (a.Type == TypeManager.dllimport_type) {
3536 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
3537 if ((ModFlags & extern_static) != extern_static) {
3538 //"The DllImport attribute must be specified on a method marked `static' and `extern'"
3539 Report.Error_T (601, a.Location);
3545 if (a.Type == TypeManager.conditional_attribute_type) {
3546 if (IsOperator || IsExplicitImpl) {
3547 // Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation
3548 Report.Error_T (577, Location, GetSignatureForError ());
3552 if (ReturnType != TypeManager.void_type) {
3553 // Conditional not valid on '{0}' because its return type is not void
3554 Report.Error_T (578, Location, GetSignatureForError ());
3558 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3559 // Conditional not valid on '{0}' because it is an override method
3560 Report.Error_T (243, Location, GetSignatureForError ());
3565 // Conditional not valid on interface members
3566 Report.Error_T (582, Location);
3570 if (MethodData.IsImplementing) {
3571 // Conditional member '{0}' cannot implement interface member
3572 Report.Error_T (629, Location, GetSignatureForError ());
3577 MethodBuilder.SetCustomAttribute (cb);
3581 // Checks our base implementation if any
3583 protected override bool CheckBase ()
3587 // Check whether arguments were correct.
3588 if (!DoDefineParameters ())
3591 MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
3593 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
3596 // Check in our class for dups
3598 ArrayList ar = Parent.Methods;
3600 int arLen = ar.Count;
3602 for (int i = 0; i < arLen; i++) {
3603 Method m = (Method) ar [i];
3604 if (IsDuplicateImplementation (Parent, m))
3612 // Verify if the parent has a type with the same name, and then
3613 // check whether we have to create a new slot for it or not.
3615 Type ptype = Parent.TypeBuilder.BaseType;
3617 // ptype is only null for System.Object while compiling corlib.
3618 if (ptype != null) {
3621 // Explicit implementations do not have `parent' methods, however,
3622 // the member cache stores them there. Without this check, we get
3623 // an incorrect warning in corlib.
3625 if (! IsExplicitImpl) {
3626 parent_method = (MethodInfo)((IMemberContainer)Parent).Parent.MemberCache.FindMemberToOverride (
3627 Parent.TypeBuilder, Name, ParameterTypes, false);
3630 if (parent_method != null) {
3631 string name = parent_method.DeclaringType.Name + "." +
3634 if (!CheckMethodAgainstBase (Parent, flags, parent_method, name))
3637 if ((ModFlags & Modifiers.NEW) == 0) {
3638 Type parent_ret = TypeManager.TypeToCoreType (
3639 parent_method.ReturnType);
3641 if (!parent_ret.Equals (MemberType)) {
3643 508, Location, Parent.MakeName (Name) + ": cannot " +
3644 "change return type when overriding " +
3645 "inherited member " + name);
3650 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (parent_method);
3652 Report.SymbolRelatedToPreviousError (parent_method);
3653 Report.Warning_T (672, Location, GetSignatureForError (Parent));
3656 if (!OverridesSomething && ((ModFlags & Modifiers.NEW) != 0))
3657 WarningNotHiding (Parent);
3659 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3660 Report.Error (115, Location,
3661 Parent.MakeName (Name) +
3662 " no suitable methods found to override");
3665 } else if ((ModFlags & Modifiers.NEW) != 0)
3666 WarningNotHiding (Parent);
3674 public override bool Define ()
3676 if (!DoDefineBase ())
3679 MethodBuilder mb = null;
3680 if (GenericMethod != null) {
3681 mb = Parent.TypeBuilder.DefineGenericMethod (Name, flags);
3682 if (!GenericMethod.Define (mb))
3692 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
3693 this, mb, GenericMethod);
3695 if (!MethodData.Define (Parent))
3699 // Setup iterator if we are one
3701 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
3702 Iterator iterator = new Iterator (
3703 Parent, Name, MemberType, ParameterTypes,
3704 ParameterInfo, ModFlags, block, Location);
3706 if (!iterator.DefineIterator ())
3709 block = iterator.Block;
3712 MethodBuilder = MethodData.MethodBuilder;
3715 // This is used to track the Entry Point,
3717 if (Name == "Main" &&
3718 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
3719 (RootContext.MainClass == null ||
3720 RootContext.MainClass == Parent.TypeBuilder.FullName)){
3721 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
3722 if (RootContext.EntryPoint == null) {
3723 if (Parent.IsGeneric){
3724 Report.Error (-201, Location,
3725 "Entry point can not be defined in a generic class");
3728 RootContext.EntryPoint = MethodBuilder;
3729 RootContext.EntryPointLocation = Location;
3731 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
3732 DuplicateEntryPoint (MethodBuilder, Location);
3735 Report28(MethodBuilder);
3744 public override void Emit ()
3746 MethodData.Emit (Parent, this);
3752 void IIteratorContainer.SetYields ()
3754 ModFlags |= Modifiers.METHOD_YIELDS;
3757 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
3759 return IsIdentifierAndParamClsCompliant (ds, Name, MethodBuilder, parameter_types);
3762 #region IMethodData Members
3764 public CallingConventions CallingConventions {
3766 CallingConventions cc = Parameters.GetCallingConvention ();
3767 if (Parameters.HasArglist)
3768 block.HasVarargs = true;
3771 if ((ModFlags & Modifiers.STATIC) == 0)
3772 cc |= CallingConventions.HasThis;
3774 // FIXME: How is `ExplicitThis' used in C#?
3780 public Type ReturnType {
3786 public string MethodName {
3792 public new Location Location {
3794 return base.Location;
3798 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
3800 return new EmitContext (
3801 tc, ds, Location, ig, ReturnType, ModFlags, false);
3804 public ObsoleteAttribute GetObsoleteAttribute ()
3806 return GetObsoleteAttribute (ds);
3810 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
3812 public bool IsExcluded (EmitContext ec)
3814 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3815 return (caching_flags & Flags.Excluded) != 0;
3817 caching_flags &= ~Flags.Excluded_Undetected;
3819 if (parent_method == null) {
3820 if (OptAttributes == null)
3823 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3828 foreach (Attribute a in attrs) {
3829 string condition = a.GetConditionalAttributeValue (ds);
3830 if (RootContext.AllDefines.Contains (condition))
3834 caching_flags |= Flags.Excluded;
3838 IMethodData md = TypeManager.GetMethod (parent_method);
3840 if (AttributeTester.IsConditionalMethodExcluded (parent_method)) {
3841 caching_flags |= Flags.Excluded;
3847 if (md.IsExcluded (ec)) {
3848 caching_flags |= Flags.Excluded;
3854 GenericMethod IMethodData.GenericMethod {
3856 return GenericMethod;
3862 public abstract class ConstructorInitializer {
3863 ArrayList argument_list;
3864 protected ConstructorInfo parent_constructor;
3865 Parameters parameters;
3868 public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
3871 this.argument_list = argument_list;
3872 this.parameters = parameters;
3876 public ArrayList Arguments {
3878 return argument_list;
3882 public bool Resolve (ConstructorBuilder caller_builder, EmitContext ec)
3884 Expression parent_constructor_group;
3887 ec.CurrentBlock = new ToplevelBlock (Block.Flags.Implicit, parameters, loc);
3889 if (argument_list != null){
3890 foreach (Argument a in argument_list){
3891 if (!a.Resolve (ec, loc))
3895 ec.CurrentBlock = null;
3897 if (this is ConstructorBaseInitializer) {
3898 if (ec.ContainerType.BaseType == null)
3901 t = ec.ContainerType.BaseType;
3902 if (ec.ContainerType.IsValueType) {
3903 Report.Error (522, loc,
3904 "structs cannot call base class constructors");
3908 t = ec.ContainerType;
3910 parent_constructor_group = Expression.MemberLookup (
3911 ec, t, ".ctor", MemberTypes.Constructor,
3912 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3915 if (parent_constructor_group == null){
3916 parent_constructor_group = Expression.MemberLookup (
3917 ec, t, ".ctor", MemberTypes.Constructor,
3918 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
3921 if (parent_constructor_group != null)
3923 112, loc, "`{0}.{1}' is inaccessible due to " +
3924 "its protection level", t.FullName, t.Name);
3927 1501, loc, "Can not find a constructor for " +
3928 "this argument list");
3932 parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (
3933 ec, (MethodGroupExpr) parent_constructor_group, argument_list,
3936 if (parent_constructor == null){
3937 Report.Error (1501, loc,
3938 "Can not find a constructor for this argument list");
3942 if (parent_constructor == caller_builder){
3943 Report.Error (515, String.Format ("Constructor `{0}' can not call itself", TypeManager.CSharpSignature (caller_builder)));
3950 public void Emit (EmitContext ec)
3952 if (parent_constructor != null){
3953 ec.Mark (loc, false);
3955 Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
3957 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), parent_constructor, argument_list, loc);
3962 /// Method search for base ctor. (We do not cache it).
3964 Constructor GetOverloadedConstructor (TypeContainer tc)
3966 if (tc.InstanceConstructors == null)
3969 foreach (Constructor c in tc.InstanceConstructors) {
3970 if (Arguments == null) {
3971 if (c.ParameterTypes.Length == 0)
3979 int count = c.ParameterInfo.Count;
3981 c.ParameterInfo.ParameterModifier (count - 1) == Parameter.Modifier.PARAMS) {
3982 for (int i = 0; i < count-1; i++)
3983 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
3988 if (c.ParameterTypes.Length != Arguments.Count)
3991 for (int i = 0; i < Arguments.Count; ++i)
3992 if (c.ParameterTypes [i] != ((Argument)Arguments [i]).Type) {
4007 //TODO: implement caching when it will be necessary
4008 public virtual void CheckObsoleteAttribute (TypeContainer tc, Location loc)
4010 Constructor ctor = GetOverloadedConstructor (tc);
4014 ObsoleteAttribute oa = ctor.GetObsoleteAttribute (tc);
4018 AttributeTester.Report_ObsoleteMessage (oa, ctor.GetSignatureForError (), loc);
4022 public class ConstructorBaseInitializer : ConstructorInitializer {
4023 public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
4024 base (argument_list, pars, l)
4028 public override void CheckObsoleteAttribute(TypeContainer tc, Location loc) {
4029 if (parent_constructor == null)
4032 TypeContainer type_ds = TypeManager.LookupTypeContainer (tc.TypeBuilder.BaseType);
4033 if (type_ds == null) {
4034 ObsoleteAttribute oa = AttributeTester.GetMemberObsoleteAttribute (parent_constructor);
4037 AttributeTester.Report_ObsoleteMessage (oa, TypeManager.CSharpSignature (parent_constructor), loc);
4042 base.CheckObsoleteAttribute (type_ds, loc);
4047 public class ConstructorThisInitializer : ConstructorInitializer {
4048 public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
4049 base (argument_list, pars, l)
4054 public class Constructor : MethodCore {
4055 public ConstructorBuilder ConstructorBuilder;
4056 public ConstructorInitializer Initializer;
4059 // Modifiers allowed for a constructor.
4061 public const int AllowedModifiers =
4063 Modifiers.PROTECTED |
4064 Modifiers.INTERNAL |
4070 bool has_compliant_args = false;
4072 // The spec claims that static is not permitted, but
4073 // my very own code has static constructors.
4075 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
4076 ConstructorInitializer init, Location l)
4077 : base (ds, null, null, mod, AllowedModifiers, false,
4078 new MemberName (name), null, args, l)
4083 public override string GetSignatureForError()
4085 return TypeManager.CSharpSignature (ConstructorBuilder);
4088 public bool HasCompliantArgs {
4090 return has_compliant_args;
4094 public override AttributeTargets AttributeTargets {
4096 return AttributeTargets.Constructor;
4102 // Returns true if this is a default constructor
4104 public bool IsDefault ()
4106 if ((ModFlags & Modifiers.STATIC) != 0)
4107 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4108 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
4111 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4112 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
4113 (Initializer is ConstructorBaseInitializer) &&
4114 (Initializer.Arguments == null);
4117 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4119 ConstructorBuilder.SetCustomAttribute (cb);
4122 protected override bool CheckBase ()
4126 // Check whether arguments were correct.
4127 if (!DoDefineParameters ())
4130 if ((ModFlags & Modifiers.STATIC) != 0)
4133 if (Parent.Kind == Kind.Struct && ParameterTypes.Length == 0) {
4134 Report.Error (568, Location,
4135 "Structs can not contain explicit parameterless " +
4141 // Check in our class for dups
4143 ArrayList ar = Parent.InstanceConstructors;
4145 int arLen = ar.Count;
4147 for (int i = 0; i < arLen; i++) {
4148 Constructor m = (Constructor) ar [i];
4149 if (IsDuplicateImplementation (Parent, m))
4158 // Creates the ConstructorBuilder
4160 public override bool Define ()
4162 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4163 MethodAttributes.SpecialName);
4165 if ((ModFlags & Modifiers.STATIC) != 0){
4166 ca |= MethodAttributes.Static | MethodAttributes.Private;
4168 ca |= MethodAttributes.HideBySig;
4170 if ((ModFlags & Modifiers.PUBLIC) != 0)
4171 ca |= MethodAttributes.Public;
4172 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4173 if ((ModFlags & Modifiers.INTERNAL) != 0)
4174 ca |= MethodAttributes.FamORAssem;
4176 ca |= MethodAttributes.Family;
4177 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4178 ca |= MethodAttributes.Assembly;
4179 else if (IsDefault ())
4180 ca |= MethodAttributes.Public;
4182 ca |= MethodAttributes.Private;
4185 // Check if arguments were correct.
4189 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4190 ca, GetCallingConvention (Parent.Kind == Kind.Class),
4193 if ((ModFlags & Modifiers.UNSAFE) != 0)
4194 ConstructorBuilder.InitLocals = false;
4197 // HACK because System.Reflection.Emit is lame
4199 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
4207 public override void Emit ()
4209 ILGenerator ig = ConstructorBuilder.GetILGenerator ();
4210 EmitContext ec = new EmitContext (Parent, Location, ig, null, ModFlags, true);
4213 // extern methods have no bodies
4215 if ((ModFlags & Modifiers.EXTERN) != 0) {
4216 if ((block != null) && ((ModFlags & Modifiers.EXTERN) != 0)) {
4218 179, Location, "External constructor `" +
4219 TypeManager.CSharpSignature (ConstructorBuilder) +
4220 "' can not have a body");
4223 } else if (block == null) {
4225 501, Location, "Constructor `" +
4226 TypeManager.CSharpSignature (ConstructorBuilder) +
4227 "' must declare a body since it is not marked extern");
4231 if ((ModFlags & Modifiers.STATIC) == 0){
4232 if (Parent.Kind == Kind.Class && Initializer == null)
4233 Initializer = new ConstructorBaseInitializer (
4234 null, Parameters.EmptyReadOnlyParameters, Location);
4238 // Spec mandates that Initializers will not have
4242 if (Initializer != null && !Initializer.Resolve (ConstructorBuilder, ec))
4244 ec.IsStatic = false;
4247 Parameters.LabelParameters (ec, ConstructorBuilder, Location);
4249 SourceMethod source = SourceMethod.Create (
4250 Parent, ConstructorBuilder, block);
4253 // Classes can have base initializers and instance field initializers.
4255 if (Parent.Kind == Kind.Class){
4256 if ((ModFlags & Modifiers.STATIC) == 0){
4259 // If we use a "this (...)" constructor initializer, then
4260 // do not emit field initializers, they are initialized in the other constructor
4262 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4263 Parent.EmitFieldInitializers (ec);
4266 if (Initializer != null) {
4267 Initializer.CheckObsoleteAttribute (Parent, Location);
4268 Initializer.Emit (ec);
4271 if ((ModFlags & Modifiers.STATIC) != 0)
4272 Parent.EmitFieldInitializers (ec);
4274 if (OptAttributes != null)
4275 OptAttributes.Emit (ec, this);
4277 // If this is a non-static `struct' constructor and doesn't have any
4278 // initializer, it must initialize all of the struct's fields.
4279 if ((Parent.Kind == Kind.Struct) &&
4280 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4281 Block.AddThisVariable (Parent, Location);
4283 ec.EmitTopBlock (block, ParameterInfo, Location);
4286 source.CloseMethod ();
4293 // For constructors is needed to test only parameters
4294 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
4296 if (parameter_types == null || parameter_types.Length == 0)
4299 TypeContainer tc = ds as TypeContainer;
4301 for (int i = 0; i < tc.InstanceConstructors.Count; i++) {
4302 Constructor c = (Constructor) tc.InstanceConstructors [i];
4304 if (c == this || c.ParameterTypes.Length == 0)
4307 if (!c.IsClsCompliaceRequired (ds))
4310 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, c.ParameterTypes)) {
4311 Report.Error_T (3006, Location, GetSignatureForError ());
4316 if (tc.TypeBuilder.BaseType == null)
4319 DeclSpace temp_ds = TypeManager.LookupDeclSpace (tc.TypeBuilder.BaseType);
4320 if (temp_ds != null)
4321 return IsIdentifierClsCompliant (temp_ds);
4323 MemberInfo[] ml = tc.TypeBuilder.BaseType.FindMembers (MemberTypes.Constructor, BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance, null, null);
4324 // Skip parameter-less ctor
4328 foreach (ConstructorInfo ci in ml) {
4329 object[] cls_attribute = ci.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false);
4330 if (cls_attribute.Length == 1 && (!((CLSCompliantAttribute)cls_attribute[0]).IsCompliant))
4333 if (!AttributeTester.AreOverloadedMethodParamsClsCompliant (parameter_types, TypeManager.GetArgumentTypes (ci))) {
4334 Report.Error_T (3006, Location, GetSignatureForError ());
4342 protected override bool VerifyClsCompliance (DeclSpace ds)
4344 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4348 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4349 foreach (Type param in parameter_types) {
4350 if (param.IsArray) {
4355 has_compliant_args = true;
4362 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4364 public interface IMethodData
4366 CallingConventions CallingConventions { get; }
4367 Location Location { get; }
4368 string MethodName { get; }
4369 Type[] ParameterTypes { get; }
4370 Type ReturnType { get; }
4371 GenericMethod GenericMethod { get; }
4373 Attributes OptAttributes { get; }
4374 Block Block { get; }
4376 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4377 ObsoleteAttribute GetObsoleteAttribute ();
4378 string GetSignatureForError (TypeContainer tc);
4379 bool IsExcluded (EmitContext ec);
4383 // Encapsulates most of the Method's state
4385 public class MethodData {
4387 readonly IMethodData method;
4390 // The return type of this method
4392 public readonly GenericMethod GenericMethod;
4393 public readonly InternalParameters ParameterInfo;
4396 // Are we implementing an interface ?
4398 public bool IsImplementing = false;
4403 protected MemberBase member;
4404 protected int modifiers;
4405 protected MethodAttributes flags;
4406 protected Type declaring_type;
4410 MethodBuilder builder = null;
4411 public MethodBuilder MethodBuilder {
4417 public Type DeclaringType {
4419 return declaring_type;
4423 public MethodData (MemberBase member, InternalParameters parameters,
4424 int modifiers, MethodAttributes flags, IMethodData method)
4426 this.member = member;
4427 this.ParameterInfo = parameters;
4428 this.modifiers = modifiers;
4431 this.method = method;
4434 public MethodData (MemberBase member, InternalParameters parameters,
4435 int modifiers, MethodAttributes flags,
4436 IMethodData method, MethodBuilder builder,
4437 GenericMethod generic)
4438 : this (member, parameters, modifiers, flags, method)
4440 this.builder = builder;
4441 this.GenericMethod = generic;
4444 static string RemoveArity (string name)
4447 StringBuilder sb = new StringBuilder ();
4448 while (start < name.Length) {
4449 int pos = name.IndexOf ('`', start);
4451 sb.Append (name.Substring (start));
4455 sb.Append (name.Substring (start, pos-start));
4456 while (Char.IsNumber (name [++pos]))
4462 return sb.ToString ();
4465 public bool Define (TypeContainer container)
4467 MethodInfo implementing = null;
4470 if (member.IsExplicitImpl)
4471 prefix = RemoveArity (member.InterfaceType.FullName) + ".";
4475 string name = method.MethodName;
4476 string method_name = prefix + name;
4477 Type[] ParameterTypes = method.ParameterTypes;
4479 if (container.Pending != null){
4480 if (member is Indexer)
4481 implementing = container.Pending.IsInterfaceIndexer (
4482 member.InterfaceType, method.ReturnType, ParameterTypes);
4484 implementing = container.Pending.IsInterfaceMethod (
4485 member.InterfaceType, name, method.ReturnType, ParameterTypes);
4487 if (member.InterfaceType != null && implementing == null){
4488 Report.Error (539, method.Location, "'{0}' in explicit interface declaration is not an interface", method_name);
4494 // For implicit implementations, make sure we are public, for
4495 // explicit implementations, make sure we are private.
4497 if (implementing != null){
4499 // Setting null inside this block will trigger a more
4500 // verbose error reporting for missing interface implementations
4502 // The "candidate" function has been flagged already
4503 // but it wont get cleared
4505 if (member.IsExplicitImpl){
4506 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
4507 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
4508 implementing = null;
4510 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
4511 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
4513 // If this is an interface method implementation,
4514 // check for public accessibility
4516 implementing = null;
4517 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
4518 // We may never be private.
4519 implementing = null;
4520 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
4522 // We may be protected if we're overriding something.
4524 implementing = null;
4529 // Static is not allowed
4531 if ((modifiers & Modifiers.STATIC) != 0){
4532 implementing = null;
4533 Modifiers.Error_InvalidModifier (method.Location, "static");
4538 // If implementing is still valid, set flags
4540 if (implementing != null){
4542 // When implementing interface methods, set NewSlot
4543 // unless, we are overwriting a method.
4545 if (implementing.DeclaringType.IsInterface){
4546 if ((modifiers & Modifiers.OVERRIDE) == 0)
4547 flags |= MethodAttributes.NewSlot;
4550 MethodAttributes.Virtual |
4551 MethodAttributes.HideBySig;
4553 // Set Final unless we're virtual, abstract or already overriding a method.
4554 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
4555 flags |= MethodAttributes.Final;
4557 // Get the method name from the explicit interface.
4558 if (member.InterfaceType != null) {
4559 name = implementing.Name;
4560 method_name = prefix + name;
4563 IsImplementing = true;
4566 EmitContext ec = method.CreateEmitContext (container, null);
4568 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
4570 if (builder == null)
4573 if (GenericMethod != null) {
4574 if (!GenericMethod.DefineType (ec, builder))
4578 if (container.CurrentType != null)
4579 declaring_type = container.CurrentType.ResolveType (ec);
4581 declaring_type = container.TypeBuilder;
4583 if ((modifiers & Modifiers.UNSAFE) != 0)
4584 builder.InitLocals = false;
4586 if (IsImplementing){
4588 // clear the pending implemntation flag
4590 if (member is Indexer) {
4591 container.Pending.ImplementIndexer (
4592 member.InterfaceType, builder, method.ReturnType,
4593 ParameterTypes, true);
4595 container.Pending.ImplementMethod (
4596 member.InterfaceType, name, method.ReturnType,
4597 ParameterTypes, member.IsExplicitImpl);
4599 if (member.IsExplicitImpl)
4600 container.TypeBuilder.DefineMethodOverride (
4601 builder, implementing);
4605 if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
4606 Report.Error (111, method.Location,
4607 "Class `" + container.Name +
4608 "' already contains a definition with the " +
4609 "same return value and parameter types as the " +
4610 "'get' method of property `" + member.Name + "'");
4614 TypeManager.AddMethod (builder, method);
4620 /// Create the MethodBuilder for the method
4622 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
4624 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4626 if ((modifiers & extern_static) == extern_static) {
4628 if (method.OptAttributes != null) {
4629 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
4630 if (dllimport_attribute != null) {
4631 flags |= MethodAttributes.PinvokeImpl;
4632 builder = dllimport_attribute.DefinePInvokeMethod (
4633 ec, container.TypeBuilder, method_name, flags,
4634 method.ReturnType, ParameterTypes);
4640 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
4641 // We are more strict than Microsoft and report CS0626 like error
4642 if (method.OptAttributes == null ||
4643 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
4644 //"Method, operator, or accessor '{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation"
4645 Report.Error_T (626, method.Location, method.GetSignatureForError (container));
4650 if (builder == null)
4651 builder = container.TypeBuilder.DefineMethod (
4652 method_name, flags, method.CallingConventions,
4653 method.ReturnType, ParameterTypes);
4655 builder.SetGenericMethodSignature (
4656 flags, method.CallingConventions,
4657 method.ReturnType, ParameterTypes);
4663 public void Emit (TypeContainer container, Attributable kind)
4666 if ((flags & MethodAttributes.PinvokeImpl) == 0)
4667 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
4669 ec = method.CreateEmitContext (container, null);
4671 Location loc = method.Location;
4672 Attributes OptAttributes = method.OptAttributes;
4674 if (OptAttributes != null)
4675 OptAttributes.Emit (ec, kind);
4677 if (member is MethodCore)
4678 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder, loc);
4680 Block block = method.Block;
4683 // abstract or extern methods have no bodies
4685 if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
4690 // abstract or extern methods have no bodies.
4692 if ((modifiers & Modifiers.ABSTRACT) != 0)
4694 500, method.Location, "Abstract method `" +
4695 TypeManager.CSharpSignature (builder) +
4696 "' can not have a body");
4698 if ((modifiers & Modifiers.EXTERN) != 0)
4700 179, method.Location, "External method `" +
4701 TypeManager.CSharpSignature (builder) +
4702 "' can not have a body");
4708 // Methods must have a body unless they're extern or abstract
4710 if (block == null) {
4712 501, method.Location, "Method `" +
4713 TypeManager.CSharpSignature (builder) +
4714 "' must declare a body since it is not marked " +
4715 "abstract or extern");
4719 SourceMethod source = SourceMethod.Create (
4720 container, MethodBuilder, method.Block);
4723 // Handle destructors specially
4725 // FIXME: This code generates buggy code
4727 if (member is Destructor)
4728 EmitDestructor (ec, block);
4730 ec.EmitTopBlock (block, ParameterInfo, loc);
4733 source.CloseMethod ();
4736 void EmitDestructor (EmitContext ec, Block block)
4738 ILGenerator ig = ec.ig;
4740 Label finish = ig.DefineLabel ();
4742 block.SetDestructor ();
4744 ig.BeginExceptionBlock ();
4745 ec.ReturnLabel = finish;
4746 ec.HasReturnLabel = true;
4747 ec.EmitTopBlock (block, null, method.Location);
4749 // ig.MarkLabel (finish);
4750 ig.BeginFinallyBlock ();
4752 if (ec.ContainerType.BaseType != null) {
4753 Expression member_lookup = Expression.MemberLookup (
4754 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
4755 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
4757 if (member_lookup != null){
4758 MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
4760 ig.Emit (OpCodes.Ldarg_0);
4761 ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
4765 ig.EndExceptionBlock ();
4766 //ig.MarkLabel (ec.ReturnLabel);
4767 ig.Emit (OpCodes.Ret);
4771 public class Destructor : Method {
4773 public Destructor (TypeContainer ds, Expression return_type, int mod, string name,
4774 Parameters parameters, Attributes attrs, Location l)
4775 : base (ds, null, return_type, mod, false, new MemberName (name),
4776 parameters, attrs, l)
4779 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
4781 if (a.Type == TypeManager.conditional_attribute_type) {
4782 // Conditional not valid on '{0}' because it is a destructor, operator, or explicit interface implementation
4783 Report.Error_T (577, Location, GetSignatureForError ());
4787 base.ApplyAttributeBuilder (a, cb);
4791 abstract public class MemberBase : MemberCore {
4792 public Expression Type;
4794 public MethodAttributes flags;
4796 protected readonly int explicit_mod_flags;
4799 // The "short" name of this property / indexer / event. This is the
4800 // name without the explicit interface.
4802 public string ShortName;
4805 // The type of this property / indexer / event
4807 public Type MemberType;
4810 // If true, this is an explicit interface implementation
4812 public bool IsExplicitImpl = false;
4815 // The name of the interface we are explicitly implementing
4817 public Expression ExplicitInterfaceName = null;
4820 // Whether this is an interface member.
4822 public bool IsInterface;
4825 // If true, the interface type we are explicitly implementing
4827 public Type InterfaceType = null;
4830 // The method we're overriding if this is an override method.
4832 protected MethodInfo parent_method = null;
4833 public MethodInfo ParentMethod {
4835 return parent_method;
4840 // The constructor is only exposed to our children
4842 protected MemberBase (TypeContainer parent, Expression type, int mod,
4843 int allowed_mod, int def_mod, MemberName name,
4844 Attributes attrs, Location loc)
4845 : base (parent, name, attrs, loc)
4847 explicit_mod_flags = mod;
4849 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, loc);
4852 protected virtual bool CheckBase ()
4854 if ((Parent.Kind == Kind.Struct) || (RootContext.WarningLevel > 3)){
4855 if ((ModFlags & Modifiers.PROTECTED) != 0 && (Parent.ModFlags & Modifiers.SEALED) != 0){
4856 if (Parent.Kind == Kind.Struct){
4857 Report.Error (666, Location, "Protected member in struct declaration");
4860 Report.Warning (628, Location, "Member " + Parent.MakeName (Name) + " protected in sealed class");
4866 protected void WarningNotHiding (TypeContainer parent)
4870 "The member " + parent.MakeName (Name) + " does not hide an " +
4871 "inherited member. The keyword new is not required");
4875 void Error_CannotChangeAccessModifiers (TypeContainer parent, MethodInfo parent_method,
4879 // FIXME: report the old/new permissions?
4882 507, Location, parent.MakeName (Name) +
4883 ": can't change the access modifiers when overriding inherited " +
4884 "member `" + name + "'");
4887 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
4890 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
4891 // that have been defined.
4893 // `name' is the user visible name for reporting errors (this is used to
4894 // provide the right name regarding method names and properties)
4896 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodAttributes my_attrs,
4897 MethodInfo mb, string name)
4901 if ((ModFlags & Modifiers.OVERRIDE) != 0){
4902 if (!(mb.IsAbstract || mb.IsVirtual)){
4904 506, Location, parent.MakeName (Name) +
4905 ": cannot override inherited member `" +
4906 name + "' because it is not " +
4907 "virtual, abstract or override");
4911 // Now we check that the overriden method is not final
4914 // This happens when implementing interface methods.
4915 if (mb.IsHideBySig && mb.IsVirtual) {
4917 506, Location, parent.MakeName (Name) +
4918 ": cannot override inherited member `" +
4919 name + "' because it is not " +
4920 "virtual, abstract or override");
4922 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
4923 "override inherited member `" + name +
4924 "' because it is sealed.");
4929 // Check that the constraints match when overriding a
4933 if (!CheckGenericOverride (mb, name))
4937 // Check that the permissions are not being changed
4939 MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
4940 MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
4943 // special case for "protected internal"
4946 if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4948 // when overriding protected internal, the method can be declared
4949 // protected internal only within the same assembly
4952 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
4953 if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
4955 // assemblies differ - report an error
4958 Error_CannotChangeAccessModifiers (parent, mb, name);
4960 } else if (thisp != parentp) {
4962 // same assembly, but other attributes differ - report an error
4965 Error_CannotChangeAccessModifiers (parent, mb, name);
4968 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
4970 // if it's not "protected internal", it must be "protected"
4973 Error_CannotChangeAccessModifiers (parent, mb, name);
4975 } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
4977 // protected within the same assembly - an error
4979 Error_CannotChangeAccessModifiers (parent, mb, name);
4981 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
4982 (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
4984 // protected ok, but other attributes differ - report an error
4986 Error_CannotChangeAccessModifiers (parent, mb, name);
4990 if (thisp != parentp){
4991 Error_CannotChangeAccessModifiers (parent, mb, name);
4997 if (mb.IsVirtual || mb.IsAbstract){
4998 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
4999 if (Name != "Finalize"){
5001 114, 2, Location, parent.MakeName (Name) +
5002 " hides inherited member `" + name +
5003 "'. To make the current member override that " +
5004 "implementation, add the override keyword, " +
5005 "otherwise use the new keyword");
5006 ModFlags |= Modifiers.NEW;
5010 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
5011 if (Name != "Finalize"){
5013 108, 1, Location, "The keyword new is required on " +
5014 parent.MakeName (Name) + " because it hides " +
5015 "inherited member `" + name + "'");
5016 ModFlags |= Modifiers.NEW;
5024 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
5028 foreach (Type partype in parameters){
5029 if (partype == TypeManager.void_type) {
5031 1547, Location, "Keyword 'void' cannot " +
5032 "be used in this context");
5036 if (partype.IsPointer){
5039 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
5043 if (ds.AsAccessible (partype, ModFlags))
5046 if (this is Indexer)
5047 Report.Error (55, Location,
5048 "Inconsistent accessibility: parameter type `" +
5049 TypeManager.CSharpName (partype) + "' is less " +
5050 "accessible than indexer `" + Name + "'");
5051 else if ((this is Method) && ((Method) this).IsOperator)
5052 Report.Error (57, Location,
5053 "Inconsistent accessibility: parameter type `" +
5054 TypeManager.CSharpName (partype) + "' is less " +
5055 "accessible than operator `" + Name + "'");
5057 Report.Error (51, Location,
5058 "Inconsistent accessibility: parameter type `" +
5059 TypeManager.CSharpName (partype) + "' is less " +
5060 "accessible than method `" + Name + "'");
5067 protected virtual bool DoDefineBase ()
5073 ModFlags = Modifiers.PUBLIC |
5074 Modifiers.ABSTRACT |
5075 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE);
5077 flags = MethodAttributes.Public |
5078 MethodAttributes.Abstract |
5079 MethodAttributes.HideBySig |
5080 MethodAttributes.NewSlot |
5081 MethodAttributes.Virtual;
5083 if (!Parent.MethodModifiersValid (ModFlags, Name, Location))
5086 flags = Modifiers.MethodAttr (ModFlags);
5092 protected virtual bool DoDefine (DeclSpace decl)
5094 // Lookup Type, verify validity
5095 MemberType = decl.ResolveType (Type, false, Location);
5096 if (MemberType == null)
5099 if ((Parent.ModFlags & Modifiers.SEALED) != 0){
5100 if ((ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0){
5101 Report.Error (549, Location, "Virtual method can not be contained in sealed class");
5106 // verify accessibility
5107 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5108 if (this is Property)
5109 Report.Error (53, Location,
5110 "Inconsistent accessibility: property type `" +
5111 TypeManager.CSharpName (MemberType) + "' is less " +
5112 "accessible than property `" + Name + "'");
5113 else if (this is Indexer)
5114 Report.Error (54, Location,
5115 "Inconsistent accessibility: indexer return type `" +
5116 TypeManager.CSharpName (MemberType) + "' is less " +
5117 "accessible than indexer `" + Name + "'");
5118 else if (this is Method) {
5119 if (((Method) this).IsOperator)
5120 Report.Error (56, Location,
5121 "Inconsistent accessibility: return type `" +
5122 TypeManager.CSharpName (MemberType) + "' is less " +
5123 "accessible than operator `" + Name + "'");
5125 Report.Error (50, Location,
5126 "Inconsistent accessibility: return type `" +
5127 TypeManager.CSharpName (MemberType) + "' is less " +
5128 "accessible than method `" + Name + "'");
5130 Report.Error (52, Location,
5131 "Inconsistent accessibility: field type `" +
5132 TypeManager.CSharpName (MemberType) + "' is less " +
5133 "accessible than field `" + Name + "'");
5137 if (MemberType.IsPointer && !UnsafeOK (Parent))
5141 // Check for explicit interface implementation
5143 if (MemberName.Left != null) {
5144 ExplicitInterfaceName = MemberName.Left.GetTypeExpression (Location);
5145 ShortName = MemberName.Name;
5149 if (ExplicitInterfaceName != null) {
5150 InterfaceType = Parent.ResolveType (
5151 ExplicitInterfaceName, false, Location);
5152 if (InterfaceType == null)
5155 if (InterfaceType.IsClass) {
5156 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", ExplicitInterfaceName);
5160 // Compute the full name that we need to export.
5161 Name = InterfaceType.FullName + "." + ShortName;
5163 if (!Parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
5166 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5168 IsExplicitImpl = true;
5170 IsExplicitImpl = false;
5176 /// Use this method when MethodBuilder is null
5178 public virtual string GetSignatureForError (TypeContainer tc)
5180 return String.Concat (tc.Name, '.', Name);
5183 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5185 return IsIdentifierAndParamClsCompliant (ds, Name, null, null);
5188 protected override bool VerifyClsCompliance(DeclSpace ds)
5190 if (base.VerifyClsCompliance (ds)) {
5194 if (IsInterface && HasClsCompliantAttribute && ds.IsClsCompliaceRequired (ds)) {
5195 Report.Error_T (3010, Location, GetSignatureForError ());
5200 protected override void VerifyObsoleteAttribute()
5202 CheckUsageOfObsoleteAttribute (MemberType);
5207 // Fields and Events both generate FieldBuilders, we use this to share
5208 // their common bits. This is also used to flag usage of the field
5210 abstract public class FieldBase : MemberBase {
5211 public FieldBuilder FieldBuilder;
5212 public Status status;
5215 public enum Status : byte { ASSIGNED = 1, USED = 2 }
5217 static string[] attribute_targets = new string [] { "field" };
5220 // The constructor is only exposed to our children
5222 protected FieldBase (TypeContainer parent, Expression type, int mod,
5223 int allowed_mod, MemberName name, object init,
5224 Attributes attrs, Location loc)
5225 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE,
5231 public override AttributeTargets AttributeTargets {
5233 return AttributeTargets.Field;
5237 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5239 if (a.Type == TypeManager.marshal_as_attr_type) {
5240 UnmanagedMarshal marshal = a.GetMarshal ();
5241 if (marshal != null) {
5242 FieldBuilder.SetMarshal (marshal);
5245 Report.Warning_T (-24, a.Location);
5250 FieldBuilder.SetCustomAttribute (cb);
5254 // Whether this field has an initializer.
5256 public bool HasInitializer {
5258 return init != null;
5262 protected readonly Object init;
5264 Expression init_expr;
5265 bool init_expr_initialized = false;
5267 protected override bool CheckGenericOverride (MethodInfo method, string name)
5273 // Resolves and returns the field initializer.
5275 public Expression GetInitializerExpression (EmitContext ec)
5277 if (init_expr_initialized)
5281 if (init is Expression)
5282 e = (Expression) init;
5284 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
5286 ec.IsFieldInitializer = true;
5287 e = e.DoResolve (ec);
5288 ec.IsFieldInitializer = false;
5291 init_expr_initialized = true;
5296 protected override bool DoDefine (DeclSpace ds)
5298 if (!base.DoDefine (ds))
5301 if (MemberType == TypeManager.void_type) {
5302 Report.Error (1547, Location,
5303 "Keyword 'void' cannot be used in this context");
5307 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5308 // "Field or property cannot be of type '{0}'";
5309 Report.Error_T (610, Location, TypeManager.CSharpName (MemberType));
5316 public override string GetSignatureForError ()
5318 return TypeManager.GetFullNameSignature (FieldBuilder);
5321 protected override string[] ValidAttributeTargets {
5323 return attribute_targets;
5327 protected override bool VerifyClsCompliance (DeclSpace ds)
5329 if (!base.VerifyClsCompliance (ds))
5332 if (FieldBuilder == null) {
5336 if (!AttributeTester.IsClsCompliant (FieldBuilder.FieldType)) {
5337 Report.Error_T (3003, Location, GetSignatureForError ());
5343 public void SetAssigned ()
5345 status |= Status.ASSIGNED;
5350 // The Field class is used to represents class/struct fields during parsing.
5352 public class Field : FieldBase {
5354 // Modifiers allowed in a class declaration
5356 const int AllowedModifiers =
5359 Modifiers.PROTECTED |
5360 Modifiers.INTERNAL |
5363 Modifiers.VOLATILE |
5367 public Field (TypeContainer parent, Expression type, int mod, string name,
5368 Object expr_or_array_init, Attributes attrs, Location loc)
5369 : base (parent, type, mod, AllowedModifiers, new MemberName (name),
5370 expr_or_array_init, attrs, loc)
5374 public override bool Define ()
5376 MemberType = Parent.ResolveType (Type, false, Location);
5378 if (MemberType == null)
5383 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5384 Report.Error (52, Location,
5385 "Inconsistent accessibility: field type `" +
5386 TypeManager.CSharpName (MemberType) + "' is less " +
5387 "accessible than field `" + Name + "'");
5391 if (MemberType.IsPointer && !UnsafeOK (Parent))
5394 if (RootContext.WarningLevel > 1){
5395 Type ptype = Parent.TypeBuilder.BaseType;
5397 // ptype is only null for System.Object while compiling corlib.
5399 TypeContainer.FindMembers (
5400 ptype, MemberTypes.Method,
5401 BindingFlags.Public |
5402 BindingFlags.Static | BindingFlags.Instance,
5403 System.Type.FilterName, Name);
5407 if ((ModFlags & Modifiers.VOLATILE) != 0){
5408 if (!MemberType.IsClass){
5409 Type vt = MemberType;
5411 if (TypeManager.IsEnumType (vt))
5412 vt = TypeManager.EnumToUnderlying (MemberType);
5414 if (!((vt == TypeManager.bool_type) ||
5415 (vt == TypeManager.sbyte_type) ||
5416 (vt == TypeManager.byte_type) ||
5417 (vt == TypeManager.short_type) ||
5418 (vt == TypeManager.ushort_type) ||
5419 (vt == TypeManager.int32_type) ||
5420 (vt == TypeManager.uint32_type) ||
5421 (vt == TypeManager.char_type) ||
5422 (vt == TypeManager.float_type) ||
5423 (!vt.IsValueType))){
5425 677, Location, Parent.MakeName (Name) +
5426 " A volatile field can not be of type `" +
5427 TypeManager.CSharpName (vt) + "'");
5432 if ((ModFlags & Modifiers.READONLY) != 0){
5435 "A field can not be both volatile and readonly");
5440 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
5442 if (Parent.Kind == Kind.Struct &&
5443 ((fa & FieldAttributes.Static) == 0) &&
5444 MemberType == Parent.TypeBuilder &&
5445 !TypeManager.IsBuiltinType (MemberType)){
5446 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
5447 "' causes a cycle in the structure layout");
5452 FieldBuilder = Parent.TypeBuilder.DefineField (
5453 Name, MemberType, Modifiers.FieldAttr (ModFlags));
5455 TypeManager.RegisterFieldBase (FieldBuilder, this);
5457 catch (ArgumentException) {
5458 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
5465 public override void Emit ()
5467 if (OptAttributes != null) {
5468 EmitContext ec = new EmitContext (
5469 Parent, Location, null, FieldBuilder.FieldType,
5471 OptAttributes.Emit (ec, this);
5479 // `set' and `get' accessors are represented with an Accessor.
5481 public class Accessor {
5483 // Null if the accessor is empty, or a Block if not
5486 public Attributes Attributes;
5488 public Accessor (Block b, Attributes attrs)
5496 // Ooouh Martin, templates are missing here.
5497 // When it will be possible move here a lot of child code and template method type.
5498 public abstract class AbstractPropertyEventMethod: Attributable, IMethodData
5500 protected MethodData method_data;
5501 protected Block block;
5503 ReturnParameter return_attributes;
5505 public AbstractPropertyEventMethod ():
5510 public AbstractPropertyEventMethod (Accessor accessor):
5511 base (accessor.Attributes)
5513 this.block = accessor.Block;
5516 #region IMethodData Members
5518 public Block Block {
5528 public CallingConventions CallingConventions {
5530 return CallingConventions.Standard;
5534 public bool IsExcluded (EmitContext ec)
5539 GenericMethod IMethodData.GenericMethod {
5545 public abstract ObsoleteAttribute GetObsoleteAttribute ();
5546 public abstract string GetSignatureForError (TypeContainer tc);
5547 public abstract Location Location { get; }
5548 public abstract string MethodName { get; }
5549 public abstract Type[] ParameterTypes { get; }
5550 public abstract Type ReturnType { get; }
5551 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
5555 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5557 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
5558 a.Type == TypeManager.conditional_attribute_type) {
5559 //"'{0}' is not valid on property or event accessors. It is valid on '{1}' declarations only"
5560 Report.Error_T (1667, a.Location, TypeManager.CSharpName (a.Type), a.GetValidTargets ());
5564 if (a.Target == "method") {
5565 method_data.MethodBuilder.SetCustomAttribute (cb);
5569 if (a.Target == "return") {
5570 if (return_attributes == null)
5571 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
5573 return_attributes.ApplyAttributeBuilder (a, cb);
5577 ApplyToExtraTarget (a, cb);
5580 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
5582 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
5585 public virtual void Emit (TypeContainer container)
5587 method_data.Emit (container, this);
5593 // Properties and Indexers both generate PropertyBuilders, we use this to share
5594 // their common bits.
5596 abstract public class PropertyBase : MethodCore {
5598 public class GetMethod: PropertyMethod
5600 static string[] attribute_targets = new string [] { "method", "return" };
5602 public GetMethod (MethodCore method, Accessor accessor):
5603 base (method, accessor)
5607 public override MethodBuilder Define(TypeContainer container)
5609 method_data = new MethodData (method, method.ParameterInfo, method.ModFlags, method.flags, this);
5611 if (!method_data.Define (container))
5614 return method_data.MethodBuilder;
5617 public override string GetSignatureForError (TypeContainer tc)
5619 return String.Concat (base.GetSignatureForError (tc), ".get");
5622 public override string MethodName
5625 return "get_" + method.ShortName;
5629 public override Type ReturnType {
5631 return method.MemberType;
5635 protected override string[] ValidAttributeTargets {
5637 return attribute_targets;
5642 public class SetMethod: PropertyMethod {
5644 static string[] attribute_targets = new string [] { "method", "param", "return" };
5645 ImplicitParameter param_attr;
5647 public SetMethod (MethodCore method, Accessor accessor):
5648 base (method, accessor)
5652 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
5654 if (a.Target == "param") {
5655 if (param_attr == null)
5656 param_attr = new ImplicitParameter (method_data.MethodBuilder);
5658 param_attr.ApplyAttributeBuilder (a, cb);
5662 base.ApplyAttributeBuilder (a, cb);
5665 protected virtual InternalParameters GetParameterInfo (TypeContainer container)
5667 Parameter [] parms = new Parameter [1];
5668 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null);
5669 return new InternalParameters (
5670 container, new Parameters (parms, null, method.Location));
5673 public override MethodBuilder Define(TypeContainer container)
5675 method_data = new MethodData (method, GetParameterInfo (container), method.ModFlags, method.flags, this);
5677 if (!method_data.Define (container))
5680 return method_data.MethodBuilder;
5683 public override string GetSignatureForError (TypeContainer tc)
5685 return String.Concat (base.GetSignatureForError (tc), ".set");
5688 public override string MethodName {
5690 return "set_" + method.ShortName;
5694 public override Type[] ParameterTypes {
5696 return new Type[] { method.MemberType };
5700 public override Type ReturnType {
5702 return TypeManager.void_type;
5706 protected override string[] ValidAttributeTargets {
5708 return attribute_targets;
5713 static string[] attribute_targets = new string [] { "property" };
5715 public abstract class PropertyMethod: AbstractPropertyEventMethod {
5716 protected readonly MethodCore method;
5718 public PropertyMethod (MethodCore method, Accessor accessor):
5721 this.method = method;
5724 public override AttributeTargets AttributeTargets {
5726 return AttributeTargets.Method | AttributeTargets.ReturnValue;
5730 public override bool IsClsCompliaceRequired(DeclSpace ds)
5732 return method.IsClsCompliaceRequired (ds);
5735 public InternalParameters ParameterInfo
5738 return method_data.ParameterInfo;
5742 public abstract MethodBuilder Define (TypeContainer container);
5744 public override Type[] ParameterTypes {
5746 return TypeManager.NoTypes;
5750 public override Location Location {
5752 return method.Location;
5756 public override EmitContext CreateEmitContext (TypeContainer tc,
5759 return new EmitContext (
5760 tc, method.ds, method.Location, ig, ReturnType,
5761 method.ModFlags, false);
5764 public override ObsoleteAttribute GetObsoleteAttribute ()
5766 return method.GetObsoleteAttribute (method.ds);
5769 public override string GetSignatureForError (TypeContainer tc)
5771 return String.Concat (tc.Name, '.', method.Name);
5775 public PropertyMethod Get, Set;
5776 public PropertyBuilder PropertyBuilder;
5777 public MethodBuilder GetBuilder, SetBuilder;
5779 protected EmitContext ec;
5781 public PropertyBase (TypeContainer parent, Expression type, int mod_flags,
5782 int allowed_mod, bool is_iface, MemberName name,
5783 Parameters parameters, Attributes attrs,
5785 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
5786 attrs, parameters, loc)
5790 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5792 PropertyBuilder.SetCustomAttribute (cb);
5795 public override AttributeTargets AttributeTargets {
5797 return AttributeTargets.Property;
5801 protected override bool DoDefine (DeclSpace decl)
5803 if (!base.DoDefine (decl))
5806 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5807 // "Field or property cannot be of type '{0}'";
5808 Report.Error_T (610, Location, TypeManager.CSharpName (MemberType));
5812 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
5817 public override string GetSignatureForError()
5819 return TypeManager.CSharpSignature (PropertyBuilder, false);
5822 protected virtual string RealMethodName {
5828 protected override bool IsIdentifierClsCompliant (DeclSpace ds)
5830 if (!IsIdentifierAndParamClsCompliant (ds, RealMethodName, null, null))
5833 if (Get != null && !IsIdentifierAndParamClsCompliant (ds, "get_" + RealMethodName, null, null))
5836 if (Set != null && !IsIdentifierAndParamClsCompliant (ds, "set_" + RealMethodName, null, null))
5844 // Checks our base implementation if any
5846 protected override bool CheckBase ()
5850 // Check whether arguments were correct.
5851 if (!DoDefineParameters ())
5858 // Check in our class for dups
5860 ArrayList ar = Parent.Properties;
5862 int arLen = ar.Count;
5864 for (int i = 0; i < arLen; i++) {
5865 Property m = (Property) ar [i];
5866 if (IsDuplicateImplementation (Parent, m))
5875 MethodSignature ms, base_ms;
5876 if (this is Indexer) {
5877 string name, base_name;
5879 report_name = "this";
5880 name = TypeManager.IndexerPropertyName (Parent.TypeBuilder);
5881 ms = new MethodSignature (name, null, ParameterTypes);
5882 base_name = TypeManager.IndexerPropertyName (Parent.TypeBuilder.BaseType);
5883 base_ms = new MethodSignature (base_name, null, ParameterTypes);
5886 ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
5890 // Verify if the parent has a type with the same name, and then
5891 // check whether we have to create a new slot for it or not.
5893 Type ptype = Parent.TypeBuilder.BaseType;
5895 // ptype is only null for System.Object while compiling corlib.
5896 if (ptype == null) {
5897 if ((ModFlags & Modifiers.NEW) != 0)
5898 WarningNotHiding (Parent);
5903 MemberInfo parent_member = null;
5906 // Explicit implementations do not have `parent' methods, however,
5907 // the member cache stores them there. Without this check, we get
5908 // an incorrect warning in corlib.
5910 if (! IsExplicitImpl) {
5911 parent_member = ((IMemberContainer)Parent).Parent.MemberCache.FindMemberToOverride (
5912 Parent.TypeBuilder, Name, ParameterTypes, true);
5915 if (parent_member is PropertyInfo) {
5916 PropertyInfo parent_property = (PropertyInfo)parent_member;
5918 string name = parent_property.DeclaringType.Name + "." +
5919 parent_property.Name;
5921 MethodInfo get, set, parent_method;
5922 get = parent_property.GetGetMethod (true);
5923 set = parent_property.GetSetMethod (true);
5926 parent_method = get;
5927 else if (set != null)
5928 parent_method = set;
5930 throw new Exception ("Internal error!");
5932 if (!CheckMethodAgainstBase (Parent, flags, parent_method, name))
5935 if ((ModFlags & Modifiers.NEW) == 0) {
5936 Type parent_type = TypeManager.TypeToCoreType (
5937 parent_property.PropertyType);
5939 if (parent_type != MemberType) {
5941 508, Location, Parent.MakeName (Name) + ": cannot " +
5942 "change return type when overriding " +
5943 "inherited member " + name);
5947 } else if (parent_member == null){
5948 if ((ModFlags & Modifiers.NEW) != 0)
5949 WarningNotHiding (Parent);
5951 if ((ModFlags & Modifiers.OVERRIDE) != 0){
5952 if (this is Indexer)
5953 Report.Error (115, Location,
5954 Parent.MakeName (Name) +
5955 " no suitable indexers found to override");
5957 Report.Error (115, Location,
5958 Parent.MakeName (Name) +
5959 " no suitable properties found to override");
5966 public override void Emit ()
5969 // The PropertyBuilder can be null for explicit implementations, in that
5970 // case, we do not actually emit the ".property", so there is nowhere to
5971 // put the attribute
5973 if (PropertyBuilder != null && OptAttributes != null)
5974 OptAttributes.Emit (ec, this);
5985 protected override string[] ValidAttributeTargets {
5987 return attribute_targets;
5992 public class Property : PropertyBase, IIteratorContainer {
5993 const int AllowedModifiers =
5996 Modifiers.PROTECTED |
5997 Modifiers.INTERNAL |
6001 Modifiers.OVERRIDE |
6002 Modifiers.ABSTRACT |
6005 Modifiers.METHOD_YIELDS |
6008 const int AllowedInterfaceModifiers =
6011 public Property (TypeContainer parent, Expression type, int mod_flags,
6012 bool is_iface, MemberName name, Attributes attrs,
6013 Accessor get_block, Accessor set_block, Location loc)
6014 : base (parent, type, mod_flags,
6015 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6016 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs,
6019 if (get_block != null)
6020 Get = new GetMethod (this, get_block);
6022 if (set_block != null)
6023 Set = new SetMethod (this, set_block);
6026 public override bool Define ()
6028 if (!DoDefineBase ())
6031 if (!DoDefine (Parent))
6037 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6041 GetBuilder = Get.Define (Parent);
6042 if (GetBuilder == null)
6046 // Setup iterator if we are one
6048 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
6049 Iterator iterator = new Iterator (
6050 Parent, "get", MemberType,
6051 TypeManager.NoTypes, Get.ParameterInfo,
6052 ModFlags, Get.Block, Location);
6054 if (!iterator.DefineIterator ())
6056 Get.Block = iterator.Block;
6061 SetBuilder = Set.Define (Parent);
6062 if (SetBuilder == null)
6065 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
6068 // FIXME - PropertyAttributes.HasDefault ?
6070 PropertyAttributes prop_attr = PropertyAttributes.None;
6072 prop_attr |= PropertyAttributes.RTSpecialName |
6073 PropertyAttributes.SpecialName;
6075 if (!IsExplicitImpl){
6076 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6077 Name, prop_attr, MemberType, null);
6080 PropertyBuilder.SetGetMethod (GetBuilder);
6083 PropertyBuilder.SetSetMethod (SetBuilder);
6086 // HACK for the reasons exposed above
6088 if (!TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder)) {
6091 "Class `" + Parent.Name +
6092 "' already contains a definition for the property `" +
6100 public void SetYields ()
6102 ModFlags |= Modifiers.METHOD_YIELDS;
6107 /// Gigantic workaround for lameness in SRE follows :
6108 /// This class derives from EventInfo and attempts to basically
6109 /// wrap around the EventBuilder so that FindMembers can quickly
6110 /// return this in it search for members
6112 public class MyEventBuilder : EventInfo {
6115 // We use this to "point" to our Builder which is
6116 // not really a MemberInfo
6118 EventBuilder MyBuilder;
6121 // We "catch" and wrap these methods
6123 MethodInfo raise, remove, add;
6125 EventAttributes attributes;
6126 Type declaring_type, reflected_type, event_type;
6131 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6133 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6135 // And now store the values in our own fields.
6137 declaring_type = type_builder;
6139 reflected_type = type_builder;
6141 attributes = event_attr;
6144 this.event_type = event_type;
6148 // Methods that you have to override. Note that you only need
6149 // to "implement" the variants that take the argument (those are
6150 // the "abstract" methods, the others (GetAddMethod()) are
6153 public override MethodInfo GetAddMethod (bool nonPublic)
6158 public override MethodInfo GetRemoveMethod (bool nonPublic)
6163 public override MethodInfo GetRaiseMethod (bool nonPublic)
6169 // These methods make "MyEventInfo" look like a Builder
6171 public void SetRaiseMethod (MethodBuilder raiseMethod)
6173 raise = raiseMethod;
6174 MyBuilder.SetRaiseMethod (raiseMethod);
6177 public void SetRemoveOnMethod (MethodBuilder removeMethod)
6179 remove = removeMethod;
6180 MyBuilder.SetRemoveOnMethod (removeMethod);
6183 public void SetAddOnMethod (MethodBuilder addMethod)
6186 MyBuilder.SetAddOnMethod (addMethod);
6189 public void SetCustomAttribute (CustomAttributeBuilder cb)
6191 MyBuilder.SetCustomAttribute (cb);
6194 public override object [] GetCustomAttributes (bool inherit)
6196 // FIXME : There's nothing which can be seemingly done here because
6197 // we have no way of getting at the custom attribute objects of the
6202 public override object [] GetCustomAttributes (Type t, bool inherit)
6204 // FIXME : Same here !
6208 public override bool IsDefined (Type t, bool b)
6213 public override EventAttributes Attributes {
6219 public override string Name {
6225 public override Type DeclaringType {
6227 return declaring_type;
6231 public override Type ReflectedType {
6233 return reflected_type;
6237 public Type EventType {
6243 public void SetUsed ()
6245 if (my_event != null)
6246 my_event.status = (FieldBase.Status.ASSIGNED | FieldBase.Status.USED);
6251 /// For case when event is declared like property (with add and remove accessors).
6253 public class EventProperty: Event {
6255 static string[] attribute_targets = new string [] { "event", "property" };
6257 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
6258 bool is_iface, MemberName name, Object init,
6259 Attributes attrs, Accessor add, Accessor remove,
6261 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6263 Add = new AddDelegateMethod (this, add);
6264 Remove = new RemoveDelegateMethod (this, remove);
6267 protected override string[] ValidAttributeTargets {
6269 return attribute_targets;
6275 /// Event is declared like field.
6277 public class EventField: Event {
6279 static string[] attribute_targets = new string [] { "event", "field", "method" };
6281 public EventField (TypeContainer parent, Expression type, int mod_flags,
6282 bool is_iface, MemberName name, Object init,
6283 Attributes attrs, Location loc)
6284 : base (parent, type, mod_flags, is_iface, name, init, attrs, loc)
6286 Add = new AddDelegateMethod (this);
6287 Remove = new RemoveDelegateMethod (this);
6290 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6292 if (a.Target == "field") {
6293 FieldBuilder.SetCustomAttribute (cb);
6297 if (a.Target == "method") {
6298 AddBuilder.SetCustomAttribute (cb);
6299 RemoveBuilder.SetCustomAttribute (cb);
6303 base.ApplyAttributeBuilder (a, cb);
6306 protected override string[] ValidAttributeTargets {
6308 return attribute_targets;
6313 public abstract class Event : FieldBase {
6315 protected sealed class AddDelegateMethod: DelegateMethod
6317 public AddDelegateMethod (Event method):
6322 public AddDelegateMethod (Event method, Accessor accessor):
6323 base (method, accessor)
6327 public override string MethodName {
6329 return "add_" + method.ShortName;
6333 protected override MethodInfo DelegateMethodInfo {
6335 return TypeManager.delegate_combine_delegate_delegate;
6341 protected sealed class RemoveDelegateMethod: DelegateMethod
6343 public RemoveDelegateMethod (Event method):
6348 public RemoveDelegateMethod (Event method, Accessor accessor):
6349 base (method, accessor)
6353 public override string MethodName {
6355 return "remove_" + method.ShortName;
6359 protected override MethodInfo DelegateMethodInfo {
6361 return TypeManager.delegate_remove_delegate_delegate;
6367 public abstract class DelegateMethod: AbstractPropertyEventMethod
6369 protected readonly Event method;
6370 ImplicitParameter param_attr;
6372 static string[] attribute_targets = new string [] { "method", "param", "return" };
6374 public DelegateMethod (Event method)
6376 this.method = method;
6379 public DelegateMethod (Event method, Accessor accessor):
6382 this.method = method;
6385 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6387 if (a.Target == "param") {
6388 if (param_attr == null)
6389 param_attr = new ImplicitParameter (method_data.MethodBuilder);
6391 param_attr.ApplyAttributeBuilder (a, cb);
6395 base.ApplyAttributeBuilder (a, cb);
6398 public override AttributeTargets AttributeTargets {
6400 return AttributeTargets.Method;
6404 public override bool IsClsCompliaceRequired(DeclSpace ds)
6406 return method.IsClsCompliaceRequired (ds);
6409 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
6411 method_data = new MethodData (method, ip, method.ModFlags,
6412 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
6414 if (!method_data.Define (container))
6417 MethodBuilder mb = method_data.MethodBuilder;
6418 mb.DefineParameter (1, ParameterAttributes.None, "value");
6423 public override void Emit (TypeContainer tc)
6425 if (block != null) {
6430 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
6431 EmitContext ec = CreateEmitContext (tc, ig);
6432 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
6434 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
6435 if ((method.ModFlags & Modifiers.STATIC) != 0) {
6436 ig.Emit (OpCodes.Ldsfld, field_info);
6437 ig.Emit (OpCodes.Ldarg_0);
6438 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6439 ig.Emit (OpCodes.Castclass, method.MemberType);
6440 ig.Emit (OpCodes.Stsfld, field_info);
6442 ig.Emit (OpCodes.Ldarg_0);
6443 ig.Emit (OpCodes.Ldarg_0);
6444 ig.Emit (OpCodes.Ldfld, field_info);
6445 ig.Emit (OpCodes.Ldarg_1);
6446 ig.Emit (OpCodes.Call, DelegateMethodInfo);
6447 ig.Emit (OpCodes.Castclass, method.MemberType);
6448 ig.Emit (OpCodes.Stfld, field_info);
6450 ig.Emit (OpCodes.Ret);
6453 protected abstract MethodInfo DelegateMethodInfo { get; }
6455 public override Type[] ParameterTypes {
6457 return new Type[] { method.MemberType };
6461 public override Type ReturnType {
6463 return TypeManager.void_type;
6467 public override Location Location {
6469 return method.Location;
6473 public override EmitContext CreateEmitContext (TypeContainer tc,
6476 return new EmitContext (
6477 tc, method.Parent, Location, ig, ReturnType,
6478 method.ModFlags, false);
6481 public override string GetSignatureForError (TypeContainer tc)
6483 return String.Concat (tc.Name, '.', method.Name);
6486 public override ObsoleteAttribute GetObsoleteAttribute ()
6488 return method.GetObsoleteAttribute (method.Parent);
6491 protected override string[] ValidAttributeTargets {
6493 return attribute_targets;
6499 const int AllowedModifiers =
6502 Modifiers.PROTECTED |
6503 Modifiers.INTERNAL |
6508 Modifiers.OVERRIDE |
6512 const int AllowedInterfaceModifiers =
6515 protected DelegateMethod Add, Remove;
6516 public MyEventBuilder EventBuilder;
6517 public MethodBuilder AddBuilder, RemoveBuilder;
6519 MethodData AddData, RemoveData;
6521 public Event (TypeContainer parent, Expression type, int mod_flags,
6522 bool is_iface, MemberName name, Object init, Attributes attrs,
6524 : base (parent, type, mod_flags,
6525 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6526 name, init, attrs, loc)
6528 IsInterface = is_iface;
6531 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6533 EventBuilder.SetCustomAttribute (cb);
6536 public override AttributeTargets AttributeTargets {
6538 return AttributeTargets.Event;
6542 public override bool Define ()
6544 EventAttributes e_attr;
6545 e_attr = EventAttributes.None;
6547 if (!DoDefineBase ())
6550 if (!DoDefine (Parent))
6553 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
6554 Report.Error (74, Location, "'" + Parent.Name + "." + Name +
6555 "': abstract event can not have an initializer");
6559 if (!TypeManager.IsDelegateType (MemberType)) {
6560 Report.Error (66, Location, "'" + Parent.Name + "." + Name +
6561 "' : event must be of a delegate type");
6565 Parameter [] parms = new Parameter [1];
6566 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
6567 InternalParameters ip = new InternalParameters (
6568 Parent, new Parameters (parms, null, Location));
6574 // Now define the accessors
6577 AddBuilder = Add.Define (Parent, ip);
6578 if (AddBuilder == null)
6581 RemoveBuilder = Remove.Define (Parent, ip);
6582 if (RemoveBuilder == null)
6585 if (!IsExplicitImpl){
6586 EventBuilder = new MyEventBuilder (this,
6587 Parent.TypeBuilder, Name, e_attr, MemberType);
6589 if (Add.Block == null && Remove.Block == null &&
6591 FieldBuilder = Parent.TypeBuilder.DefineField (
6593 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
6594 TypeManager.RegisterPrivateFieldOfEvent (
6595 (EventInfo) EventBuilder, FieldBuilder);
6596 TypeManager.RegisterFieldBase (FieldBuilder, this);
6599 EventBuilder.SetAddOnMethod (AddBuilder);
6600 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
6602 if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
6603 Report.Error (111, Location,
6604 "Class `" + Parent.Name +
6605 "' already contains a definition for the event `" +
6614 public override void Emit ()
6616 if (OptAttributes != null) {
6617 EmitContext ec = new EmitContext (
6618 Parent, Location, null, MemberType, ModFlags);
6619 OptAttributes.Emit (ec, this);
6624 Remove.Emit (Parent);
6630 public override string GetSignatureForError ()
6632 return TypeManager.GetFullNameSignature (EventBuilder);
6637 // FIXME: This does not handle:
6639 // int INTERFACENAME [ args ]
6644 // int this [ args ]
6646 public class Indexer : PropertyBase {
6648 class GetIndexerMethod: GetMethod
6650 public GetIndexerMethod (MethodCore method, Accessor accessor):
6651 base (method, accessor)
6655 public override Type[] ParameterTypes {
6657 return method.ParameterTypes;
6662 class SetIndexerMethod: SetMethod
6664 readonly Parameters parameters;
6666 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
6667 base (method, accessor)
6669 this.parameters = parameters;
6672 public override Type[] ParameterTypes {
6674 int top = method.ParameterTypes.Length;
6675 Type [] set_pars = new Type [top + 1];
6676 method.ParameterTypes.CopyTo (set_pars, 0);
6677 set_pars [top] = method.MemberType;
6682 protected override InternalParameters GetParameterInfo (TypeContainer container)
6684 Parameter [] fixed_parms = parameters.FixedParameters;
6686 if (fixed_parms == null){
6687 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
6688 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6689 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6691 // Here is the problem: the `value' parameter has
6692 // to come *after* the array parameter in the declaration
6694 // X (object [] x, Type value)
6697 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6698 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
6702 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
6704 fixed_parms.CopyTo (tmp, 0);
6705 tmp [fixed_parms.Length] = new Parameter (
6706 method.Type, "value", Parameter.Modifier.NONE, null);
6708 Parameters set_formal_params = new Parameters (tmp, null, method.Location);
6710 return new InternalParameters (container, set_formal_params);
6716 const int AllowedModifiers =
6719 Modifiers.PROTECTED |
6720 Modifiers.INTERNAL |
6724 Modifiers.OVERRIDE |
6729 const int AllowedInterfaceModifiers =
6732 public string IndexerName = "Item";
6733 public string InterfaceIndexerName;
6736 // Are we implementing an interface ?
6738 public Indexer (TypeContainer parent, Expression type, int mod_flags,
6739 bool is_iface, MemberName name, Parameters parameters,
6740 Attributes attrs, Accessor get_block, Accessor set_block,
6742 : base (parent, type, mod_flags,
6743 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6744 is_iface, name, parameters, attrs, loc)
6746 if (get_block != null)
6747 Get = new GetIndexerMethod (this, get_block);
6749 if (set_block != null)
6750 Set = new SetIndexerMethod (this, parameters, set_block);
6753 public override bool Define ()
6755 PropertyAttributes prop_attr =
6756 PropertyAttributes.RTSpecialName |
6757 PropertyAttributes.SpecialName;
6759 if (!DoDefineBase ())
6762 if (!DoDefine (Parent))
6765 if (OptAttributes != null) {
6766 Attribute indexer_attr = OptAttributes.GetIndexerNameAttribute (ec);
6767 if (indexer_attr != null) {
6768 IndexerName = indexer_attr.GetIndexerAttributeValue (ec);
6769 if (IsExplicitImpl) {
6770 // The 'IndexerName' attribute is valid only on an indexer that is not an explicit interface member declaration
6771 Report.Error_T (415, indexer_attr.Location);
6775 if (IsExplicitImpl) {
6776 // The 'IndexerName' attribute is valid only on an indexer that is not an explicit interface member declaration
6777 Report.Error_T (415, indexer_attr.Location);
6781 if (!Tokenizer.IsValidIdentifier (IndexerName)) {
6782 // The argument to the 'IndexerName' attribute must be a valid identifier
6783 Report.Error_T (633, indexer_attr.Location);
6789 ShortName = IndexerName;
6790 if (IsExplicitImpl) {
6791 InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
6792 Name = InterfaceType.FullName + "." + IndexerName;
6794 InterfaceIndexerName = IndexerName;
6798 if (!CheckNameCollision (Parent))
6804 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6806 GetBuilder = Get.Define (Parent);
6807 if (GetBuilder == null)
6812 SetBuilder = Set.Define (Parent);
6813 if (SetBuilder == null)
6818 // Now name the parameters
6820 Parameter [] p = Parameters.FixedParameters;
6824 for (i = 0; i < p.Length; ++i) {
6826 GetBuilder.DefineParameter (
6827 i + 1, p [i].Attributes, p [i].Name);
6830 SetBuilder.DefineParameter (
6831 i + 1, p [i].Attributes, p [i].Name);
6835 SetBuilder.DefineParameter (
6836 i + 1, ParameterAttributes.None, "value");
6838 if (i != ParameterTypes.Length) {
6839 Parameter array_param = Parameters.ArrayParameter;
6841 SetBuilder.DefineParameter (
6842 i + 1, array_param.Attributes, array_param.Name);
6847 // Define the PropertyBuilder if one of the following conditions are met:
6848 // a) we're not implementing an interface indexer.
6849 // b) the indexer has a different IndexerName and this is no
6850 // explicit interface implementation.
6852 if (!IsExplicitImpl) {
6853 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6854 IndexerName, prop_attr, MemberType, ParameterTypes);
6857 PropertyBuilder.SetGetMethod (GetBuilder);
6860 PropertyBuilder.SetSetMethod (SetBuilder);
6862 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
6869 bool CheckNameCollision (TypeContainer container) {
6870 switch (VerifyName (container)){
6871 case DeclSpace.AdditionResult.NameExists:
6872 Report.Error (102, Location, "The container '{0}' already contains a definition for '{1}'", container.GetSignatureForError (), Name);
6875 case DeclSpace.AdditionResult.Success:
6878 throw new NotImplementedException ();
6881 DeclSpace.AdditionResult VerifyName (TypeContainer container) {
6882 if (!AddIndexer (container, container.Name + "." + Name))
6883 return DeclSpace.AdditionResult.NameExists;
6886 if (!AddIndexer (container, container.Name + ".get_" + Name))
6887 return DeclSpace.AdditionResult.NameExists;
6891 if (!AddIndexer (container, container.Name + ".set_" + Name))
6892 return DeclSpace.AdditionResult.NameExists;
6894 return DeclSpace.AdditionResult.Success;
6897 bool AddIndexer (TypeContainer container, string fullname)
6899 object value = container.GetDefinition (fullname);
6901 if (value != null) {
6902 return value.GetType () != GetType () ? false : true;
6905 container.DefineName (fullname, this);
6909 public override string GetSignatureForError ()
6911 return TypeManager.CSharpSignature (PropertyBuilder, true);
6914 protected override string RealMethodName {
6921 public class Operator : MemberBase, IIteratorContainer {
6923 const int AllowedModifiers =
6929 const int RequiredModifiers =
6933 public enum OpType : byte {
6943 // Unary and Binary operators
6966 // Implicit and Explicit
6971 public readonly OpType OperatorType;
6972 public readonly Expression ReturnType;
6973 public readonly Expression FirstArgType, SecondArgType;
6974 public readonly string FirstArgName, SecondArgName;
6976 public MethodBuilder OperatorMethodBuilder;
6978 public string MethodName;
6979 public Method OperatorMethod;
6981 static string[] attribute_targets = new string [] { "method", "return" };
6983 public Operator (TypeContainer parent, OpType type, Expression ret_type,
6984 int mod_flags, Expression arg1type, string arg1name,
6985 Expression arg2type, string arg2name,
6986 Block block, Attributes attrs, Location loc)
6987 : base (parent, ret_type, mod_flags, AllowedModifiers,
6988 Modifiers.PUBLIC, MemberName.Null, attrs, loc)
6990 OperatorType = type;
6991 Name = "op_" + OperatorType;
6992 ReturnType = ret_type;
6993 FirstArgType = arg1type;
6994 FirstArgName = arg1name;
6995 SecondArgType = arg2type;
6996 SecondArgName = arg2name;
7000 string Prototype (TypeContainer container)
7002 return container.Name + ".operator " + OperatorType + " (" + FirstArgType + "," +
7003 SecondArgType + ")";
7006 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7008 OperatorMethod.ApplyAttributeBuilder (a, cb);
7011 public override AttributeTargets AttributeTargets {
7013 return AttributeTargets.Method;
7017 protected override bool CheckGenericOverride (MethodInfo method, string name)
7022 public override bool Define ()
7025 MethodName = "op_" + OperatorType;
7027 if (SecondArgType != null)
7030 Parameter [] param_list = new Parameter [length];
7032 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7035 "User defined operators `" +
7036 Prototype (Parent) +
7037 "' must be declared static and public");
7041 param_list[0] = new Parameter (FirstArgType, FirstArgName,
7042 Parameter.Modifier.NONE, null);
7043 if (SecondArgType != null)
7044 param_list[1] = new Parameter (SecondArgType, SecondArgName,
7045 Parameter.Modifier.NONE, null);
7047 OperatorMethod = new Method (
7048 Parent, null, ReturnType, ModFlags, false,
7049 new MemberName (MethodName),
7050 new Parameters (param_list, null, Location),
7051 OptAttributes, Location);
7053 OperatorMethod.Block = Block;
7054 OperatorMethod.IsOperator = true;
7055 OperatorMethod.Define ();
7057 if (OperatorMethod.MethodBuilder == null)
7060 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7062 Type [] param_types = OperatorMethod.ParameterTypes;
7063 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
7064 Type return_type = OperatorMethod.GetReturnType ();
7065 Type first_arg_type = param_types [0];
7067 // Rules for conversion operators
7069 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7070 if (first_arg_type == return_type && first_arg_type == declaring_type){
7073 "User-defined conversion cannot take an object of the " +
7074 "enclosing type and convert to an object of the enclosing" +
7079 if (first_arg_type != declaring_type && return_type != declaring_type){
7082 "User-defined conversion must convert to or from the " +
7087 if (first_arg_type == TypeManager.object_type ||
7088 return_type == TypeManager.object_type){
7091 "User-defined conversion cannot convert to or from " +
7096 if (first_arg_type.IsInterface || return_type.IsInterface){
7099 "User-defined conversion cannot convert to or from an " +
7104 if (first_arg_type.IsSubclassOf (return_type)
7105 || return_type.IsSubclassOf (first_arg_type)){
7106 if (declaring_type.IsSubclassOf (return_type)) {
7107 // '{0}' : user defined conversion to/from base class
7108 Report.Error_T (553, Location, GetSignatureForError ());
7111 // '{0}' : user defined conversion to/from derived class
7112 Report.Error_T (554, Location, GetSignatureForError ());
7115 } else if (SecondArgType == null) {
7116 // Checks for Unary operators
7118 if (first_arg_type != declaring_type){
7121 "The parameter of a unary operator must be the " +
7126 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7127 if (return_type != declaring_type){
7130 "The parameter and return type for ++ and -- " +
7131 "must be the containing type");
7137 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7138 if (return_type != TypeManager.bool_type){
7141 "The return type of operator True or False " +
7148 // Checks for Binary operators
7150 if (first_arg_type != declaring_type &&
7151 param_types [1] != declaring_type){
7154 "One of the parameters of a binary operator must " +
7155 "be the containing type");
7163 public override void Emit ()
7166 // abstract or extern methods have no bodies
7168 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7171 OperatorMethod.Emit ();
7175 public static string GetName (OpType ot)
7178 case OpType.LogicalNot:
7180 case OpType.OnesComplement:
7182 case OpType.Increment:
7184 case OpType.Decrement:
7190 case OpType.Addition:
7192 case OpType.Subtraction:
7194 case OpType.UnaryPlus:
7196 case OpType.UnaryNegation:
7198 case OpType.Multiply:
7200 case OpType.Division:
7202 case OpType.Modulus:
7204 case OpType.BitwiseAnd:
7206 case OpType.BitwiseOr:
7208 case OpType.ExclusiveOr:
7210 case OpType.LeftShift:
7212 case OpType.RightShift:
7214 case OpType.Equality:
7216 case OpType.Inequality:
7218 case OpType.GreaterThan:
7220 case OpType.LessThan:
7222 case OpType.GreaterThanOrEqual:
7224 case OpType.LessThanOrEqual:
7226 case OpType.Implicit:
7228 case OpType.Explicit:
7234 public override string GetSignatureForError(TypeContainer tc)
7239 public override string GetSignatureForError()
7244 public override string ToString ()
7246 Type return_type = OperatorMethod.GetReturnType();
7247 Type [] param_types = OperatorMethod.ParameterTypes;
7249 if (SecondArgType == null)
7250 return String.Format (
7251 "{0} operator {1}({2})",
7252 TypeManager.CSharpName (return_type),
7253 GetName (OperatorType),
7256 return String.Format (
7257 "{0} operator {1}({2}, {3})",
7258 TypeManager.CSharpName (return_type),
7259 GetName (OperatorType),
7260 param_types [0], param_types [1]);
7263 protected override string[] ValidAttributeTargets {
7265 return attribute_targets;
7269 public void SetYields ()
7271 ModFlags |= Modifiers.METHOD_YIELDS;
7276 // This is used to compare method signatures
7278 struct MethodSignature {
7280 public Type RetType;
7281 public Type [] Parameters;
7284 /// This delegate is used to extract methods which have the
7285 /// same signature as the argument
7287 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
7289 public MethodSignature (string name, Type ret_type, Type [] parameters)
7294 if (parameters == null)
7295 Parameters = TypeManager.NoTypes;
7297 Parameters = parameters;
7300 public override string ToString ()
7303 if (Parameters.Length != 0){
7304 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
7305 for (int i = 0; i < Parameters.Length; i++){
7306 sb.Append (Parameters [i]);
7307 if (i+1 < Parameters.Length)
7310 pars = sb.ToString ();
7313 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
7316 public override int GetHashCode ()
7318 return Name.GetHashCode ();
7321 public override bool Equals (Object o)
7323 MethodSignature other = (MethodSignature) o;
7325 if (other.Name != Name)
7328 if (other.RetType != RetType)
7331 if (Parameters == null){
7332 if (other.Parameters == null)
7337 if (other.Parameters == null)
7340 int c = Parameters.Length;
7341 if (other.Parameters.Length != c)
7344 for (int i = 0; i < c; i++)
7345 if (other.Parameters [i] != Parameters [i])
7351 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
7353 MethodSignature sig = (MethodSignature) filter_criteria;
7355 if (m.Name != sig.Name)
7359 MethodInfo mi = m as MethodInfo;
7360 PropertyInfo pi = m as PropertyInfo;
7363 ReturnType = mi.ReturnType;
7364 else if (pi != null)
7365 ReturnType = pi.PropertyType;
7370 // we use sig.RetType == null to mean `do not check the
7371 // method return value.
7373 if (sig.RetType != null)
7374 if (ReturnType != sig.RetType)
7379 args = TypeManager.GetArgumentTypes (mi);
7381 args = TypeManager.GetArgumentTypes (pi);
7382 Type [] sigp = sig.Parameters;
7384 if (args.Length != sigp.Length)
7387 for (int i = args.Length; i > 0; ){
7389 if (args [i] != sigp [i])