2 // class.cs: Class and Struct handlers
4 // Authors: Miguel de Icaza (miguel@gnu.org)
5 // Martin Baulig (martin@ximian.com)
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)
11 // (C) 2004 Novell, Inc
14 // 2002-10-11 Miguel de Icaza <miguel@ximian.com>
16 // * class.cs: Following the comment from 2002-09-26 to AddMethod, I
17 // have fixed a remaining problem: not every AddXXXX was adding a
18 // fully qualified name.
20 // Now everyone registers a fully qualified name in the DeclSpace as
21 // being defined instead of the partial name.
23 // Downsides: we are slower than we need to be due to the excess
24 // copies and the names being registered this way.
26 // The reason for this is that we currently depend (on the corlib
27 // bootstrap for instance) that types are fully qualified, because
28 // we dump all the types in the namespace, and we should really have
29 // types inserted into the proper namespace, so we can only store the
30 // basenames in the defined_names array.
36 using System.Collections;
37 using System.Collections.Specialized;
38 using System.Reflection;
39 using System.Reflection.Emit;
40 using System.Runtime.CompilerServices;
41 using System.Runtime.InteropServices;
42 using System.Security;
43 using System.Security.Permissions;
46 using Mono.CompilerServices.SymbolWriter;
48 namespace Mono.CSharp {
58 /// This is the base class for structs and classes.
60 public abstract class TypeContainer : DeclSpace, IMemberContainer {
62 public class MemberCoreArrayList: ArrayList
65 /// Defines the MemberCore objects that are in this array
67 public virtual void DefineContainerMembers ()
69 foreach (MemberCore mc in this) {
74 public virtual void Emit ()
76 foreach (MemberCore mc in this)
81 public class MethodArrayList : MemberCoreArrayList
89 CachedMethods cached_method;
90 TypeContainer container;
92 public MethodArrayList (TypeContainer container)
94 this.container = container;
98 /// Method container contains Equals method
100 public bool HasEquals {
102 cached_method |= CachedMethods.Equals;
106 return (cached_method & CachedMethods.Equals) != 0;
111 /// Method container contains GetHashCode method
113 public bool HasGetHashCode {
115 cached_method |= CachedMethods.GetHashCode;
119 return (cached_method & CachedMethods.GetHashCode) != 0;
123 public override void DefineContainerMembers ()
125 base.DefineContainerMembers ();
127 if ((RootContext.WarningLevel >= 3) && HasEquals && !HasGetHashCode) {
128 Report.Warning (659, container.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", container.GetSignatureForError ());
134 public sealed class IndexerArrayList : MemberCoreArrayList
137 /// The indexer name for this container
139 public string IndexerName = DefaultIndexerName;
141 bool seen_normal_indexers = false;
143 TypeContainer container;
145 public IndexerArrayList (TypeContainer container)
147 this.container = container;
151 /// Defines the indexers, and also verifies that the IndexerNameAttribute in the
152 /// class is consistent. Either it is `Item' or it is the name defined by all the
153 /// indexers with the `IndexerName' attribute.
155 /// Turns out that the IndexerNameAttribute is applied to each indexer,
156 /// but it is never emitted, instead a DefaultMember attribute is attached
159 public override void DefineContainerMembers()
161 base.DefineContainerMembers ();
163 string class_indexer_name = null;
166 // If there's both an explicit and an implicit interface implementation, the
167 // explicit one actually implements the interface while the other one is just
168 // a normal indexer. See bug #37714.
171 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
172 foreach (Indexer i in this) {
173 if (i.InterfaceType != null) {
174 if (seen_normal_indexers)
175 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
179 seen_normal_indexers = true;
181 if (class_indexer_name == null) {
182 class_indexer_name = i.ShortName;
186 if (i.ShortName != class_indexer_name)
187 Report.Error (668, i.Location, "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
190 if (class_indexer_name != null)
191 IndexerName = class_indexer_name;
194 public override void Emit ()
198 if (!seen_normal_indexers)
201 CustomAttributeBuilder cb = new CustomAttributeBuilder (TypeManager.default_member_ctor, new string [] { IndexerName });
202 container.TypeBuilder.SetCustomAttribute (cb);
206 public class OperatorArrayList: MemberCoreArrayList
208 TypeContainer container;
210 public OperatorArrayList (TypeContainer container)
212 this.container = container;
216 // Operator pair checking
221 public Type ret_type;
222 public Type type1, type2;
224 public Operator.OpType ot;
226 public OperatorEntry (int f, Operator o)
230 ret_type = o.OperatorMethod.ReturnType;
231 Type [] pt = o.OperatorMethod.ParameterTypes;
238 public override int GetHashCode ()
240 return ret_type.GetHashCode ();
243 public override bool Equals (object o)
245 OperatorEntry other = (OperatorEntry) o;
247 if (other.ret_type != ret_type)
249 if (other.type1 != type1)
251 if (other.type2 != type2)
258 // Checks that some operators come in pairs:
264 // They are matched based on the return type and the argument types
266 void CheckPairedOperators ()
268 Hashtable pairs = new Hashtable (null, null);
269 Operator true_op = null;
270 Operator false_op = null;
271 bool has_equality_or_inequality = false;
273 // Register all the operators we care about.
274 foreach (Operator op in this){
277 // Skip erroneous code.
278 if (op.OperatorMethod == null)
281 switch (op.OperatorType){
282 case Operator.OpType.Equality:
284 has_equality_or_inequality = true;
286 case Operator.OpType.Inequality:
288 has_equality_or_inequality = true;
291 case Operator.OpType.True:
294 case Operator.OpType.False:
298 case Operator.OpType.GreaterThan:
300 case Operator.OpType.LessThan:
303 case Operator.OpType.GreaterThanOrEqual:
305 case Operator.OpType.LessThanOrEqual:
311 OperatorEntry oe = new OperatorEntry (reg, op);
313 object o = pairs [oe];
317 oe = (OperatorEntry) o;
322 if (true_op != null){
323 if (false_op == null)
324 Report.Error (216, true_op.Location, "The operator `{0}' requires a matching operator `false' to also be defined",
325 true_op.GetSignatureForError ());
326 } else if (false_op != null)
327 Report.Error (216, false_op.Location, "The operator `{0}' requires a matching operator `true' to also be defined",
328 false_op.GetSignatureForError ());
331 // Look for the mistakes.
333 foreach (DictionaryEntry de in pairs){
334 OperatorEntry oe = (OperatorEntry) de.Key;
341 case Operator.OpType.Equality:
344 case Operator.OpType.Inequality:
347 case Operator.OpType.GreaterThan:
350 case Operator.OpType.LessThan:
353 case Operator.OpType.GreaterThanOrEqual:
356 case Operator.OpType.LessThanOrEqual:
360 Report.Error (216, oe.op.Location,
361 "The operator `{0}' requires a matching operator `{1}' to also be defined",
362 oe.op.GetSignatureForError (), s);
365 if (has_equality_or_inequality && (RootContext.WarningLevel > 2)) {
366 if (container.Methods == null || !container.Methods.HasEquals)
367 Report.Warning (660, container.Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)", container.GetSignatureForError ());
369 if (container.Methods == null || !container.Methods.HasGetHashCode)
370 Report.Warning (661, container.Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()", container.GetSignatureForError ());
374 public override void DefineContainerMembers ()
376 base.DefineContainerMembers ();
377 CheckPairedOperators ();
382 // Whether this is a struct, class or interface
383 public readonly Kind Kind;
385 // Holds a list of classes and structures
388 // Holds the list of properties
389 MemberCoreArrayList properties;
391 // Holds the list of enumerations
392 MemberCoreArrayList enums;
394 // Holds the list of delegates
395 MemberCoreArrayList delegates;
397 // Holds the list of constructors
398 protected MemberCoreArrayList instance_constructors;
400 // Holds the list of fields
401 MemberCoreArrayList fields;
403 // Holds a list of fields that have initializers
404 protected ArrayList initialized_fields;
406 // Holds a list of static fields that have initializers
407 protected ArrayList initialized_static_fields;
409 // Holds the list of constants
410 MemberCoreArrayList constants;
413 MemberCoreArrayList interfaces;
415 // Holds the methods.
416 MethodArrayList methods;
419 protected MemberCoreArrayList events;
421 // Holds the indexers
422 IndexerArrayList indexers;
424 // Holds the operators
425 MemberCoreArrayList operators;
427 // Holds the iterators
430 // Holds the parts of a partial class;
434 // Pointers to the default constructor and the default static constructor
436 protected Constructor default_constructor;
437 protected Constructor default_static_constructor;
440 // Points to the first non-static field added to the container.
442 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
443 // and the first one's as good as any.
445 FieldBase first_nonstatic_field = null;
448 // This one is computed after we can distinguish interfaces
449 // from classes from the arraylist `type_bases'
451 string base_class_name;
453 TypeExpr[] iface_exprs;
455 ArrayList type_bases;
457 bool members_defined;
458 bool members_defined_ok;
460 // The interfaces we implement.
461 protected Type[] ifaces;
462 protected Type ptype;
464 // The base member cache and our member cache
465 MemberCache base_cache;
466 MemberCache member_cache;
468 public const string DefaultIndexerName = "Item";
471 GenericTypeParameterBuilder[] gen_params;
473 public TypeContainer (NamespaceEntry ns, TypeContainer parent, MemberName name,
474 Attributes attrs, Kind kind)
475 : base (ns, parent, name, attrs)
477 if (parent != null && parent != RootContext.Tree.Types && parent.NamespaceEntry != ns)
478 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
482 types = new ArrayList ();
484 base_class_name = null;
487 public bool AddToMemberContainer (MemberCore symbol)
489 return AddToContainer (symbol, symbol.Name);
492 protected virtual bool AddToTypeContainer (DeclSpace ds)
494 return AddToContainer (ds, ds.Basename);
497 public void AddConstant (Const constant)
499 if (!AddToMemberContainer (constant))
502 if (constants == null)
503 constants = new MemberCoreArrayList ();
505 constants.Add (constant);
508 public void AddEnum (Mono.CSharp.Enum e)
510 if (!AddToTypeContainer (e))
514 enums = new MemberCoreArrayList ();
519 public bool AddClassOrStruct (TypeContainer c)
521 if (!AddToTypeContainer (c))
528 public void AddDelegate (Delegate d)
530 if (!AddToTypeContainer (d))
533 if (delegates == null)
534 delegates = new MemberCoreArrayList ();
539 public void AddMethod (Method method)
541 if (!AddToMemberContainer (method))
545 methods = new MethodArrayList (this);
547 if (method.MemberName.Left != null)
548 methods.Insert (0, method);
550 methods.Add (method);
553 public void AddConstructor (Constructor c)
555 if (c.Name != MemberName.Name) {
556 Report.Error (1520, c.Location, "Class, struct, or interface method must have a return type");
559 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
562 if (default_static_constructor != null) {
563 Report.SymbolRelatedToPreviousError (default_static_constructor);
564 Report.Error (111, c.Location, Error111, c.GetSignatureForError ());
568 default_static_constructor = c;
571 if (default_constructor != null) {
572 Report.SymbolRelatedToPreviousError (default_constructor);
573 Report.Error (111, c.Location, Error111, c.Location, c.GetSignatureForError ());
576 default_constructor = c;
579 if (instance_constructors == null)
580 instance_constructors = new MemberCoreArrayList ();
582 instance_constructors.Add (c);
586 internal static string Error111 {
588 return "`{0}' is already defined. Rename this member or use different parameter types";
592 public bool AddInterface (TypeContainer iface)
594 if (!AddToTypeContainer (iface))
597 if (interfaces == null) {
598 interfaces = new MemberCoreArrayList ();
601 interfaces.Add (iface);
605 public void AddField (FieldMember field)
607 if (!AddToMemberContainer (field))
611 fields = new MemberCoreArrayList ();
615 if (field.HasInitializer)
616 RegisterFieldForInitialization (field);
618 if ((field.ModFlags & Modifiers.STATIC) != 0)
621 if (first_nonstatic_field == null) {
622 first_nonstatic_field = field;
626 if (Kind == Kind.Struct &&
627 first_nonstatic_field.Parent != field.Parent &&
628 RootContext.WarningLevel >= 3) {
629 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
630 Report.Warning (282, field.Location,
631 "struct instance field `{0}' found in different declaration from instance field `{1}'",
632 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
636 public void AddProperty (Property prop)
638 if (!AddToMemberContainer (prop) ||
639 !AddToMemberContainer (prop.Get) || !AddToMemberContainer (prop.Set))
642 if (properties == null)
643 properties = new MemberCoreArrayList ();
645 if (prop.MemberName.Left != null)
646 properties.Insert (0, prop);
648 properties.Add (prop);
651 public void AddEvent (Event e)
653 if (!AddToMemberContainer (e))
656 if (e is EventProperty) {
657 if (!AddToMemberContainer (e.Add))
660 if (!AddToMemberContainer (e.Remove))
665 events = new MemberCoreArrayList ();
671 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
673 public void AddIndexer (Indexer i)
675 if (indexers == null)
676 indexers = new IndexerArrayList (this);
678 if (i.IsExplicitImpl)
679 indexers.Insert (0, i);
684 public void AddOperator (Operator op)
686 if (!AddToMemberContainer (op))
689 if (operators == null)
690 operators = new OperatorArrayList (this);
695 public void AddIterator (Iterator i)
697 if (iterators == null)
698 iterators = new ArrayList ();
703 public void AddType (TypeContainer tc)
708 public void AddPart (ClassPart part)
711 parts = new ArrayList ();
716 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
718 if (a.Type == TypeManager.default_member_type) {
719 if (Indexers != null) {
720 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
725 base.ApplyAttributeBuilder (a, cb);
728 public override AttributeTargets AttributeTargets {
732 return AttributeTargets.Class;
734 return AttributeTargets.Struct;
736 return AttributeTargets.Interface;
738 throw new NotSupportedException ();
743 public ArrayList Types {
749 public MethodArrayList Methods {
755 public ArrayList Constants {
761 public ArrayList Interfaces {
767 public ArrayList Iterators {
775 return base_class_name;
779 public ArrayList Bases {
789 public ArrayList Fields {
795 public ArrayList InstanceConstructors {
797 return instance_constructors;
801 public ArrayList Properties {
807 public ArrayList Events {
813 public ArrayList Enums {
819 public ArrayList Indexers {
825 public ArrayList Operators {
831 public ArrayList Delegates {
837 public ArrayList Parts {
843 protected override TypeAttributes TypeAttr {
845 return Modifiers.TypeAttr (ModFlags, this) | base.TypeAttr;
849 public string IndexerName {
851 return indexers == null ? DefaultIndexerName : indexers.IndexerName;
855 public virtual void RegisterFieldForInitialization (FieldMember field)
857 if ((field.ModFlags & Modifiers.STATIC) != 0){
858 if (initialized_static_fields == null)
859 initialized_static_fields = new ArrayList ();
861 initialized_static_fields.Add (field);
863 if (initialized_fields == null)
864 initialized_fields = new ArrayList ();
866 initialized_fields.Add (field);
870 bool CanElideInitializer (Type field_type, Constant c)
872 if (field_type == c.Type)
874 if (TypeManager.IsValueType (field_type) || TypeManager.HasElementType (field_type))
876 // Reference type with null initializer.
877 return c.Type == TypeManager.null_type;
881 // Emits the instance field initializers
883 public virtual bool EmitFieldInitializers (EmitContext ec)
886 Expression instance_expr;
889 fields = initialized_static_fields;
890 instance_expr = null;
892 fields = initialized_fields;
893 instance_expr = new This (Location.Null).Resolve (ec);
899 foreach (FieldMember f in fields){
900 Expression e = f.GetInitializerExpression (ec);
904 Location l = f.Location;
905 FieldExpr fe = new FieldExpr (f.FieldBuilder, l, true);
906 fe.InstanceExpression = instance_expr;
908 ExpressionStatement a = new Assign (fe, e, l);
910 a = a.ResolveStatement (ec);
914 Constant c = e as Constant;
915 if (c != null && c.IsDefaultValue && CanElideInitializer (f.MemberType, c))
918 a.EmitStatement (ec);
925 // Defines the default constructors
927 protected void DefineDefaultConstructor (bool is_static)
931 // The default constructor is public
932 // If the class is abstract, the default constructor is protected
933 // The default static constructor is private
935 int mods = Modifiers.PUBLIC;
937 mods = Modifiers.STATIC | Modifiers.PRIVATE;
938 else if ((ModFlags & Modifiers.ABSTRACT) != 0)
939 mods = Modifiers.PROTECTED;
941 TypeContainer constructor_parent = this;
943 constructor_parent = (TypeContainer) Parts [0];
945 c = new Constructor (constructor_parent, MemberName.Name, mods,
946 Parameters.EmptyReadOnlyParameters,
947 new GeneratedBaseInitializer (Location),
952 c.Block = new ToplevelBlock (null, Location);
957 /// The pending methods that need to be implemented
958 // (interfaces or abstract methods)
960 public PendingImplementation Pending;
962 public abstract PendingImplementation GetPendingImplementations ();
964 TypeExpr[] GetPartialBases (out TypeExpr base_class)
966 ArrayList ifaces = new ArrayList ();
969 Location base_loc = Location.Null;
971 foreach (ClassPart part in parts) {
972 TypeExpr new_base_class;
973 TypeExpr[] new_ifaces;
975 new_ifaces = part.GetClassBases (out new_base_class);
976 if (new_ifaces == null && new_base_class != null)
979 if ((base_class != null) && (new_base_class != null) &&
980 !base_class.Equals (new_base_class)) {
981 Report.Error (263, part.Location,
982 "Partial declarations of `{0}' must " +
983 "not specify different base classes",
986 if (!base_loc.IsNull)
987 Report.LocationOfPreviousError (base_loc);
992 if ((base_class == null) && (new_base_class != null)) {
993 base_class = new_base_class;
994 base_loc = part.Location;
997 if (new_ifaces == null)
1000 foreach (TypeExpr iface in new_ifaces) {
1002 foreach (TypeExpr old_iface in ifaces) {
1003 if (old_iface.Equals (iface)) {
1014 TypeExpr[] retval = new TypeExpr [ifaces.Count];
1015 ifaces.CopyTo (retval, 0);
1019 TypeExpr[] GetNormalBases (out TypeExpr base_class)
1023 int count = Bases.Count;
1024 int start = 0, i, j;
1026 if (Kind == Kind.Class){
1027 TypeExpr name = ResolveBaseTypeExpr (
1028 (Expression) Bases [0], false, Location);
1034 if (!name.IsInterface) {
1035 // base_class could be a class, struct, enum, delegate.
1036 // This is validated in GetClassBases.
1042 TypeExpr [] ifaces = new TypeExpr [count-start];
1044 for (i = start, j = 0; i < count; i++, j++){
1045 TypeExpr resolved = ResolveBaseTypeExpr ((Expression) Bases [i], false, Location);
1046 if (resolved == null) {
1050 ifaces [j] = resolved;
1057 /// This function computes the Base class and also the
1058 /// list of interfaces that the class or struct @c implements.
1060 /// The return value is an array (might be null) of
1061 /// interfaces implemented (as Types).
1063 /// The @base_class argument is set to the base object or null
1064 /// if this is `System.Object'.
1066 protected virtual TypeExpr [] GetClassBases (out TypeExpr base_class)
1073 ifaces = GetPartialBases (out base_class);
1074 else if (Bases == null){
1078 ifaces = GetNormalBases (out base_class);
1083 if ((base_class != null) && (Kind == Kind.Class)){
1084 if (base_class is TypeParameterExpr){
1086 689, base_class.Location,
1087 "Type parameter `{0}' can not be used as a " +
1088 "base class or interface", base_class.Name);
1093 if (base_class.Type.IsArray || base_class.Type.IsPointer) {
1094 Report.Error (1521, base_class.Location, "Invalid base type");
1098 if (base_class.IsSealed){
1099 Report.SymbolRelatedToPreviousError (base_class.Type);
1100 if (base_class.Type.IsAbstract) {
1101 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
1102 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
1104 Report.Error (509, Location, "`{0}': cannot derive from sealed class `{1}'",
1105 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
1110 if (!base_class.CanInheritFrom ()){
1111 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
1112 GetSignatureForError (), base_class.GetSignatureForError ());
1116 if (!base_class.AsAccessible (this, ModFlags)) {
1117 Report.SymbolRelatedToPreviousError (base_class.Type);
1118 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
1119 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
1123 if (base_class != null)
1124 base_class_name = base_class.Name;
1129 int count = ifaces != null ? ifaces.Length : 0;
1131 for (i = 0; i < count; i++) {
1132 TypeExpr iface = (TypeExpr) ifaces [i];
1134 if (!iface.IsInterface) {
1135 if (Kind != Kind.Class) {
1136 // TODO: location of symbol related ....
1137 Error_TypeInListIsNotInterface (Location, iface.FullName);
1139 else if (base_class != null)
1140 Report.Error (1721, Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1141 GetSignatureForError (), base_class.GetSignatureForError (), iface.GetSignatureForError ());
1143 Report.Error (1722, Location, "`{0}': Base class `{1}' must be specified as first",
1144 GetSignatureForError (), iface.GetSignatureForError ());
1149 for (int x = 0; x < i; x++) {
1150 if (iface.Equals (ifaces [x])) {
1151 Report.Error (528, Location,
1152 "`{0}' is already listed in " +
1153 "interface list", iface.Name);
1158 if ((Kind == Kind.Interface) &&
1159 !iface.AsAccessible (Parent, ModFlags)) {
1160 Report.Error (61, Location,
1161 "Inconsistent accessibility: base " +
1162 "interface `{0}' is less accessible " +
1163 "than interface `{1}'", iface.Name,
1171 bool CheckGenericInterfaces (Type[] ifaces)
1173 ArrayList already_checked = new ArrayList ();
1175 for (int i = 0; i < ifaces.Length; i++) {
1176 Type iface = ifaces [i];
1177 foreach (Type t in already_checked) {
1181 Type[] infered = new Type [CountTypeParameters];
1182 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, infered, null))
1187 "`{0}' cannot implement both `{1}' and `{2}' " +
1188 "because they may unify for some type " +
1189 "parameter substitutions",
1190 TypeManager.GetFullName (TypeBuilder),
1195 already_checked.Add (iface);
1203 protected void Error_TypeInListIsNotInterface (Location loc, string type)
1205 Report.Error (527, loc, "Type `{0}' in interface list is not an interface", type);
1209 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1211 public override TypeBuilder DefineType ()
1216 if (TypeBuilder != null)
1219 TypeAttributes type_attributes = TypeAttr;
1223 if (TypeManager.NamespaceClash (Name, Location)) {
1228 ModuleBuilder builder = CodeGen.Module.Builder;
1229 TypeBuilder = builder.DefineType (
1230 Name, type_attributes, null, null);
1232 TypeBuilder builder = Parent.TypeBuilder;
1233 if (builder == null) {
1238 TypeBuilder = builder.DefineNestedType (
1239 Basename, type_attributes, ptype, null);
1241 } catch (ArgumentException) {
1242 Report.RuntimeMissingSupport (Location, "static classes");
1247 TypeManager.AddUserType (Name, this);
1249 if (Parts != null) {
1251 foreach (ClassPart part in Parts) {
1252 part.TypeBuilder = TypeBuilder;
1253 part.ec = new EmitContext (part, Mono.CSharp.Location.Null, null, null, ModFlags);
1254 part.ec.ContainerType = TypeBuilder;
1258 // Normally, we create the EmitContext here.
1259 // The only exception is if we're an Iterator - in this case,
1260 // we already have the `ec', so we don't want to create a new one.
1263 ec = new EmitContext (this, Mono.CSharp.Location.Null, null, null, ModFlags);
1264 ec.ContainerType = TypeBuilder;
1268 string[] param_names = new string [TypeParameters.Length];
1269 for (int i = 0; i < TypeParameters.Length; i++)
1270 param_names [i] = TypeParameters [i].Name;
1272 gen_params = TypeBuilder.DefineGenericParameters (param_names);
1274 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1275 for (int i = offset; i < gen_params.Length; i++)
1276 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1279 iface_exprs = GetClassBases (out base_type);
1280 if (iface_exprs == null && base_type != null) {
1286 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1287 // which in turn should have called DefineType()s on base types if necessary.
1289 // None of the code below should trigger DefineType()s on classes that we depend on.
1290 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1292 // Let's do it as soon as possible, since code below can call DefineType() on classes
1293 // that depend on us to be populated before they are.
1295 if (!(this is Iterator))
1296 RootContext.RegisterOrder (this);
1298 if (base_type == null) {
1299 if (Kind == Kind.Class){
1300 if (RootContext.StdLib)
1301 base_type = TypeManager.system_object_expr;
1302 else if (Name != "System.Object")
1303 base_type = TypeManager.system_object_expr;
1304 } else if (Kind == Kind.Struct){
1306 // If we are compiling our runtime,
1307 // and we are defining ValueType, then our
1308 // base is `System.Object'.
1310 if (!RootContext.StdLib && Name == "System.ValueType")
1311 base_type = TypeManager.system_object_expr;
1312 else if (Kind == Kind.Struct)
1313 base_type = TypeManager.system_valuetype_expr;
1317 // Avoid attributes check when parent is not set
1318 TypeResolveEmitContext.TestObsoleteMethodUsage = false;
1320 if (base_type != null) {
1321 // FIXME: I think this should be ...ResolveType (Parent.EmitContext).
1322 // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
1323 FullNamedExpression fne = base_type.ResolveAsTypeStep (TypeResolveEmitContext);
1324 if ((fne == null) || (fne.Type == null)) {
1331 if (IsGeneric && TypeManager.IsAttributeType (ptype)) {
1332 Report.Error (698, base_type.Location,
1333 "A generic type cannot derive from `{0}' " +
1334 "because it is an attribute class",
1341 if (!CheckRecursiveDefinition (this)) {
1346 if (ptype != null) {
1347 TypeBuilder.SetParent (ptype);
1350 // Attribute is undefined at the begining of corlib compilation
1351 if (TypeManager.obsolete_attribute_type != null) {
1352 TypeResolveEmitContext.TestObsoleteMethodUsage = GetObsoleteAttribute () == null;
1353 if (ptype != null && TypeResolveEmitContext.TestObsoleteMethodUsage) {
1354 CheckObsoleteType (base_type);
1358 // add interfaces that were not added at type creation
1359 if (iface_exprs != null) {
1360 // FIXME: I think this should be ...ExpandInterfaces (Parent.EmitContext, ...).
1361 // However, if Parent == RootContext.Tree.Types, its NamespaceEntry will be null.
1362 TypeResolveEmitContext.ContainerType = TypeBuilder;
1363 ifaces = TypeManager.ExpandInterfaces (TypeResolveEmitContext, iface_exprs);
1364 if (ifaces == null) {
1369 foreach (Type itype in ifaces)
1370 TypeBuilder.AddInterfaceImplementation (itype);
1372 if (!CheckGenericInterfaces (ifaces)) {
1377 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1380 if (this is Iterator && !ResolveType ()) {
1385 if (!DefineNestedTypes ()) {
1393 public bool ResolveType ()
1395 if ((base_type != null) &&
1396 (base_type.ResolveType (TypeResolveEmitContext) == null)) {
1404 TypeExpr current_type = null;
1405 if (Parts != null) {
1406 foreach (ClassPart part in Parts) {
1407 if (!part.DefineTypeParameters ()) {
1413 foreach (TypeParameter type_param in CurrentTypeParameters) {
1414 if (!type_param.Resolve (this)) {
1420 int offset = CountTypeParameters - CurrentTypeParameters.Length;
1421 for (int i = offset; i < gen_params.Length; i++)
1422 CurrentTypeParameters [i - offset].DefineConstraints ();
1424 foreach (TypeParameter type_param in TypeParameters) {
1425 if (!type_param.DefineType (ec)) {
1431 current_type = new ConstructedType (
1432 TypeBuilder, TypeParameters, Location);
1435 foreach (TypeParameter type_param in TypeParameters)
1436 if (!type_param.CheckDependencies (ec)) {
1441 if (current_type != null) {
1442 current_type = current_type.ResolveAsTypeTerminal (ec);
1443 if (current_type == null) {
1448 CurrentType = current_type.ResolveType (ec);
1454 protected virtual bool DefineNestedTypes ()
1456 if (Interfaces != null) {
1457 foreach (TypeContainer iface in Interfaces)
1458 if (iface.DefineType () == null)
1462 if (Types != null) {
1463 foreach (TypeContainer tc in Types)
1464 if (tc.DefineType () == null)
1468 if (Delegates != null) {
1469 foreach (Delegate d in Delegates)
1470 if (d.DefineType () == null)
1474 if (Enums != null) {
1475 foreach (Enum en in Enums)
1476 if (en.DefineType () == null)
1483 TypeContainer InTransit;
1485 protected bool CheckRecursiveDefinition (TypeContainer tc)
1487 if (InTransit != null) {
1488 Report.SymbolRelatedToPreviousError (this);
1489 if (this is Interface)
1491 529, tc.Location, "Inherited interface `{0}' causes a " +
1492 "cycle in the interface hierarchy of `{1}'",
1493 GetSignatureForError (), tc.GetSignatureForError ());
1496 146, tc.Location, "Circular base class dependency " +
1497 "involving `{0}' and `{1}'",
1498 tc.GetSignatureForError (), GetSignatureForError ());
1504 Type parent = ptype;
1505 if (parent != null) {
1506 if (parent.IsGenericInstance)
1507 parent = parent.GetGenericTypeDefinition ();
1509 TypeContainer ptc = TypeManager.LookupTypeContainer (parent);
1510 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1514 if (iface_exprs != null) {
1515 foreach (TypeExpr iface in iface_exprs) {
1516 Type itype = iface.Type;
1518 if (itype.IsGenericInstance)
1519 itype = itype.GetGenericTypeDefinition ();
1521 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1522 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1531 public static void Error_KeywordNotAllowed (Location loc)
1533 Report.Error (1530, loc, "Keyword `new' is not allowed on namespace elements");
1537 /// Populates our TypeBuilder with fields and methods
1539 public override bool DefineMembers (TypeContainer container)
1541 if (members_defined)
1542 return members_defined_ok;
1544 if (!base.DefineMembers (container))
1547 members_defined_ok = DoDefineMembers ();
1548 members_defined = true;
1550 return members_defined_ok;
1553 protected virtual bool DoDefineMembers ()
1555 if (iface_exprs != null) {
1556 foreach (TypeExpr iface in iface_exprs) {
1557 ConstructedType ct = iface as ConstructedType;
1558 if ((ct != null) && !ct.CheckConstraints (ec))
1563 if (base_type != null) {
1564 ConstructedType ct = base_type as ConstructedType;
1565 if ((ct != null) && !ct.CheckConstraints (ec))
1570 MemberInfo conflict_symbol = Parent.MemberCache.FindMemberWithSameName (Basename, false, TypeBuilder);
1571 if (conflict_symbol == null) {
1572 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0))
1573 Report.Warning (109, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1575 if ((ModFlags & Modifiers.NEW) == 0) {
1576 Report.SymbolRelatedToPreviousError (conflict_symbol);
1577 Report.Warning (108, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1578 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1583 DefineContainerMembers (constants);
1584 DefineContainerMembers (fields);
1586 if ((Kind == Kind.Class) && !(this is ClassPart)){
1587 if ((instance_constructors == null) &&
1588 !(this is StaticClass)) {
1589 if (default_constructor == null)
1590 DefineDefaultConstructor (false);
1593 if (initialized_static_fields != null &&
1594 default_static_constructor == null)
1595 DefineDefaultConstructor (true);
1598 if (Kind == Kind.Struct){
1600 // Structs can not have initialized instance
1603 if (initialized_static_fields != null &&
1604 default_static_constructor == null)
1605 DefineDefaultConstructor (true);
1607 if (initialized_fields != null)
1608 ReportStructInitializedInstanceError ();
1611 Pending = GetPendingImplementations ();
1613 if (parts != null) {
1614 foreach (ClassPart part in parts) {
1615 if (!part.DefineMembers (this))
1621 // Constructors are not in the defined_names array
1623 DefineContainerMembers (instance_constructors);
1625 if (default_static_constructor != null)
1626 default_static_constructor.Define ();
1628 DefineContainerMembers (properties);
1629 DefineContainerMembers (events);
1630 DefineContainerMembers (indexers);
1631 DefineContainerMembers (methods);
1632 DefineContainerMembers (operators);
1633 DefineContainerMembers (enums);
1634 DefineContainerMembers (delegates);
1636 if (CurrentType != null) {
1637 GenericType = CurrentType;
1639 ec.ContainerType = GenericType;
1644 if (!(this is ClassPart))
1645 member_cache = new MemberCache (this);
1648 if (parts != null) {
1649 foreach (ClassPart part in parts)
1650 part.member_cache = member_cache;
1653 if (iterators != null) {
1654 foreach (Iterator iterator in iterators) {
1655 if (iterator.DefineType () == null)
1659 foreach (Iterator iterator in iterators) {
1660 if (!iterator.DefineMembers (this))
1668 void ReportStructInitializedInstanceError ()
1670 foreach (Field f in initialized_fields){
1671 Report.Error (573, Location,
1672 "`{0}': Structs cannot have instance field initializers",
1673 f.GetSignatureForError ());
1677 protected virtual void DefineContainerMembers (MemberCoreArrayList mcal)
1680 mcal.DefineContainerMembers ();
1683 public override bool Define ()
1685 if (parts != null) {
1686 foreach (ClassPart part in parts) {
1687 if (!part.Define ())
1692 if (iterators != null) {
1693 foreach (Iterator iterator in iterators) {
1694 if (!iterator.Define ())
1702 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1704 return BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1708 /// This function is based by a delegate to the FindMembers routine
1710 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1716 /// This filter is used by FindMembers, and we just keep
1717 /// a global for the filter to `AlwaysAccept'
1719 static MemberFilter accepting_filter;
1722 static TypeContainer ()
1724 accepting_filter = new MemberFilter (AlwaysAccept);
1727 public MethodInfo[] GetMethods ()
1729 ArrayList members = new ArrayList ();
1731 DefineMembers (null);
1733 if (methods != null) {
1734 int len = methods.Count;
1735 for (int i = 0; i < len; i++) {
1736 Method m = (Method) methods [i];
1738 members.Add (m.MethodBuilder);
1742 if (operators != null) {
1743 int len = operators.Count;
1744 for (int i = 0; i < len; i++) {
1745 Operator o = (Operator) operators [i];
1747 members.Add (o.OperatorMethodBuilder);
1751 if (properties != null) {
1752 int len = properties.Count;
1753 for (int i = 0; i < len; i++) {
1754 Property p = (Property) properties [i];
1756 if (p.GetBuilder != null)
1757 members.Add (p.GetBuilder);
1758 if (p.SetBuilder != null)
1759 members.Add (p.SetBuilder);
1763 if (indexers != null) {
1764 int len = indexers.Count;
1765 for (int i = 0; i < len; i++) {
1766 Indexer ix = (Indexer) indexers [i];
1768 if (ix.GetBuilder != null)
1769 members.Add (ix.GetBuilder);
1770 if (ix.SetBuilder != null)
1771 members.Add (ix.SetBuilder);
1775 if (events != null) {
1776 int len = events.Count;
1777 for (int i = 0; i < len; i++) {
1778 Event e = (Event) events [i];
1780 if (e.AddBuilder != null)
1781 members.Add (e.AddBuilder);
1782 if (e.RemoveBuilder != null)
1783 members.Add (e.RemoveBuilder);
1787 MethodInfo[] retMethods = new MethodInfo [members.Count];
1788 members.CopyTo (retMethods, 0);
1792 // Indicated whether container has StructLayout attribute set Explicit
1793 public virtual bool HasExplicitLayout {
1799 public override Type FindNestedType (string name)
1801 ArrayList [] lists = { types, enums, delegates, interfaces };
1803 for (int j = 0; j < lists.Length; ++j) {
1804 ArrayList list = lists [j];
1808 int len = list.Count;
1809 for (int i = 0; i < len; ++i) {
1810 DeclSpace ds = (DeclSpace) list [i];
1811 if (ds.Basename == name) {
1813 return ds.TypeBuilder;
1821 private void FindMembers_NestedTypes (int modflags,
1822 BindingFlags bf, MemberFilter filter, object criteria,
1823 ref ArrayList members)
1825 ArrayList [] lists = { types, enums, delegates, interfaces };
1827 for (int j = 0; j < lists.Length; ++j) {
1828 ArrayList list = lists [j];
1832 int len = list.Count;
1833 for (int i = 0; i < len; i++) {
1834 DeclSpace ds = (DeclSpace) list [i];
1836 if ((ds.ModFlags & modflags) == 0)
1839 TypeBuilder tb = ds.TypeBuilder;
1841 if (!(criteria is string) || ds.Basename.Equals (criteria))
1842 tb = ds.DefineType ();
1845 if (tb != null && (filter (tb, criteria) == true)) {
1846 if (members == null)
1847 members = new ArrayList ();
1856 /// This method returns the members of this type just like Type.FindMembers would
1857 /// Only, we need to use this for types which are _being_ defined because MS'
1858 /// implementation can't take care of that.
1861 // FIXME: return an empty static array instead of null, that cleans up
1862 // some code and is consistent with some coding conventions I just found
1866 // Notice that in various cases we check if our field is non-null,
1867 // something that would normally mean that there was a bug elsewhere.
1869 // The problem happens while we are defining p-invoke methods, as those
1870 // will trigger a FindMembers, but this happens before things are defined
1872 // Since the whole process is a no-op, it is fine to check for null here.
1874 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1875 MemberFilter filter, object criteria)
1877 ArrayList members = null;
1880 if ((bf & BindingFlags.Public) != 0)
1881 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1883 if ((bf & BindingFlags.NonPublic) != 0)
1884 modflags |= Modifiers.PRIVATE;
1886 int static_mask = 0, static_flags = 0;
1887 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1888 case BindingFlags.Static:
1889 static_mask = static_flags = Modifiers.STATIC;
1892 case BindingFlags.Instance:
1893 static_mask = Modifiers.STATIC;
1898 static_mask = static_flags = 0;
1902 Timer.StartTimer (TimerType.TcFindMembers);
1905 filter = accepting_filter;
1907 if ((mt & MemberTypes.Field) != 0) {
1908 if (fields != null) {
1909 int len = fields.Count;
1910 for (int i = 0; i < len; i++) {
1911 FieldMember f = (FieldMember) fields [i];
1913 if ((f.ModFlags & modflags) == 0)
1915 if ((f.ModFlags & static_mask) != static_flags)
1918 FieldBuilder fb = f.FieldBuilder;
1919 if (fb != null && filter (fb, criteria) == true) {
1920 if (members == null)
1921 members = new ArrayList ();
1928 if (constants != null) {
1929 int len = constants.Count;
1930 for (int i = 0; i < len; i++) {
1931 Const con = (Const) constants [i];
1933 if ((con.ModFlags & modflags) == 0)
1935 if ((con.ModFlags & static_mask) != static_flags)
1938 FieldBuilder fb = con.FieldBuilder;
1941 fb = con.FieldBuilder;
1943 if (fb != null && filter (fb, criteria) == true) {
1944 if (members == null)
1945 members = new ArrayList ();
1953 if ((mt & MemberTypes.Method) != 0) {
1954 if (methods != null) {
1955 int len = methods.Count;
1956 for (int i = 0; i < len; i++) {
1957 Method m = (Method) methods [i];
1959 if ((m.ModFlags & modflags) == 0)
1961 if ((m.ModFlags & static_mask) != static_flags)
1964 MethodBuilder mb = m.MethodBuilder;
1966 if (mb != null && filter (mb, criteria) == true) {
1967 if (members == null)
1968 members = new ArrayList ();
1975 if (operators != null) {
1976 int len = operators.Count;
1977 for (int i = 0; i < len; i++) {
1978 Operator o = (Operator) operators [i];
1980 if ((o.ModFlags & modflags) == 0)
1982 if ((o.ModFlags & static_mask) != static_flags)
1985 MethodBuilder ob = o.OperatorMethodBuilder;
1986 if (ob != null && filter (ob, criteria) == true) {
1987 if (members == null)
1988 members = new ArrayList ();
1995 if (properties != null) {
1996 int len = properties.Count;
1997 for (int i = 0; i < len; i++) {
1998 Property p = (Property) properties [i];
2000 if ((p.ModFlags & modflags) == 0)
2002 if ((p.ModFlags & static_mask) != static_flags)
2008 if (b != null && filter (b, criteria) == true) {
2009 if (members == null)
2010 members = new ArrayList ();
2016 if (b != null && filter (b, criteria) == true) {
2017 if (members == null)
2018 members = new ArrayList ();
2025 if (indexers != null) {
2026 int len = indexers.Count;
2027 for (int i = 0; i < len; i++) {
2028 Indexer ix = (Indexer) indexers [i];
2030 if ((ix.ModFlags & modflags) == 0)
2032 if ((ix.ModFlags & static_mask) != static_flags)
2038 if (b != null && filter (b, criteria) == true) {
2039 if (members == null)
2040 members = new ArrayList ();
2046 if (b != null && filter (b, criteria) == true) {
2047 if (members == null)
2048 members = new ArrayList ();
2056 if ((mt & MemberTypes.Event) != 0) {
2057 if (events != null) {
2058 int len = events.Count;
2059 for (int i = 0; i < len; i++) {
2060 Event e = (Event) events [i];
2062 if ((e.ModFlags & modflags) == 0)
2064 if ((e.ModFlags & static_mask) != static_flags)
2067 MemberInfo eb = e.EventBuilder;
2068 if (eb != null && filter (eb, criteria) == true) {
2069 if (members == null)
2070 members = new ArrayList ();
2072 members.Add (e.EventBuilder);
2078 if ((mt & MemberTypes.Property) != 0){
2079 if (properties != null) {
2080 int len = properties.Count;
2081 for (int i = 0; i < len; i++) {
2082 Property p = (Property) properties [i];
2084 if ((p.ModFlags & modflags) == 0)
2086 if ((p.ModFlags & static_mask) != static_flags)
2089 MemberInfo pb = p.PropertyBuilder;
2090 if (pb != null && filter (pb, criteria) == true) {
2091 if (members == null)
2092 members = new ArrayList ();
2094 members.Add (p.PropertyBuilder);
2099 if (indexers != null) {
2100 int len = indexers.Count;
2101 for (int i = 0; i < len; i++) {
2102 Indexer ix = (Indexer) indexers [i];
2104 if ((ix.ModFlags & modflags) == 0)
2106 if ((ix.ModFlags & static_mask) != static_flags)
2109 MemberInfo ib = ix.PropertyBuilder;
2110 if (ib != null && filter (ib, criteria) == true) {
2111 if (members == null)
2112 members = new ArrayList ();
2114 members.Add (ix.PropertyBuilder);
2120 if ((mt & MemberTypes.NestedType) != 0)
2121 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
2123 if ((mt & MemberTypes.Constructor) != 0){
2124 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
2125 int len = instance_constructors.Count;
2126 for (int i = 0; i < len; i++) {
2127 Constructor c = (Constructor) instance_constructors [i];
2129 ConstructorBuilder cb = c.ConstructorBuilder;
2130 if (cb != null && filter (cb, criteria) == true) {
2131 if (members == null)
2132 members = new ArrayList ();
2139 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
2140 ConstructorBuilder cb =
2141 default_static_constructor.ConstructorBuilder;
2143 if (cb != null && filter (cb, criteria) == true) {
2144 if (members == null)
2145 members = new ArrayList ();
2153 // Lookup members in base if requested.
2155 if ((bf & BindingFlags.DeclaredOnly) == 0) {
2156 if (TypeBuilder.BaseType != null) {
2157 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2158 if (list.Count > 0) {
2159 if (members == null)
2160 members = new ArrayList ();
2162 members.AddRange (list);
2168 Timer.StopTimer (TimerType.TcFindMembers);
2170 if (members == null)
2171 return MemberList.Empty;
2173 return new MemberList (members);
2176 public override MemberCache MemberCache {
2178 return member_cache;
2182 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2183 MemberFilter filter, object criteria)
2185 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2188 return ds.FindMembers (mt, bf, filter, criteria);
2190 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2194 // FindMethods will look for methods not only in the type `t', but in
2195 // any interfaces implemented by the type.
2197 public static MethodInfo [] FindMethods (Type t, BindingFlags bf,
2198 MemberFilter filter, object criteria)
2204 /// Emits the values for the constants
2206 public void EmitConstants ()
2208 if (constants != null)
2209 foreach (Const con in constants)
2214 void CheckMemberUsage (MemberCoreArrayList al, string member_type)
2219 foreach (MemberCore mc in al) {
2220 if ((mc.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2224 Report.Warning (169, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2229 public virtual void VerifyMembers ()
2232 // Check for internal or private fields that were never assigned
2234 if (RootContext.WarningLevel >= 3) {
2235 CheckMemberUsage (properties, "property");
2236 CheckMemberUsage (methods, "method");
2237 CheckMemberUsage (constants, "constant");
2239 if (fields != null){
2240 foreach (FieldMember f in fields) {
2241 if ((f.ModFlags & Modifiers.Accessibility) != Modifiers.PRIVATE)
2245 if ((f.caching_flags & Flags.IsAssigned) == 0)
2246 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2249 const int error_code = 414;
2251 const int error_code = 169;
2253 Report.Warning (error_code, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2254 f.GetSignatureForError ());
2260 // Only report 649 on level 4
2262 if (RootContext.WarningLevel < 4)
2265 if ((f.caching_flags & Flags.IsAssigned) != 0)
2268 Report.Warning (649, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2269 f.GetSignatureForError (), f.Type.Type.IsValueType ? Activator.CreateInstance (f.Type.Type).ToString() : "null");
2276 /// Emits the code, this step is performed after all
2277 /// the types, enumerations, constructors
2279 public void EmitType ()
2281 if (OptAttributes != null)
2282 OptAttributes.Emit (ec, this);
2285 // Structs with no fields need to have at least one byte.
2286 // The right thing would be to set the PackingSize in a DefineType
2287 // but there are no functions that allow interfaces *and* the size to
2291 if (Kind == Kind.Struct && first_nonstatic_field == null){
2292 FieldBuilder fb = TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
2293 FieldAttributes.Private);
2295 if (HasExplicitLayout){
2296 object [] ctor_args = new object [1];
2299 CustomAttributeBuilder cba = new CustomAttributeBuilder (
2300 TypeManager.field_offset_attribute_ctor, ctor_args);
2301 fb.SetCustomAttribute (cba);
2307 if (instance_constructors != null) {
2308 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired (this)) {
2309 bool has_compliant_args = false;
2311 foreach (Constructor c in instance_constructors) {
2314 if (has_compliant_args)
2317 has_compliant_args = c.HasCompliantArgs;
2319 if (!has_compliant_args)
2320 Report.Error (3015, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2322 foreach (Constructor c in instance_constructors)
2327 // Can not continue if constants are broken
2329 if (Report.Errors > 0)
2332 if (default_static_constructor != null)
2333 default_static_constructor.Emit ();
2335 if (methods != null)
2336 foreach (Method m in methods)
2339 if (operators != null)
2340 foreach (Operator o in operators)
2343 if (properties != null)
2344 foreach (Property p in properties)
2347 if (indexers != null){
2352 foreach (FieldMember f in fields)
2355 if (events != null){
2356 foreach (Event e in Events)
2360 if (delegates != null) {
2361 foreach (Delegate d in Delegates) {
2366 if (enums != null) {
2367 foreach (Enum e in enums) {
2372 if (parts != null) {
2373 foreach (ClassPart part in parts)
2377 if ((Pending != null) && !(this is ClassPart))
2378 if (Pending.VerifyPendingMethods ())
2381 if (iterators != null)
2382 foreach (Iterator iterator in iterators)
2383 iterator.EmitType ();
2385 // if (types != null)
2386 // foreach (TypeContainer tc in types)
2390 public override void CloseType ()
2392 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2396 caching_flags |= Flags.CloseTypeCreated;
2397 TypeBuilder.CreateType ();
2398 } catch (TypeLoadException){
2400 // This is fine, the code still created the type
2402 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2403 // Console.WriteLine (e.Message);
2405 Console.WriteLine ("In type: " + Name);
2410 foreach (Enum en in Enums)
2414 foreach (TypeContainer tc in Types)
2415 if (tc.Kind == Kind.Struct)
2418 foreach (TypeContainer tc in Types)
2419 if (tc.Kind != Kind.Struct)
2423 if (Delegates != null)
2424 foreach (Delegate d in Delegates)
2427 if (Iterators != null)
2428 foreach (Iterator i in Iterators)
2436 initialized_fields = null;
2437 initialized_static_fields = null;
2446 default_constructor = null;
2447 default_static_constructor = null;
2449 OptAttributes = null;
2452 member_cache = null;
2456 // Performs the validation on a Method's modifiers (properties have
2457 // the same properties).
2459 public bool MethodModifiersValid (MemberCore mc)
2461 const int vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2462 const int va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2463 const int nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2465 int flags = mc.ModFlags;
2468 // At most one of static, virtual or override
2470 if ((flags & Modifiers.STATIC) != 0){
2471 if ((flags & vao) != 0){
2472 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2473 mc.GetSignatureForError ());
2478 if (Kind == Kind.Struct){
2479 if ((flags & va) != 0){
2480 Modifiers.Error_InvalidModifier (mc.Location, "virtual or abstract");
2485 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2486 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2487 mc.GetSignatureForError ());
2492 // If the declaration includes the abstract modifier, then the
2493 // declaration does not include static, virtual or extern
2495 if ((flags & Modifiers.ABSTRACT) != 0){
2496 if ((flags & Modifiers.EXTERN) != 0){
2498 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2502 if ((flags & Modifiers.SEALED) != 0) {
2503 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2507 if ((flags & Modifiers.VIRTUAL) != 0){
2508 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2512 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2513 Report.Error (513, mc.Location, "`{0}' is abstract but it is contained in nonabstract class", mc.GetSignatureForError ());
2518 if ((flags & Modifiers.PRIVATE) != 0){
2519 if ((flags & vao) != 0){
2520 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2525 if ((flags & Modifiers.SEALED) != 0){
2526 if ((flags & Modifiers.OVERRIDE) == 0){
2527 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2535 public bool UserDefinedStaticConstructor {
2537 return default_static_constructor != null;
2541 public Constructor DefaultStaticConstructor {
2542 get { return default_static_constructor; }
2545 protected override bool VerifyClsCompliance (DeclSpace ds)
2547 if (!base.VerifyClsCompliance (ds))
2552 Type base_type = TypeBuilder.BaseType;
2553 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2554 Report.Error (3009, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2557 if (!Parent.IsClsComplianceRequired (ds)) {
2558 Report.Error (3018, Location, "`{0}' cannot be marked as CLS-compliant because it is a member of non CLS-compliant type `{1}'",
2559 GetSignatureForError (), Parent.GetSignatureForError ());
2566 /// Checks whether container name is CLS Compliant
2568 void VerifyClsName ()
2570 Hashtable base_members = base_cache == null ?
2572 base_cache.GetPublicMembers ();
2573 Hashtable this_members = new Hashtable ();
2575 foreach (DictionaryEntry entry in defined_names) {
2576 MemberCore mc = (MemberCore)entry.Value;
2577 if (!mc.IsClsComplianceRequired (mc.Parent))
2580 string name = (string) entry.Key;
2581 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2583 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2584 object found = base_members [lcase];
2585 if (found == null) {
2586 found = this_members [lcase];
2587 if (found == null) {
2588 this_members.Add (lcase, mc);
2593 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2596 if (found is MemberInfo) {
2597 if (basename == ((MemberInfo) found).Name)
2599 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2601 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2603 Report.Warning (3005, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2609 /// Performs checks for an explicit interface implementation. First it
2610 /// checks whether the `interface_type' is a base inteface implementation.
2611 /// Then it checks whether `name' exists in the interface type.
2613 public virtual bool VerifyImplements (MemberBase mb)
2615 if (ifaces != null) {
2616 foreach (Type t in ifaces){
2617 if (t == mb.InterfaceType)
2622 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2623 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2631 string IMemberContainer.Name {
2637 Type IMemberContainer.Type {
2643 MemberCache IMemberContainer.MemberCache {
2645 return member_cache;
2649 bool IMemberContainer.IsInterface {
2651 return Kind == Kind.Interface;
2655 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2657 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2659 if (GenericType != null)
2660 return TypeManager.FindMembers (GenericType, mt, new_bf,
2663 return FindMembers (mt, new_bf, null, null);
2667 // Generates xml doc comments (if any), and if required,
2668 // handle warning report.
2670 internal override void GenerateDocComment (DeclSpace ds)
2672 DocUtil.GenerateTypeDocComment (this, ds);
2675 public override string DocCommentHeader {
2676 get { return "T:"; }
2679 public virtual MemberCache BaseCache {
2681 if (base_cache != null)
2683 if (TypeBuilder.BaseType != null)
2684 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2685 if (TypeBuilder.IsInterface)
2686 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2693 public class PartialContainer : TypeContainer {
2695 public readonly Namespace Namespace;
2696 public readonly int OriginalModFlags;
2697 public readonly int AllowedModifiers;
2698 public readonly TypeAttributes DefaultTypeAttributes;
2700 static PartialContainer Create (NamespaceEntry ns, TypeContainer parent,
2701 MemberName member_name, int mod_flags, Kind kind)
2704 if (!CheckModFlags (0, mod_flags, member_name))
2707 PartialContainer pc = RootContext.Tree.GetDecl (member_name) as PartialContainer;
2709 if (pc.Kind != kind) {
2711 261, member_name.Location,
2712 "Partial declarations of `{0}' must be all classes, " +
2713 "all structs or all interfaces",
2714 member_name.GetTypeName ());
2718 if (!CheckModFlags (pc.OriginalModFlags, mod_flags, member_name))
2720 pc.ModFlags |= (mod_flags & pc.AllowedModifiers);
2723 if (pc.CountTypeParameters != member_name.CountTypeArguments) {
2725 264, member_name.Location,
2726 "Partial declarations of `{0}' must have the " +
2727 "same type parameter names in the same order",
2728 member_name.GetTypeName ());
2732 string[] pc_names = pc.MemberName.TypeArguments.GetDeclarations ();
2733 string[] names = member_name.TypeArguments.GetDeclarations ();
2735 for (int i = 0; i < pc.CountTypeParameters; i++) {
2736 if (pc_names [i] == names [i])
2740 264, member_name.Location,
2741 "Partial declarations of `{0}' must have the " +
2742 "same type parameter names in the same order",
2743 member_name.GetTypeName ());
2751 if (parent is ClassPart)
2752 parent = ((ClassPart) parent).PartialContainer;
2754 pc = new PartialContainer (ns.NS, parent, member_name, mod_flags, kind);
2756 if (kind == Kind.Interface) {
2757 if (!parent.AddInterface (pc))
2759 } else if (kind == Kind.Class || kind == Kind.Struct) {
2760 if (!parent.AddClassOrStruct (pc))
2763 throw new InvalidOperationException ();
2765 RootContext.Tree.RecordDecl (ns.NS, member_name, pc);
2766 // This is needed to define our type parameters; we define the constraints later.
2767 pc.SetParameterInfo (null);
2771 static bool CheckModFlags (int flags_org, int flags, MemberName member_name)
2773 // Check (abstract|static|sealed) sanity.
2774 int tmp = (flags_org | flags) & (Modifiers.ABSTRACT | Modifiers.SEALED | Modifiers.STATIC);
2775 if ((tmp & Modifiers.ABSTRACT) != 0) {
2776 if ((tmp & (Modifiers.STATIC | Modifiers.SEALED)) != 0) {
2778 418, member_name.Location,
2779 "`{0}': an abstract class cannot be sealed or static", member_name.ToString ());
2782 } else if (tmp == (Modifiers.SEALED | Modifiers.STATIC)) {
2783 Report.Error (441, member_name.Location, "`{0}': a class cannot be both static and sealed", member_name.ToString ());
2791 if (0 != ((flags_org ^ flags) & (0xFFFFFFFF ^ (Modifiers.SEALED | Modifiers.ABSTRACT)))) {
2793 262, member_name.Location, "Partial declarations of `{0}' " +
2794 "have conflicting accessibility modifiers",
2795 member_name.GetName ());
2801 public static ClassPart CreatePart (NamespaceEntry ns, TypeContainer parent,
2802 MemberName name, int mod, Attributes attrs,
2803 Kind kind, Location loc)
2805 PartialContainer pc = Create (ns, parent, name, mod, kind);
2807 // An error occured; create a dummy container, but don't
2809 pc = new PartialContainer (ns.NS, parent, name, mod, kind);
2812 ClassPart part = new ClassPart (ns, pc, parent, mod, attrs, kind);
2817 protected PartialContainer (Namespace ns, TypeContainer parent,
2818 MemberName name, int mod, Kind kind)
2819 : base (null, parent, name, null, kind)
2821 this.Namespace = ns;
2825 AllowedModifiers = Class.AllowedModifiers;
2826 DefaultTypeAttributes = Class.DefaultTypeAttributes;
2830 AllowedModifiers = Struct.AllowedModifiers;
2831 DefaultTypeAttributes = Struct.DefaultTypeAttributes;
2834 case Kind.Interface:
2835 AllowedModifiers = Interface.AllowedModifiers;
2836 DefaultTypeAttributes = Interface.DefaultTypeAttributes;
2840 throw new InvalidOperationException ();
2844 if (parent.Parent == null)
2845 accmods = Modifiers.INTERNAL;
2847 accmods = Modifiers.PRIVATE;
2849 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
2850 this.OriginalModFlags = mod;
2853 public override PendingImplementation GetPendingImplementations ()
2855 return PendingImplementation.GetPendingImplementations (this);
2858 public override bool MarkForDuplicationCheck ()
2863 protected override TypeAttributes TypeAttr {
2865 return base.TypeAttr | DefaultTypeAttributes;
2870 public class ClassPart : TypeContainer, IMemberContainer {
2871 public readonly PartialContainer PartialContainer;
2872 public readonly bool IsPartial;
2874 Constraints[] constraints;
2876 public ClassPart (NamespaceEntry ns, PartialContainer pc, TypeContainer parent,
2877 int mod, Attributes attrs, Kind kind)
2878 : base (ns, parent, pc.MemberName, attrs, kind)
2880 this.PartialContainer = pc;
2881 this.IsPartial = true;
2884 if (parent == null || parent == RootContext.Tree.Types)
2885 accmods = Modifiers.INTERNAL;
2887 accmods = Modifiers.PRIVATE;
2889 this.ModFlags = Modifiers.Check (pc.AllowedModifiers, mod, accmods, pc.MemberName.Location);
2892 constraints = new Constraints [pc.CountCurrentTypeParameters];
2895 public override PendingImplementation GetPendingImplementations ()
2897 return PartialContainer.Pending;
2900 public override bool VerifyImplements (MemberBase mb)
2902 return PartialContainer.VerifyImplements (mb);
2905 public override void SetParameterInfo (ArrayList constraints_list)
2907 if (constraints_list == null)
2910 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
2911 for (int i = 0; i < constraints.Length; i++) {
2912 foreach (Constraints constraint in constraints_list) {
2913 if (constraint.TypeParameter == current_params [i].Name) {
2914 constraints [i] = constraint;
2921 public bool DefineTypeParameters ()
2923 TypeParameter[] current_params = PartialContainer.CurrentTypeParameters;
2925 for (int i = 0; i < current_params.Length; i++) {
2926 Constraints new_constraints = constraints [i];
2927 if (new_constraints == null)
2930 if (!current_params [i].UpdateConstraints (ec, new_constraints)) {
2931 Report.Error (265, Location, "Partial declarations of `{0}' have " +
2932 "inconsistent constraints for type parameter `{1}'.",
2933 MemberName.GetTypeName (), current_params [i].Name);
2938 for (int i = 0; i < current_params.Length; i++) {
2939 if (!current_params [i].Resolve (this))
2943 for (int i = 0; i < current_params.Length; i++)
2944 current_params [i].DefineConstraints ();
2946 foreach (TypeParameter type_param in PartialContainer.TypeParameters) {
2947 if (!type_param.DefineType (ec))
2954 public override void RegisterFieldForInitialization (FieldMember field)
2956 PartialContainer.RegisterFieldForInitialization (field);
2959 public override bool EmitFieldInitializers (EmitContext ec)
2961 return PartialContainer.EmitFieldInitializers (ec);
2964 public override Type FindNestedType (string name)
2966 return PartialContainer.FindNestedType (name);
2969 public override MemberCache BaseCache {
2971 return PartialContainer.BaseCache;
2975 public override TypeBuilder DefineType ()
2977 throw new InternalErrorException ("Should not get here");
2982 public abstract class ClassOrStruct : TypeContainer {
2983 bool has_explicit_layout = false;
2984 ListDictionary declarative_security;
2986 public ClassOrStruct (NamespaceEntry ns, TypeContainer parent,
2987 MemberName name, Attributes attrs, Kind kind)
2988 : base (ns, parent, name, attrs, kind)
2992 public override PendingImplementation GetPendingImplementations ()
2994 return PendingImplementation.GetPendingImplementations (this);
2997 public override bool HasExplicitLayout {
2999 return has_explicit_layout;
3003 public override void VerifyMembers ()
3005 base.VerifyMembers ();
3007 if ((events != null) && (RootContext.WarningLevel >= 3)) {
3008 foreach (Event e in events){
3009 if ((e.caching_flags & Flags.IsAssigned) == 0)
3010 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
3015 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
3017 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
3018 if (declarative_security == null)
3019 declarative_security = new ListDictionary ();
3021 a.ExtractSecurityPermissionSet (declarative_security);
3025 if (a.Type == TypeManager.struct_layout_attribute_type && a.GetLayoutKindValue () == LayoutKind.Explicit)
3026 has_explicit_layout = true;
3028 base.ApplyAttributeBuilder (a, cb);
3031 public override void Emit()
3035 if (declarative_security != null) {
3036 foreach (DictionaryEntry de in declarative_security) {
3037 TypeBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
3044 /// Class handles static classes declaration
3046 public sealed class StaticClass: Class {
3047 public StaticClass (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
3049 : base (ns, parent, name, mod, attrs)
3051 if (RootContext.Version == LanguageVersion.ISO_1) {
3052 Report.FeatureIsNotStandardized (Location, "static classes");
3056 protected override int AllowedModifiersProp {
3058 return Modifiers.NEW | Modifiers.PUBLIC | Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE |
3059 Modifiers.STATIC | Modifiers.UNSAFE;
3063 protected override void DefineContainerMembers (MemberCoreArrayList list)
3068 foreach (MemberCore m in list) {
3069 if (m is Operator) {
3070 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
3074 if (m is Destructor) {
3075 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
3079 if ((m.ModFlags & Modifiers.PROTECTED) != 0) {
3080 Report.Error (1057, m.Location, "`{0}': Static classes cannot contain protected members", m.GetSignatureForError ());
3085 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
3089 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
3092 if (m is Constructor) {
3093 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
3097 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
3100 base.DefineContainerMembers (list);
3103 public override TypeBuilder DefineType()
3105 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
3106 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
3110 TypeBuilder tb = base.DefineType ();
3114 if (ptype != TypeManager.object_type) {
3115 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object", GetSignatureForError (), TypeManager.CSharpName (ptype));
3119 if (ifaces != null) {
3120 foreach (Type t in ifaces)
3121 Report.SymbolRelatedToPreviousError (t);
3122 Report.Error (714, Location, "`{0}': static classes cannot implement interfaces", GetSignatureForError ());
3127 protected override TypeAttributes TypeAttr {
3129 return base.TypeAttr | TypeAttributes.Abstract | TypeAttributes.Sealed;
3134 public class Class : ClassOrStruct {
3135 // TODO: remove this and use only AllowedModifiersProp to fix partial classes bugs
3136 public const int AllowedModifiers =
3139 Modifiers.PROTECTED |
3140 Modifiers.INTERNAL |
3142 Modifiers.ABSTRACT |
3146 public Class (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
3148 : base (ns, parent, name, attrs, Kind.Class)
3150 this.ModFlags = mod;
3153 virtual protected int AllowedModifiersProp {
3155 return AllowedModifiers;
3159 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
3161 if (a.Type == TypeManager.attribute_usage_type) {
3162 if (ptype != TypeManager.attribute_type &&
3163 !ptype.IsSubclassOf (TypeManager.attribute_type) &&
3164 TypeBuilder.FullName != "System.Attribute") {
3165 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
3169 if (a.Type == TypeManager.conditional_attribute_type &&
3170 !(ptype == TypeManager.attribute_type || ptype.IsSubclassOf (TypeManager.attribute_type))) {
3171 Report.Error (1689, a.Location, "Attribute 'System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
3175 if (AttributeTester.IsAttributeExcluded (a.Type))
3178 base.ApplyAttributeBuilder (a, cb);
3181 public const TypeAttributes DefaultTypeAttributes =
3182 TypeAttributes.AutoLayout | TypeAttributes.Class;
3184 public override TypeBuilder DefineType()
3186 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
3187 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
3191 int accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3192 ModFlags = Modifiers.Check (AllowedModifiersProp, ModFlags, accmods, Location);
3194 return base.DefineType ();
3197 /// Search for at least one defined condition in ConditionalAttribute of attribute class
3198 /// Valid only for attribute classes.
3199 public bool IsExcluded ()
3201 if ((caching_flags & Flags.Excluded_Undetected) == 0)
3202 return (caching_flags & Flags.Excluded) != 0;
3204 caching_flags &= ~Flags.Excluded_Undetected;
3206 if (OptAttributes == null)
3209 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
3214 foreach (Attribute a in attrs) {
3215 string condition = a.GetConditionalAttributeValue (Parent.EmitContext);
3216 if (RootContext.AllDefines.Contains (condition))
3220 caching_flags |= Flags.Excluded;
3225 // FIXME: How do we deal with the user specifying a different
3228 protected override TypeAttributes TypeAttr {
3230 return base.TypeAttr | DefaultTypeAttributes;
3235 public class Struct : ClassOrStruct {
3237 // Modifiers allowed in a struct declaration
3239 public const int AllowedModifiers =
3242 Modifiers.PROTECTED |
3243 Modifiers.INTERNAL |
3247 public Struct (NamespaceEntry ns, TypeContainer parent, MemberName name,
3248 int mod, Attributes attrs)
3249 : base (ns, parent, name, attrs, Kind.Struct)
3253 if (parent.Parent == null)
3254 accmods = Modifiers.INTERNAL;
3256 accmods = Modifiers.PRIVATE;
3258 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, Location);
3260 this.ModFlags |= Modifiers.SEALED;
3263 public const TypeAttributes DefaultTypeAttributes =
3264 TypeAttributes.SequentialLayout |
3265 TypeAttributes.Sealed |
3266 TypeAttributes.BeforeFieldInit;
3269 // FIXME: Allow the user to specify a different set of attributes
3270 // in some cases (Sealed for example is mandatory for a class,
3271 // but what SequentialLayout can be changed
3273 protected override TypeAttributes TypeAttr {
3275 return base.TypeAttr | DefaultTypeAttributes;
3283 public class Interface : TypeContainer, IMemberContainer {
3286 /// Modifiers allowed in a class declaration
3288 public const int AllowedModifiers =
3291 Modifiers.PROTECTED |
3292 Modifiers.INTERNAL |
3296 public Interface (NamespaceEntry ns, TypeContainer parent, MemberName name, int mod,
3298 : base (ns, parent, name, attrs, Kind.Interface)
3302 if (parent.Parent == null)
3303 accmods = Modifiers.INTERNAL;
3305 accmods = Modifiers.PRIVATE;
3307 this.ModFlags = Modifiers.Check (AllowedModifiers, mod, accmods, name.Location);
3310 public override PendingImplementation GetPendingImplementations ()
3315 public const TypeAttributes DefaultTypeAttributes =
3316 TypeAttributes.AutoLayout |
3317 TypeAttributes.Abstract |
3318 TypeAttributes.Interface;
3320 protected override TypeAttributes TypeAttr {
3322 return base.TypeAttr | DefaultTypeAttributes;
3326 protected override bool VerifyClsCompliance (DeclSpace ds)
3328 if (!base.VerifyClsCompliance (ds))
3331 if (ifaces != null) {
3332 foreach (Type t in ifaces) {
3333 if (AttributeTester.IsClsCompliant (t))
3336 Report.SymbolRelatedToPreviousError (t);
3337 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3338 GetSignatureForError (), TypeManager.CSharpName (t));
3346 public abstract class MethodCore : MemberBase {
3347 public readonly Parameters Parameters;
3348 protected ToplevelBlock block;
3351 // Parameters, cached for semantic analysis.
3353 protected InternalParameters parameter_info;
3354 protected Type [] parameter_types;
3356 // Whether this is an operator method.
3357 public Operator IsOperator;
3360 // The method we're overriding if this is an override method.
3362 protected MethodInfo base_method = null;
3364 static string[] attribute_targets = new string [] { "method", "return" };
3366 public MethodCore (TypeContainer parent, GenericMethod generic,
3367 Expression type, int mod, int allowed_mod, bool is_iface,
3368 MemberName name, Attributes attrs, Parameters parameters)
3369 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3372 Parameters = parameters;
3373 IsInterface = is_iface;
3377 // Returns the System.Type array for the parameters of this method
3379 public Type [] ParameterTypes {
3381 return parameter_types;
3385 public InternalParameters ParameterInfo
3388 return parameter_info;
3392 public override EmitContext EmitContext {
3393 get { return ds.EmitContext; }
3396 public ToplevelBlock Block {
3406 public void SetYields ()
3408 ModFlags |= Modifiers.METHOD_YIELDS;
3411 protected override bool CheckBase ()
3413 if (!base.CheckBase ())
3416 // Check whether arguments were correct.
3417 if (!DoDefineParameters ())
3420 if ((caching_flags & Flags.TestMethodDuplication) != 0 && !CheckForDuplications ())
3426 // Is null for System.Object while compiling corlib and base interfaces
3427 if (Parent.BaseCache == null) {
3428 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3429 Report.Warning (109, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3434 Type base_ret_type = null;
3435 base_method = FindOutBaseMethod (Parent, ref base_ret_type);
3437 // method is override
3438 if (base_method != null) {
3440 if (!CheckMethodAgainstBase ())
3443 if ((ModFlags & Modifiers.NEW) == 0) {
3444 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_ret_type))) {
3445 Report.SymbolRelatedToPreviousError (base_method);
3446 if (this is PropertyBase) {
3447 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3448 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
3451 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3452 GetSignatureForError (), TypeManager.CSharpName (base_ret_type), TypeManager.CSharpSignature (base_method));
3457 if (base_method.IsAbstract && !IsInterface) {
3458 Report.SymbolRelatedToPreviousError (base_method);
3459 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3460 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3465 if (base_method.IsSpecialName && !(this is PropertyBase)) {
3466 Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
3470 if (RootContext.WarningLevel > 2) {
3471 if (Name == "Equals" && parameter_types.Length == 1 && parameter_types [0] == TypeManager.object_type)
3472 Parent.Methods.HasEquals = true;
3473 else if (Name == "GetHashCode" && parameter_types.Length == 0)
3474 Parent.Methods.HasGetHashCode = true;
3477 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3478 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3480 EmitContext ec = new EmitContext (this.Parent, this.Parent, Location, null, null, ModFlags, false);
3481 if (OptAttributes == null || !OptAttributes.Contains (TypeManager.obsolete_attribute_type, ec)) {
3482 Report.SymbolRelatedToPreviousError (base_method);
3483 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3484 GetSignatureForError (), TypeManager.CSharpSignature (base_method) );
3491 MemberInfo conflict_symbol = Parent.FindBaseMemberWithSameName (Name, !(this is Property));
3492 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3493 if (conflict_symbol != null) {
3494 Report.SymbolRelatedToPreviousError (conflict_symbol);
3495 if (this is PropertyBase)
3496 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3498 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3500 Report.Error (115, Location, "`{0}': no suitable method found to override", GetSignatureForError ());
3504 if (conflict_symbol == null) {
3505 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
3506 Report.Warning (109, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3511 if ((ModFlags & Modifiers.NEW) == 0) {
3512 if (this is Method && conflict_symbol is MethodBase)
3515 Report.SymbolRelatedToPreviousError (conflict_symbol);
3516 Report.Warning (108, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3517 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3524 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3525 // that have been defined.
3527 // `name' is the user visible name for reporting errors (this is used to
3528 // provide the right name regarding method names and properties)
3530 bool CheckMethodAgainstBase ()
3534 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3535 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3536 Report.Error (506, Location,
3537 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3538 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3542 // Now we check that the overriden method is not final
3544 if (base_method.IsFinal) {
3545 Report.SymbolRelatedToPreviousError (base_method);
3546 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3547 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3551 // Check that the permissions are not being changed
3553 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3554 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3556 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3557 Error_CannotChangeAccessModifiers (base_method, base_classp, null);
3562 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0 && Name != "Finalize") {
3563 ModFlags |= Modifiers.NEW;
3564 Report.SymbolRelatedToPreviousError (base_method);
3565 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3566 if (RootContext.WarningLevel >= 2)
3567 Report.Warning (114, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword", GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3569 Report.Warning (108, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3570 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3577 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3579 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3581 // when overriding protected internal, the method can be declared
3582 // protected internal only within the same assembly
3585 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3586 if (Parent.TypeBuilder.Assembly != base_method.DeclaringType.Assembly){
3588 // assemblies differ - report an error
3592 } else if (thisp != base_classp) {
3594 // same assembly, but other attributes differ - report an error
3599 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3601 // if it's not "protected internal", it must be "protected"
3605 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3607 // protected within the same assembly - an error
3610 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3611 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3613 // protected ok, but other attributes differ - report an error
3619 return (thisp == base_classp);
3623 public bool CheckAbstractAndExtern (bool has_block)
3625 if (Parent.Kind == Kind.Interface)
3629 if ((ModFlags & Modifiers.EXTERN) != 0) {
3630 Report.Error (179, Location, "`{0}' cannot declare a body because it is marked extern",
3631 GetSignatureForError ());
3635 if ((ModFlags & Modifiers.ABSTRACT) != 0) {
3636 Report.Error (500, Location, "`{0}' cannot declare a body because it is marked abstract",
3637 GetSignatureForError ());
3641 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
3642 Report.Error (501, Location, "`{0}' must declare a body because it is not marked abstract or extern",
3643 GetSignatureForError ());
3651 protected void Error_CannotChangeAccessModifiers (MemberInfo base_method, MethodAttributes ma, string suffix)
3653 Report.SymbolRelatedToPreviousError (base_method);
3654 string base_name = TypeManager.GetFullNameSignature (base_method);
3655 string this_name = GetSignatureForError ();
3656 if (suffix != null) {
3657 base_name += suffix;
3658 this_name += suffix;
3661 Report.Error (507, Location, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3662 this_name, Modifiers.GetDescription (ma), base_name);
3665 protected static string Error722 {
3667 return "`{0}': static types cannot be used as return types";
3672 /// For custom member duplication search in a container
3674 protected abstract bool CheckForDuplications ();
3677 /// Gets base method and its return type
3679 protected abstract MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type);
3681 protected virtual bool DoDefineParameters ()
3683 EmitContext ec = ds.EmitContext;
3685 throw new InternalErrorException ("DoDefineParameters invoked too early");
3687 bool old_unsafe = ec.InUnsafe;
3688 ec.InUnsafe = InUnsafe;
3689 ec.ResolvingGenericMethod = GenericMethod != null;
3690 // Check if arguments were correct
3691 parameter_types = Parameters.GetParameterInfo (ec);
3692 ec.ResolvingGenericMethod = false;
3693 ec.InUnsafe = old_unsafe;
3695 if ((parameter_types == null) ||
3696 !CheckParameters (ds, parameter_types))
3699 TypeParameter[] tparam = ds.IsGeneric ? ds.TypeParameters : null;
3700 parameter_info = new InternalParameters (parameter_types, Parameters, tparam);
3702 Parameter array_param = Parameters.ArrayParameter;
3703 if ((array_param != null) &&
3704 (!array_param.ParameterType.IsArray ||
3705 (array_param.ParameterType.GetArrayRank () != 1))) {
3706 Report.Error (225, Location, "The params parameter must be a single dimensional array");
3713 void error_425 (Type old, Type t, string name)
3715 Report.Error (425, Location,
3716 "The constraints of type parameter `{0}' " +
3717 "of method `{1}' must match the constraints for " +
3718 "type parameter `{2}' of method `{3}'",
3719 TypeManager.CSharpName (old), Name,
3720 TypeManager.CSharpName (t), name);
3723 protected override bool CheckGenericOverride (MethodInfo method, string name)
3725 ParameterData pd = TypeManager.GetParameterData (method);
3727 for (int i = 0; i < ParameterTypes.Length; i++) {
3728 GenericConstraints ogc = pd.GenericConstraints (i);
3729 GenericConstraints gc = ParameterInfo.GenericConstraints (i);
3731 if ((gc == null) && (ogc == null))
3734 Type ot = pd.ParameterType (i);
3735 Type t = ParameterTypes [i];
3737 if (!((gc != null) && (ogc != null))) {
3738 error_425 (ot, t, name);
3742 if ((gc.Attributes != ogc.Attributes) ||
3743 (gc.HasClassConstraint != ogc.HasClassConstraint)) {
3744 error_425 (ot, t, name);
3748 if (ogc.HasClassConstraint &&
3749 !ogc.ClassConstraint.Equals (gc.ClassConstraint)) {
3750 error_425 (ot, t, name);
3754 Type[] oct = ogc.InterfaceConstraints;
3755 Type[] ct = gc.InterfaceConstraints;
3757 if (oct.Length != ct.Length) {
3758 error_425 (ot, t, name);
3762 for (int j = 0; j < oct.Length; j++)
3763 if (!oct [j].Equals (ct [j])) {
3764 error_425 (ot, t, name);
3772 public override string[] ValidAttributeTargets {
3774 return attribute_targets;
3778 protected override bool VerifyClsCompliance (DeclSpace ds)
3780 if (!base.VerifyClsCompliance (ds)) {
3781 if ((ModFlags & Modifiers.ABSTRACT) != 0 && IsExposedFromAssembly (ds) && ds.IsClsComplianceRequired (ds)) {
3782 Report.Error (3011, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3787 if (Parameters.HasArglist) {
3788 Report.Error (3000, Location, "Methods with variable arguments are not CLS-compliant");
3791 if (!AttributeTester.IsClsCompliant (MemberType)) {
3792 if (this is PropertyBase)
3793 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant",
3794 GetSignatureForError ());
3796 Report.Error (3002, Location, "Return type of `{0}' is not CLS-compliant",
3797 GetSignatureForError ());
3800 AttributeTester.AreParametersCompliant (Parameters.FixedParameters, Location);
3805 bool MayUnify (MethodCore first, MethodCore second)
3807 int a_type_params = 0;
3808 if (first.GenericMethod != null)
3809 a_type_params = first.GenericMethod.CountTypeParameters;
3811 int b_type_params = 0;
3812 if (second.GenericMethod != null)
3813 b_type_params = second.GenericMethod.CountTypeParameters;
3815 if (a_type_params != b_type_params)
3818 Type[] class_infered, method_infered;
3819 if (Parent.CountTypeParameters > 0)
3820 class_infered = new Type [Parent.CountTypeParameters];
3822 class_infered = null;
3824 if (a_type_params > 0)
3825 method_infered = new Type [a_type_params];
3827 method_infered = null;
3829 return TypeManager.MayBecomeEqualGenericInstances (
3830 first.ParameterTypes, second.ParameterTypes, class_infered, method_infered);
3833 protected bool IsDuplicateImplementation (MethodCore method)
3835 if (method == this || !(method.MemberName.Equals (MemberName)))
3838 Type[] param_types = method.ParameterTypes;
3839 if (param_types == null && ParameterTypes == null)
3841 if (param_types == null || ParameterTypes == null)
3844 if (param_types.Length != ParameterTypes.Length)
3848 bool may_unify = MayUnify (this, method);
3850 for (int i = 0; i < param_types.Length; i++) {
3851 if (param_types [i] != ParameterTypes [i])
3855 if (IsExplicitImpl && (method.InterfaceType != InterfaceType))
3856 equal = may_unify = false;
3858 // TODO: make operator compatible with MethodCore to avoid this
3859 if (this is Operator && method is Operator) {
3860 if (MemberType != method.MemberType)
3861 equal = may_unify = false;
3866 // Try to report 663: method only differs on out/ref
3868 ParameterData info = ParameterInfo;
3869 ParameterData other_info = method.ParameterInfo;
3870 for (int i = 0; i < info.Count; i++){
3871 if (info.ParameterModifier (i) != other_info.ParameterModifier (i)){
3872 Report.SymbolRelatedToPreviousError (method);
3873 Report.Error (663, Location, "`{0}': Methods cannot differ only on their use of ref and out on a parameters",
3874 GetSignatureForError ());
3879 Report.SymbolRelatedToPreviousError (method);
3880 if (this is Operator && method is Operator)
3881 Report.Error (557, Location, "Duplicate user-defined conversion in type `{0}'", Parent.Name);
3883 Report.Error (111, Location, TypeContainer.Error111, GetSignatureForError ());
3886 } else if (may_unify) {
3887 Report.Error (408, Location,
3888 "`{0}' cannot define overload members that " +
3889 "may unify for some type parameter substitutions",
3897 public override bool IsUsed {
3898 get { return IsExplicitImpl || base.IsUsed; }
3902 // Returns a string that represents the signature for this
3903 // member which should be used in XML documentation.
3905 public override string GetDocCommentName (DeclSpace ds)
3907 return DocUtil.GetMethodDocCommentName (this, ds);
3911 // Raised (and passed an XmlElement that contains the comment)
3912 // when GenerateDocComment is writing documentation expectedly.
3914 // FIXME: with a few effort, it could be done with XmlReader,
3915 // that means removal of DOM use.
3917 internal override void OnGenerateDocComment (DeclSpace ds, XmlElement el)
3919 DocUtil.OnMethodGenerateDocComment (this, ds, el);
3923 // Represents header string for documentation comment.
3925 public override string DocCommentHeader {
3926 get { return "M:"; }
3931 public class SourceMethod : ISourceMethod
3933 TypeContainer container;
3936 protected SourceMethod (TypeContainer container, MethodBase builder,
3937 ISourceFile file, Location start, Location end)
3939 this.container = container;
3940 this.builder = builder;
3942 CodeGen.SymbolWriter.OpenMethod (
3943 file, this, start.Row, start.Column, end.Row, start.Column);
3946 public string Name {
3947 get { return builder.Name; }
3950 public int NamespaceID {
3951 get { return container.NamespaceEntry.SymbolFileID; }
3956 if (builder is MethodBuilder)
3957 return ((MethodBuilder) builder).GetToken ().Token;
3958 else if (builder is ConstructorBuilder)
3959 return ((ConstructorBuilder) builder).GetToken ().Token;
3961 throw new NotSupportedException ();
3965 public void CloseMethod ()
3967 if (CodeGen.SymbolWriter != null)
3968 CodeGen.SymbolWriter.CloseMethod ();
3971 public static SourceMethod Create (TypeContainer parent,
3972 MethodBase builder, Block block)
3974 if (CodeGen.SymbolWriter == null)
3979 Location start_loc = block.StartLocation;
3980 if (start_loc.IsNull)
3983 Location end_loc = block.EndLocation;
3987 ISourceFile file = start_loc.SourceFile;
3991 return new SourceMethod (
3992 parent, builder, file, start_loc, end_loc);
3996 public class Method : MethodCore, IIteratorContainer, IMethodData {
3997 public MethodBuilder MethodBuilder;
3998 public MethodData MethodData;
3999 ReturnParameter return_attributes;
4000 ListDictionary declarative_security;
4003 /// Modifiers allowed in a class declaration
4005 const int AllowedModifiers =
4008 Modifiers.PROTECTED |
4009 Modifiers.INTERNAL |
4014 Modifiers.OVERRIDE |
4015 Modifiers.ABSTRACT |
4017 Modifiers.METHOD_YIELDS |
4020 const int AllowedInterfaceModifiers =
4021 Modifiers.NEW | Modifiers.UNSAFE;
4024 // return_type can be "null" for VOID values.
4026 public Method (TypeContainer parent, GenericMethod generic,
4027 Expression return_type, int mod, bool is_iface,
4028 MemberName name, Parameters parameters, Attributes attrs)
4029 : base (parent, generic, return_type, mod,
4030 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
4031 is_iface, name, attrs, parameters)
4035 public override AttributeTargets AttributeTargets {
4037 return AttributeTargets.Method;
4041 public override string GetSignatureForError()
4043 if (IsOperator != null)
4044 return IsOperator.GetSignatureForError ();
4046 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4049 void DuplicateEntryPoint (MethodInfo b, Location location)
4053 "Program `" + CodeGen.FileName +
4054 "' has more than one entry point defined: `" +
4055 TypeManager.CSharpSignature(b) + "'");
4058 public bool IsEntryPoint (MethodBuilder b, InternalParameters pinfo)
4060 if (b.ReturnType != TypeManager.void_type &&
4061 b.ReturnType != TypeManager.int32_type)
4064 if (pinfo.Count == 0)
4067 if (pinfo.Count > 1)
4070 Type t = pinfo.ParameterType(0);
4072 (t.GetArrayRank() == 1) &&
4073 (TypeManager.GetElementType(t) == TypeManager.string_type) &&
4074 (pinfo.ParameterModifier(0) == Parameter.Modifier.NONE))
4080 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4082 if (a.Target == AttributeTargets.ReturnValue) {
4083 if (return_attributes == null)
4084 return_attributes = new ReturnParameter (MethodBuilder, Location);
4086 return_attributes.ApplyAttributeBuilder (a, cb);
4090 if (a.Type == TypeManager.methodimpl_attr_type &&
4091 (a.GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0) {
4092 MethodBuilder.SetImplementationFlags (MethodImplAttributes.InternalCall | MethodImplAttributes.Runtime);
4095 if (a.Type == TypeManager.dllimport_type) {
4096 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
4097 if ((ModFlags & extern_static) != extern_static) {
4098 Report.Error (601, a.Location, "The DllImport attribute must be specified on a method marked `static' and `extern'");
4104 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4105 if (declarative_security == null)
4106 declarative_security = new ListDictionary ();
4107 a.ExtractSecurityPermissionSet (declarative_security);
4111 if (a.Type == TypeManager.conditional_attribute_type) {
4112 if (IsOperator != null || IsExplicitImpl) {
4113 Report.Error (577, Location, "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
4114 GetSignatureForError ());
4118 if (ReturnType != TypeManager.void_type) {
4119 Report.Error (578, Location, "Conditional not valid on `{0}' because its return type is not void", GetSignatureForError ());
4123 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
4124 Report.Error (243, Location, "Conditional not valid on `{0}' because it is an override method", GetSignatureForError ());
4129 Report.Error (582, Location, "Conditional not valid on interface members");
4133 if (MethodData.implementing != null) {
4134 Report.Error (629, Location, "Conditional member `{0}' cannot implement interface member `{1}'",
4135 GetSignatureForError (), TypeManager.CSharpSignature (MethodData.implementing));
4139 for (int i = 0; i < parameter_info.Count; ++i) {
4140 if ((parameter_info.ParameterModifier (i) & Parameter.Modifier.OUT) != 0) {
4141 Report.Error (685, Location, "Conditional method `{0}' cannot have an out parameter", GetSignatureForError ());
4147 MethodBuilder.SetCustomAttribute (cb);
4150 protected override bool CheckForDuplications ()
4152 ArrayList ar = Parent.Methods;
4154 int arLen = ar.Count;
4156 for (int i = 0; i < arLen; i++) {
4157 Method m = (Method) ar [i];
4158 if (IsDuplicateImplementation (m))
4163 ar = Parent.Properties;
4165 for (int i = 0; i < ar.Count; ++i) {
4166 PropertyBase pb = (PropertyBase) ar [i];
4167 if (pb.AreAccessorsDuplicateImplementation (this))
4172 ar = Parent.Indexers;
4174 for (int i = 0; i < ar.Count; ++i) {
4175 PropertyBase pb = (PropertyBase) ar [i];
4176 if (pb.AreAccessorsDuplicateImplementation (this))
4183 for (int i = 0; i < ar.Count; ++i) {
4184 Event ev = (Event) ar [i];
4185 if (ev.AreAccessorsDuplicateImplementation (this))
4196 public override bool Define ()
4198 if (!DoDefineBase ())
4201 MethodBuilder mb = null;
4202 if (GenericMethod != null) {
4203 string method_name = MemberName.Name;
4206 method_name = TypeManager.GetFullName (InterfaceType) + "." + method_name;
4208 mb = Parent.TypeBuilder.DefineGenericMethod (method_name, flags);
4209 if (!GenericMethod.Define (mb))
4216 if (!CheckAbstractAndExtern (block != null))
4219 if (RootContext.StdLib && (ReturnType == TypeManager.arg_iterator_type || ReturnType == TypeManager.typed_reference_type)) {
4220 Error1599 (Location, ReturnType);
4227 if (IsOperator != null)
4228 flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
4230 MethodData = new MethodData (this, ParameterInfo, ModFlags, flags,
4231 this, mb, GenericMethod, base_method);
4233 if (!MethodData.Define (Parent))
4236 if (ReturnType == TypeManager.void_type && ParameterTypes.Length == 0 &&
4237 Name == "Finalize" && !(this is Destructor)) {
4238 Report.Warning (465, 1, Location, "Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?");
4242 // Setup iterator if we are one
4244 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
4245 Iterator iterator = new Iterator (
4246 this, Parent, GenericMethod, ParameterInfo, ModFlags);
4248 if (!iterator.DefineIterator ())
4252 MethodBuilder = MethodData.MethodBuilder;
4255 // This is used to track the Entry Point,
4257 if (Name == "Main" &&
4258 ((ModFlags & Modifiers.STATIC) != 0) && RootContext.NeedsEntryPoint &&
4259 (RootContext.MainClass == null ||
4260 RootContext.MainClass == Parent.TypeBuilder.FullName)){
4261 if (IsEntryPoint (MethodBuilder, ParameterInfo)) {
4262 IMethodData md = TypeManager.GetMethod (MethodBuilder);
4263 md.SetMemberIsUsed ();
4265 if (RootContext.EntryPoint == null) {
4266 if (Parent.IsGeneric){
4267 Report.Error (-201, Location,
4268 "Entry point can not be defined in a generic class");
4271 RootContext.EntryPoint = MethodBuilder;
4272 RootContext.EntryPointLocation = Location;
4274 DuplicateEntryPoint (RootContext.EntryPoint, RootContext.EntryPointLocation);
4275 DuplicateEntryPoint (MethodBuilder, Location);
4278 if (RootContext.WarningLevel >= 4)
4279 Report.Warning (28, Location, "`{0}' has the wrong signature to be an entry point", TypeManager.CSharpSignature(MethodBuilder));
4283 if (MemberType.IsAbstract && MemberType.IsSealed) {
4284 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4294 public override void Emit ()
4296 MethodData.Emit (Parent, this);
4299 if (declarative_security != null) {
4300 foreach (DictionaryEntry de in declarative_security) {
4301 MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4309 public static void Error1599 (Location loc, Type t)
4311 Report.Error (1599, loc, "Method or delegate cannot return type `{0}'", TypeManager.CSharpName (t));
4314 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4316 MethodInfo mi = (MethodInfo) container.BaseCache.FindMemberToOverride (
4317 container.TypeBuilder, Name, ParameterTypes, GenericMethod, false);
4322 base_ret_type = mi.ReturnType;
4326 public override bool MarkForDuplicationCheck ()
4328 caching_flags |= Flags.TestMethodDuplication;
4332 protected override bool VerifyClsCompliance(DeclSpace ds)
4334 if (!base.VerifyClsCompliance (ds))
4337 if (parameter_types.Length > 0) {
4338 ArrayList al = (ArrayList)ds.MemberCache.Members [Name];
4340 ds.MemberCache.VerifyClsParameterConflict (al, this, MethodBuilder);
4346 #region IMethodData Members
4348 public CallingConventions CallingConventions {
4350 CallingConventions cc = Parameters.GetCallingConvention ();
4351 if (Parameters.HasArglist)
4352 block.HasVarargs = true;
4355 if ((ModFlags & Modifiers.STATIC) == 0)
4356 cc |= CallingConventions.HasThis;
4358 // FIXME: How is `ExplicitThis' used in C#?
4364 public Type ReturnType {
4370 public MemberName MethodName {
4376 public new Location Location {
4378 return base.Location;
4382 protected override bool CheckBase() {
4383 if (!base.CheckBase ())
4386 // TODO: Destructor should derive from MethodCore
4387 if (base_method != null && (ModFlags & Modifiers.OVERRIDE) != 0 && Name == "Finalize" &&
4388 base_method.DeclaringType == TypeManager.object_type && !(this is Destructor)) {
4389 Report.Error (249, Location, "Do not override object.Finalize. Instead, provide a destructor");
4396 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4398 EmitContext ec = new EmitContext (
4399 tc, ds, Location, ig, ReturnType, ModFlags, false);
4401 Iterator iterator = tc as Iterator;
4402 if (iterator != null)
4403 ec.CurrentAnonymousMethod = iterator.Host;
4409 /// Returns true if method has conditional attribute and the conditions is not defined (method is excluded).
4411 public bool IsExcluded (EmitContext ec)
4413 if ((caching_flags & Flags.Excluded_Undetected) == 0)
4414 return (caching_flags & Flags.Excluded) != 0;
4416 caching_flags &= ~Flags.Excluded_Undetected;
4418 if (base_method == null) {
4419 if (OptAttributes == null)
4422 Attribute[] attrs = OptAttributes.SearchMulti (TypeManager.conditional_attribute_type, ec);
4427 foreach (Attribute a in attrs) {
4428 string condition = a.GetConditionalAttributeValue (Parent.EmitContext);
4429 if (RootContext.AllDefines.Contains (condition))
4433 caching_flags |= Flags.Excluded;
4437 IMethodData md = TypeManager.GetMethod (base_method);
4439 if (AttributeTester.IsConditionalMethodExcluded (base_method)) {
4440 caching_flags |= Flags.Excluded;
4446 if (md.IsExcluded (ec)) {
4447 caching_flags |= Flags.Excluded;
4453 GenericMethod IMethodData.GenericMethod {
4455 return GenericMethod;
4462 public abstract class ConstructorInitializer {
4463 ArrayList argument_list;
4464 protected ConstructorInfo base_constructor;
4467 public ConstructorInitializer (ArrayList argument_list, Location loc)
4469 this.argument_list = argument_list;
4473 public ArrayList Arguments {
4475 return argument_list;
4479 public bool Resolve (ConstructorBuilder caller_builder, Block block, EmitContext ec)
4481 Expression base_constructor_group;
4485 ec.CurrentBlock = block;
4487 if (argument_list != null){
4488 foreach (Argument a in argument_list){
4489 if (!a.Resolve (ec, loc))
4493 ec.CurrentBlock = null;
4495 if (this is ConstructorBaseInitializer) {
4496 if (ec.ContainerType.BaseType == null)
4499 t = ec.ContainerType.BaseType;
4500 if (ec.ContainerType.IsValueType) {
4501 Report.Error (522, loc,
4502 "`{0}': Struct constructors cannot call base constructors", TypeManager.CSharpSignature (caller_builder));
4506 t = ec.ContainerType;
4508 base_constructor_group = Expression.MemberLookup (
4509 ec, t, ".ctor", MemberTypes.Constructor,
4510 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4513 if (base_constructor_group == null){
4515 base_constructor_group = Expression.MemberLookup (
4516 ec, t, null, t, ".ctor", MemberTypes.Constructor,
4517 BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly,
4521 int errors = Report.Errors;
4522 if (base_constructor_group != null)
4523 base_constructor = (ConstructorInfo) Invocation.OverloadResolve (
4524 ec, (MethodGroupExpr) base_constructor_group, argument_list,
4527 if (base_constructor == null) {
4528 if (errors == Report.Errors)
4529 Invocation.Error_WrongNumArguments (loc, TypeManager.CSharpSignature (caller_builder),
4530 argument_list.Count);
4535 Expression.ErrorIsInaccesible (loc, TypeManager.CSharpSignature (base_constructor));
4536 base_constructor = null;
4540 if (base_constructor == caller_builder){
4541 Report.Error (516, loc, "Constructor `{0}' cannot call itself", TypeManager.CSharpSignature (caller_builder));
4548 public virtual void Emit (EmitContext ec)
4550 if (base_constructor != null){
4551 ec.Mark (loc, false);
4553 Invocation.EmitCall (ec, true, true, null, base_constructor, argument_list, loc);
4555 Invocation.EmitCall (ec, true, false, ec.GetThis (loc), base_constructor, argument_list, loc);
4560 public class ConstructorBaseInitializer : ConstructorInitializer {
4561 public ConstructorBaseInitializer (ArrayList argument_list, Location l) :
4562 base (argument_list, l)
4567 class GeneratedBaseInitializer: ConstructorBaseInitializer {
4568 public GeneratedBaseInitializer (Location loc):
4573 public override void Emit(EmitContext ec)
4575 bool old = ec.TestObsoleteMethodUsage;
4576 ec.TestObsoleteMethodUsage = false;
4578 ec.TestObsoleteMethodUsage = old;
4582 public class ConstructorThisInitializer : ConstructorInitializer {
4583 public ConstructorThisInitializer (ArrayList argument_list, Location l) :
4584 base (argument_list, l)
4589 public class Constructor : MethodCore, IMethodData {
4590 public ConstructorBuilder ConstructorBuilder;
4591 public ConstructorInitializer Initializer;
4592 ListDictionary declarative_security;
4595 // Modifiers allowed for a constructor.
4597 public const int AllowedModifiers =
4599 Modifiers.PROTECTED |
4600 Modifiers.INTERNAL |
4606 bool has_compliant_args = false;
4608 // The spec claims that static is not permitted, but
4609 // my very own code has static constructors.
4611 public Constructor (TypeContainer ds, string name, int mod, Parameters args,
4612 ConstructorInitializer init, Location loc)
4613 : base (ds, null, null, mod, AllowedModifiers, false,
4614 new MemberName (name, loc), null, args)
4619 public bool HasCompliantArgs {
4621 return has_compliant_args;
4625 public override AttributeTargets AttributeTargets {
4627 return AttributeTargets.Constructor;
4633 // Returns true if this is a default constructor
4635 public bool IsDefault ()
4637 if ((ModFlags & Modifiers.STATIC) != 0)
4638 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4639 (Parameters.ArrayParameter == null ? true : Parameters.Empty);
4642 return (Parameters.FixedParameters == null ? true : Parameters.Empty) &&
4643 (Parameters.ArrayParameter == null ? true : Parameters.Empty) &&
4644 (Initializer is ConstructorBaseInitializer) &&
4645 (Initializer.Arguments == null);
4648 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
4650 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
4651 if (declarative_security == null) {
4652 declarative_security = new ListDictionary ();
4654 a.ExtractSecurityPermissionSet (declarative_security);
4658 ConstructorBuilder.SetCustomAttribute (cb);
4661 protected override bool CheckForDuplications ()
4663 ArrayList ar = Parent.InstanceConstructors;
4665 int arLen = ar.Count;
4667 for (int i = 0; i < arLen; i++) {
4668 Constructor m = (Constructor) ar [i];
4669 if (IsDuplicateImplementation (m))
4676 protected override bool CheckBase ()
4678 // Check whether arguments were correct.
4679 if (!DoDefineParameters ())
4682 // TODO: skip the rest for generated ctor
4683 if ((ModFlags & Modifiers.STATIC) != 0)
4686 if (!CheckForDuplications ())
4689 if (Parent.Kind == Kind.Struct) {
4690 if (ParameterTypes.Length == 0) {
4691 Report.Error (568, Location,
4692 "Structs cannot contain explicit parameterless constructors");
4696 if ((ModFlags & Modifiers.PROTECTED) != 0) {
4697 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
4702 if ((RootContext.WarningLevel >= 4) && ((Parent.ModFlags & Modifiers.SEALED) != 0 && (ModFlags & Modifiers.PROTECTED) != 0)) {
4703 Report.Warning (628, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
4710 // Creates the ConstructorBuilder
4712 public override bool Define ()
4714 if (ConstructorBuilder != null)
4717 MethodAttributes ca = (MethodAttributes.RTSpecialName |
4718 MethodAttributes.SpecialName);
4720 if ((ModFlags & Modifiers.STATIC) != 0){
4721 ca |= MethodAttributes.Static | MethodAttributes.Private;
4723 ca |= MethodAttributes.HideBySig;
4725 if ((ModFlags & Modifiers.PUBLIC) != 0)
4726 ca |= MethodAttributes.Public;
4727 else if ((ModFlags & Modifiers.PROTECTED) != 0){
4728 if ((ModFlags & Modifiers.INTERNAL) != 0)
4729 ca |= MethodAttributes.FamORAssem;
4731 ca |= MethodAttributes.Family;
4732 } else if ((ModFlags & Modifiers.INTERNAL) != 0)
4733 ca |= MethodAttributes.Assembly;
4734 else if (IsDefault ())
4735 ca |= MethodAttributes.Public;
4737 ca |= MethodAttributes.Private;
4740 if (!CheckAbstractAndExtern (block != null))
4743 // Check if arguments were correct.
4747 ConstructorBuilder = Parent.TypeBuilder.DefineConstructor (
4748 ca, CallingConventions,
4751 if ((ModFlags & Modifiers.UNSAFE) != 0)
4752 ConstructorBuilder.InitLocals = false;
4754 TypeManager.AddMethod (ConstructorBuilder, this);
4757 // HACK because System.Reflection.Emit is lame
4759 TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes);
4767 public override void Emit ()
4769 EmitContext ec = CreateEmitContext (null, null);
4771 // If this is a non-static `struct' constructor and doesn't have any
4772 // initializer, it must initialize all of the struct's fields.
4773 if ((Parent.Kind == Kind.Struct) &&
4774 ((ModFlags & Modifiers.STATIC) == 0) && (Initializer == null))
4775 Block.AddThisVariable (Parent, Location);
4777 if (block != null) {
4778 if (!block.ResolveMeta (ec, ParameterInfo))
4782 if ((ModFlags & Modifiers.STATIC) == 0){
4783 if (Parent.Kind == Kind.Class && Initializer == null)
4784 Initializer = new GeneratedBaseInitializer (Location);
4788 // Spec mandates that Initializers will not have
4792 if ((Initializer != null) &&
4793 !Initializer.Resolve (ConstructorBuilder, block, ec))
4795 ec.IsStatic = false;
4798 Parameters.LabelParameters (ec, ConstructorBuilder);
4800 SourceMethod source = SourceMethod.Create (
4801 Parent, ConstructorBuilder, block);
4804 // Classes can have base initializers and instance field initializers.
4806 if (Parent.Kind == Kind.Class){
4807 if ((ModFlags & Modifiers.STATIC) == 0){
4810 // If we use a "this (...)" constructor initializer, then
4811 // do not emit field initializers, they are initialized in the other constructor
4813 if (!(Initializer != null && Initializer is ConstructorThisInitializer))
4814 Parent.EmitFieldInitializers (ec);
4817 if (Initializer != null) {
4818 if (GetObsoleteAttribute () != null || Parent.GetObsoleteAttribute () != null)
4819 ec.TestObsoleteMethodUsage = false;
4821 Initializer.Emit (ec);
4824 if ((ModFlags & Modifiers.STATIC) != 0)
4825 Parent.EmitFieldInitializers (ec);
4827 if (OptAttributes != null)
4828 OptAttributes.Emit (ec, this);
4830 ec.EmitTopBlock (this, block, ParameterInfo);
4833 source.CloseMethod ();
4837 if (declarative_security != null) {
4838 foreach (DictionaryEntry de in declarative_security) {
4839 ConstructorBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
4846 // Is never override
4847 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
4852 public override string GetSignatureForError()
4854 return base.GetSignatureForError () + Parameters.GetSignatureForError ();
4857 protected override bool VerifyClsCompliance (DeclSpace ds)
4859 if (!base.VerifyClsCompliance (ds) || !IsExposedFromAssembly (ds)) {
4863 if (parameter_types.Length > 0) {
4864 ArrayList al = (ArrayList)ds.MemberCache.Members [".ctor"];
4866 ds.MemberCache.VerifyClsParameterConflict (al, this, ConstructorBuilder);
4868 if (ds.TypeBuilder.IsSubclassOf (TypeManager.attribute_type)) {
4869 foreach (Type param in parameter_types) {
4870 if (param.IsArray) {
4876 has_compliant_args = true;
4880 #region IMethodData Members
4882 public System.Reflection.CallingConventions CallingConventions {
4884 CallingConventions cc = Parameters.GetCallingConvention ();
4886 if (Parent.Kind == Kind.Class)
4887 if ((ModFlags & Modifiers.STATIC) == 0)
4888 cc |= CallingConventions.HasThis;
4890 // FIXME: How is `ExplicitThis' used in C#?
4896 public new Location Location {
4898 return base.Location;
4902 public MemberName MethodName {
4908 public Type ReturnType {
4914 public EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig)
4916 ILGenerator ig_ = ConstructorBuilder.GetILGenerator ();
4917 return new EmitContext (Parent, Location, ig_, null, ModFlags, true);
4920 public bool IsExcluded(EmitContext ec)
4925 GenericMethod IMethodData.GenericMethod {
4935 /// Interface for MethodData class. Holds links to parent members to avoid member duplication.
4937 public interface IMethodData
4939 CallingConventions CallingConventions { get; }
4940 Location Location { get; }
4941 MemberName MethodName { get; }
4942 Type[] ParameterTypes { get; }
4943 Type ReturnType { get; }
4944 GenericMethod GenericMethod { get; }
4946 Attributes OptAttributes { get; }
4947 ToplevelBlock Block { get; set; }
4949 EmitContext CreateEmitContext (TypeContainer tc, ILGenerator ig);
4950 ObsoleteAttribute GetObsoleteAttribute ();
4951 string GetSignatureForError ();
4952 bool IsExcluded (EmitContext ec);
4953 bool IsClsComplianceRequired (DeclSpace ds);
4954 void SetMemberIsUsed ();
4958 // Encapsulates most of the Method's state
4960 public class MethodData {
4962 readonly IMethodData method;
4965 // The return type of this method
4967 public readonly GenericMethod GenericMethod;
4968 public readonly InternalParameters ParameterInfo;
4971 // Are we implementing an interface ?
4973 public MethodInfo implementing;
4978 protected MemberBase member;
4979 protected int modifiers;
4980 protected MethodAttributes flags;
4981 protected Type declaring_type;
4982 protected MethodInfo parent_method;
4984 MethodBuilder builder = null;
4985 public MethodBuilder MethodBuilder {
4991 public Type DeclaringType {
4993 return declaring_type;
4997 public MethodData (MemberBase member, InternalParameters parameters,
4998 int modifiers, MethodAttributes flags, IMethodData method)
5000 this.member = member;
5001 this.ParameterInfo = parameters;
5002 this.modifiers = modifiers;
5005 this.method = method;
5008 public MethodData (MemberBase member, InternalParameters parameters,
5009 int modifiers, MethodAttributes flags,
5010 IMethodData method, MethodBuilder builder,
5011 GenericMethod generic, MethodInfo parent_method)
5012 : this (member, parameters, modifiers, flags, method)
5014 this.builder = builder;
5015 this.GenericMethod = generic;
5016 this.parent_method = parent_method;
5019 public bool Define (TypeContainer container)
5021 string name = method.MethodName.Basename;
5022 string method_name = method.MethodName.FullName;
5024 Type[] ParameterTypes = method.ParameterTypes;
5026 if (container.Pending != null){
5027 if (member is Indexer) // TODO: test it, but it should work without this IF
5028 implementing = container.Pending.IsInterfaceIndexer (
5029 member.InterfaceType, method.ReturnType, ParameterInfo);
5031 implementing = container.Pending.IsInterfaceMethod (
5032 member.InterfaceType, name, method.ReturnType, ParameterInfo);
5034 if (member.InterfaceType != null){
5035 if (implementing == null){
5036 if (member is PropertyBase) {
5037 Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'",
5038 method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType),
5039 member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.')));
5042 Report.Error (539, method.Location,
5043 "`{0}.{1}' in explicit interface declaration is not a member of interface",
5044 TypeManager.CSharpName (member.InterfaceType), member.ShortName);
5048 if (implementing.IsSpecialName && !(method is AbstractPropertyEventMethod)) {
5049 Report.SymbolRelatedToPreviousError (implementing);
5050 Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor",
5051 member.GetSignatureForError (), TypeManager.CSharpSignature (implementing));
5055 method_name = TypeManager.GetFullName (member.InterfaceType) + "." + method_name;
5057 if (implementing != null) {
5058 AbstractPropertyEventMethod prop_method = method as AbstractPropertyEventMethod;
5059 if (prop_method != null) {
5060 if (!implementing.IsSpecialName) {
5061 Report.SymbolRelatedToPreviousError (implementing);
5062 Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation",
5063 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ());
5066 PropertyBase.PropertyMethod pm = prop_method as PropertyBase.PropertyMethod;
5067 if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) {
5068 Report.SymbolRelatedToPreviousError (implementing);
5069 Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'",
5070 method.GetSignatureForError (), TypeManager.CSharpSignature (implementing, true));
5079 // For implicit implementations, make sure we are public, for
5080 // explicit implementations, make sure we are private.
5082 if (implementing != null){
5084 // Setting null inside this block will trigger a more
5085 // verbose error reporting for missing interface implementations
5087 // The "candidate" function has been flagged already
5088 // but it wont get cleared
5090 if (member.IsExplicitImpl){
5091 if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
5092 Modifiers.Error_InvalidModifier (method.Location, "public, virtual or abstract");
5093 implementing = null;
5095 } else if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public){
5096 if (TypeManager.IsInterfaceType (implementing.DeclaringType)){
5098 // If this is an interface method implementation,
5099 // check for public accessibility
5101 implementing = null;
5102 } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){
5103 // We may never be private.
5104 implementing = null;
5105 } else if ((modifiers & Modifiers.OVERRIDE) == 0){
5107 // We may be protected if we're overriding something.
5109 implementing = null;
5114 // Static is not allowed
5116 if ((modifiers & Modifiers.STATIC) != 0){
5117 implementing = null;
5122 // If implementing is still valid, set flags
5124 if (implementing != null){
5126 // When implementing interface methods, set NewSlot
5127 // unless, we are overwriting a method.
5129 if (implementing.DeclaringType.IsInterface){
5130 if ((modifiers & Modifiers.OVERRIDE) == 0)
5131 flags |= MethodAttributes.NewSlot;
5134 MethodAttributes.Virtual |
5135 MethodAttributes.HideBySig;
5137 // Set Final unless we're virtual, abstract or already overriding a method.
5138 if ((modifiers & (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE)) == 0)
5139 flags |= MethodAttributes.Final;
5142 EmitContext ec = method.CreateEmitContext (container, null);
5144 DefineMethodBuilder (ec, container, method_name, ParameterTypes);
5146 if (builder == null)
5149 if (container.CurrentType != null)
5150 declaring_type = container.CurrentType;
5152 declaring_type = container.TypeBuilder;
5154 if ((modifiers & Modifiers.UNSAFE) != 0)
5155 builder.InitLocals = false;
5157 if (implementing != null){
5159 // clear the pending implemntation flag
5161 if (member is Indexer) {
5162 container.Pending.ImplementIndexer (
5163 member.InterfaceType, builder, method.ReturnType,
5164 ParameterInfo, member.IsExplicitImpl);
5166 container.Pending.ImplementMethod (
5167 member.InterfaceType, name, method.ReturnType,
5168 ParameterInfo, member.IsExplicitImpl);
5170 if (member.IsExplicitImpl)
5171 container.TypeBuilder.DefineMethodOverride (
5172 builder, implementing);
5175 TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes);
5176 TypeManager.AddMethod (builder, method);
5178 if (GenericMethod != null) {
5179 bool is_override = member.IsExplicitImpl |
5180 ((modifiers & Modifiers.OVERRIDE) != 0);
5182 if (implementing != null)
5183 parent_method = implementing;
5185 if (!GenericMethod.DefineType (ec, builder, parent_method, is_override))
5193 /// Create the MethodBuilder for the method
5195 void DefineMethodBuilder (EmitContext ec, TypeContainer container, string method_name, Type[] ParameterTypes)
5197 const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
5199 if ((modifiers & extern_static) == extern_static) {
5201 if (method.OptAttributes != null) {
5202 Attribute dllimport_attribute = method.OptAttributes.Search (TypeManager.dllimport_type, ec);
5203 if (dllimport_attribute != null) {
5204 flags |= MethodAttributes.PinvokeImpl;
5205 builder = dllimport_attribute.DefinePInvokeMethod (
5206 ec, container.TypeBuilder, method_name, flags,
5207 method.ReturnType, ParameterTypes);
5213 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
5214 // We are more strict than Microsoft and report CS0626 like error
5215 if (method.OptAttributes == null ||
5216 !method.OptAttributes.Contains (TypeManager.methodimpl_attr_type, ec)) {
5217 Report.Error (626, method.Location, "Method, operator, or accessor `{0}' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation",
5218 method.GetSignatureForError ());
5223 if (builder == null)
5224 builder = container.TypeBuilder.DefineMethod (
5225 method_name, flags, method.CallingConventions,
5226 method.ReturnType, ParameterTypes);
5228 builder.SetGenericMethodSignature (
5229 flags, method.CallingConventions,
5230 method.ReturnType, ParameterTypes);
5236 public void Emit (TypeContainer container, Attributable kind)
5239 if ((flags & MethodAttributes.PinvokeImpl) == 0)
5240 ec = method.CreateEmitContext (container, builder.GetILGenerator ());
5242 ec = method.CreateEmitContext (container, null);
5244 if (method.GetObsoleteAttribute () != null || container.GetObsoleteAttribute () != null)
5245 ec.TestObsoleteMethodUsage = false;
5247 Attributes OptAttributes = method.OptAttributes;
5249 if (OptAttributes != null)
5250 OptAttributes.Emit (ec, kind);
5252 if (member is MethodCore)
5253 ((MethodCore) member).Parameters.LabelParameters (ec, MethodBuilder);
5255 ToplevelBlock block = method.Block;
5257 SourceMethod source = SourceMethod.Create (
5258 container, MethodBuilder, method.Block);
5261 // Handle destructors specially
5263 // FIXME: This code generates buggy code
5265 if (member is Destructor)
5266 EmitDestructor (ec, block);
5268 ec.EmitTopBlock (method, block, ParameterInfo);
5271 source.CloseMethod ();
5274 void EmitDestructor (EmitContext ec, ToplevelBlock block)
5276 ILGenerator ig = ec.ig;
5278 Label finish = ig.DefineLabel ();
5280 block.SetDestructor ();
5282 ig.BeginExceptionBlock ();
5283 ec.ReturnLabel = finish;
5284 ec.HasReturnLabel = true;
5285 ec.EmitTopBlock (method, block, null);
5287 // ig.MarkLabel (finish);
5288 ig.BeginFinallyBlock ();
5290 if (ec.ContainerType.BaseType != null) {
5291 Expression member_lookup = Expression.MemberLookup (
5292 ec, ec.ContainerType.BaseType, null, ec.ContainerType.BaseType,
5293 "Finalize", MemberTypes.Method, Expression.AllBindingFlags, method.Location);
5295 if (member_lookup != null){
5296 MethodGroupExpr base_destructor = ((MethodGroupExpr) member_lookup);
5298 ig.Emit (OpCodes.Ldarg_0);
5299 ig.Emit (OpCodes.Call, (MethodInfo) base_destructor.Methods [0]);
5303 ig.EndExceptionBlock ();
5304 //ig.MarkLabel (ec.ReturnLabel);
5305 ig.Emit (OpCodes.Ret);
5309 // TODO: Should derive from MethodCore
5310 public class Destructor : Method {
5312 public Destructor (TypeContainer ds, Expression return_type, int mod,
5313 string name, Parameters parameters, Attributes attrs,
5315 : base (ds, null, return_type, mod, false, new MemberName (name, l),
5319 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5321 if (a.Type == TypeManager.conditional_attribute_type) {
5322 Report.Error (577, Location, "Conditional not valid on `{0}' because it is a constructor, destructor, operator or explicit interface implementation",
5323 GetSignatureForError ());
5327 base.ApplyAttributeBuilder (a, cb);
5330 public override string GetSignatureForError ()
5332 return Parent.GetSignatureForError () + ".~" + Parent.MemberName.Name + "()";
5337 abstract public class MemberBase : MemberCore {
5338 public Expression Type;
5340 public MethodAttributes flags;
5341 public readonly DeclSpace ds;
5342 public readonly GenericMethod GenericMethod;
5344 protected readonly int explicit_mod_flags;
5347 // The "short" name of this property / indexer / event. This is the
5348 // name without the explicit interface.
5350 public string ShortName {
5351 get { return MemberName.Name; }
5353 SetMemberName (new MemberName (MemberName.Left, value, Location));
5358 // The type of this property / indexer / event
5360 protected Type member_type;
5361 public Type MemberType {
5363 if (member_type == null && Type != null) {
5364 EmitContext ec = ds.EmitContext;
5365 bool old_unsafe = ec.InUnsafe;
5366 ec.InUnsafe = InUnsafe;
5367 ec.ResolvingGenericMethod = GenericMethod != null;
5368 Type = Type.ResolveAsTypeTerminal (ec);
5369 ec.ResolvingGenericMethod = false;
5370 ec.InUnsafe = old_unsafe;
5372 member_type = Type.Type;
5380 // Whether this is an interface member.
5382 public bool IsInterface;
5385 // If true, this is an explicit interface implementation
5387 public bool IsExplicitImpl;
5390 // The interface type we are explicitly implementing
5392 public Type InterfaceType = null;
5395 // The constructor is only exposed to our children
5397 protected MemberBase (TypeContainer parent, GenericMethod generic,
5398 Expression type, int mod, int allowed_mod, int def_mod,
5399 MemberName name, Attributes attrs)
5400 : base (parent, name, attrs)
5402 this.ds = generic != null ? generic : (DeclSpace) parent;
5403 explicit_mod_flags = mod;
5405 ModFlags = Modifiers.Check (allowed_mod, mod, def_mod, Location);
5406 IsExplicitImpl = (MemberName.Left != null);
5407 GenericMethod = generic;
5410 protected virtual bool CheckBase ()
5412 if ((ModFlags & Modifiers.PROTECTED) != 0 && Parent.Kind == Kind.Struct) {
5413 Report.Error (666, Location, "`{0}': new protected member declared in struct", GetSignatureForError ());
5417 if ((RootContext.WarningLevel >= 4) &&
5418 ((Parent.ModFlags & Modifiers.SEALED) != 0) &&
5419 ((ModFlags & Modifiers.PROTECTED) != 0) &&
5420 ((ModFlags & Modifiers.OVERRIDE) == 0) && (Name != "Finalize")) {
5421 Report.Warning (628, Location, "`{0}': new protected member declared in sealed class", GetSignatureForError ());
5426 protected abstract bool CheckGenericOverride (MethodInfo method, string name);
5428 protected virtual bool CheckParameters (DeclSpace ds, Type [] parameters)
5432 foreach (Type partype in parameters){
5433 if (partype == TypeManager.void_type) {
5435 1547, Location, "Keyword 'void' cannot " +
5436 "be used in this context");
5440 if (partype.IsPointer){
5443 if (!TypeManager.VerifyUnManaged (TypeManager.GetElementType (partype), Location))
5447 if (ds.AsAccessible (partype, ModFlags))
5450 if (this is Indexer)
5451 Report.Error (55, Location,
5452 "Inconsistent accessibility: parameter type `" +
5453 TypeManager.CSharpName (partype) + "' is less " +
5454 "accessible than indexer `" + GetSignatureForError () + "'");
5455 else if ((this is Method) && ((Method) this).IsOperator != null)
5456 Report.Error (57, Location,
5457 "Inconsistent accessibility: parameter type `" +
5458 TypeManager.CSharpName (partype) + "' is less " +
5459 "accessible than operator `" + GetSignatureForError () + "'");
5461 Report.Error (51, Location,
5462 "Inconsistent accessibility: parameter type `" +
5463 TypeManager.CSharpName (partype) + "' is less " +
5464 "accessible than method `" + GetSignatureForError () + "'");
5471 protected virtual bool DoDefineBase ()
5473 EmitContext ec = Parent.EmitContext;
5475 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5478 throw new InternalErrorException ();
5481 ModFlags = Modifiers.PUBLIC |
5482 Modifiers.ABSTRACT |
5483 Modifiers.VIRTUAL | (ModFlags & Modifiers.UNSAFE) | (ModFlags & Modifiers.NEW);
5485 flags = MethodAttributes.Public |
5486 MethodAttributes.Abstract |
5487 MethodAttributes.HideBySig |
5488 MethodAttributes.NewSlot |
5489 MethodAttributes.Virtual;
5491 if (!Parent.MethodModifiersValid (this))
5494 flags = Modifiers.MethodAttr (ModFlags);
5497 if (IsExplicitImpl) {
5498 Expression expr = MemberName.Left.GetTypeExpression ();
5499 TypeExpr iface_texpr = expr.ResolveAsTypeTerminal (ec);
5500 if (iface_texpr == null)
5503 InterfaceType = iface_texpr.ResolveType (ec);
5505 if (!InterfaceType.IsInterface) {
5506 Report.Error (538, Location, "'{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5510 if (!Parent.VerifyImplements (this))
5513 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5519 protected virtual bool DoDefine ()
5521 EmitContext ec = ds.EmitContext;
5523 throw new InternalErrorException ("MemberBase.DoDefine called too early");
5525 ec.InUnsafe = InUnsafe;
5527 if (MemberType == null)
5530 CheckObsoleteType (Type);
5532 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
5533 (ModFlags & (Modifiers.VIRTUAL|Modifiers.ABSTRACT)) != 0) {
5534 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
5535 GetSignatureForError (), Parent.GetSignatureForError ());
5539 // verify accessibility
5540 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5541 Report.SymbolRelatedToPreviousError (MemberType);
5542 if (this is Property)
5543 Report.Error (53, Location,
5544 "Inconsistent accessibility: property type `" +
5545 TypeManager.CSharpName (MemberType) + "' is less " +
5546 "accessible than property `" + GetSignatureForError () + "'");
5547 else if (this is Indexer)
5548 Report.Error (54, Location,
5549 "Inconsistent accessibility: indexer return type `" +
5550 TypeManager.CSharpName (MemberType) + "' is less " +
5551 "accessible than indexer `" + GetSignatureForError () + "'");
5552 else if (this is MethodCore) {
5553 if (this is Operator)
5554 Report.Error (56, Location,
5555 "Inconsistent accessibility: return type `" +
5556 TypeManager.CSharpName (MemberType) + "' is less " +
5557 "accessible than operator `" + GetSignatureForError () + "'");
5559 Report.Error (50, Location,
5560 "Inconsistent accessibility: return type `" +
5561 TypeManager.CSharpName (MemberType) + "' is less " +
5562 "accessible than method `" + GetSignatureForError () + "'");
5564 Report.Error (52, Location,
5565 "Inconsistent accessibility: field type `" +
5566 TypeManager.CSharpName (MemberType) + "' is less " +
5567 "accessible than field `" + GetSignatureForError () + "'");
5572 if (MemberType.IsPointer && !UnsafeOK (Parent))
5575 if (IsExplicitImpl) {
5576 Expression expr = MemberName.Left.GetTypeExpression ();
5577 TypeExpr texpr = expr.ResolveAsTypeTerminal (ec);
5581 InterfaceType = texpr.ResolveType (ec);
5583 if (!InterfaceType.IsInterface) {
5584 Report.Error (538, Location, "`{0}' in explicit interface declaration is not an interface", TypeManager.CSharpName (InterfaceType));
5588 if (!Parent.VerifyImplements (this))
5591 Modifiers.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location);
5597 protected bool IsTypePermitted ()
5599 if (MemberType == TypeManager.arg_iterator_type || MemberType == TypeManager.typed_reference_type) {
5600 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
5606 protected override bool VerifyClsCompliance(DeclSpace ds)
5608 if (base.VerifyClsCompliance (ds)) {
5612 if (IsInterface && HasClsCompliantAttribute && ds.IsClsComplianceRequired (ds)) {
5613 Report.Error (3010, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
5621 // Fields and Events both generate FieldBuilders, we use this to share
5622 // their common bits. This is also used to flag usage of the field
5624 abstract public class FieldBase : MemberBase {
5625 public FieldBuilder FieldBuilder;
5626 public Status status;
5629 public enum Status : byte {
5630 HAS_OFFSET = 4 // Used by FieldMember.
5633 static string[] attribute_targets = new string [] { "field" };
5636 /// Symbol with same name in base class/struct
5638 public MemberInfo conflict_symbol;
5641 // The constructor is only exposed to our children
5643 protected FieldBase (TypeContainer parent, Expression type, int mod,
5644 int allowed_mod, MemberName name, object init,
5646 : base (parent, null, type, mod, allowed_mod, Modifiers.PRIVATE,
5652 public override AttributeTargets AttributeTargets {
5654 return AttributeTargets.Field;
5658 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
5660 if (a.Type == TypeManager.marshal_as_attr_type) {
5661 UnmanagedMarshal marshal = a.GetMarshal (this);
5662 if (marshal != null) {
5663 FieldBuilder.SetMarshal (marshal);
5668 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
5669 a.Error_InvalidSecurityParent ();
5673 FieldBuilder.SetCustomAttribute (cb);
5677 // Whether this field has an initializer.
5679 public bool HasInitializer {
5681 return init != null;
5685 protected readonly Object init;
5687 Expression init_expr;
5688 bool init_expr_initialized = false;
5690 protected override bool CheckGenericOverride (MethodInfo method, string name)
5696 // Resolves and returns the field initializer.
5698 public Expression GetInitializerExpression (EmitContext ec)
5700 if (init_expr_initialized)
5704 if (init is Expression)
5705 e = (Expression) init;
5707 e = new ArrayCreation (Type, "", (ArrayList)init, Location);
5709 // TODO: Any reason why we are using parent EC ?
5710 EmitContext parent_ec = Parent.EmitContext;
5712 bool old_is_static = parent_ec.IsStatic;
5713 bool old_is_ctor = parent_ec.IsConstructor;
5714 parent_ec.IsStatic = ec.IsStatic;
5715 parent_ec.IsConstructor = ec.IsConstructor;
5716 parent_ec.IsFieldInitializer = true;
5717 e = e.DoResolve (parent_ec);
5718 parent_ec.IsFieldInitializer = false;
5719 parent_ec.IsStatic = old_is_static;
5720 parent_ec.IsConstructor = old_is_ctor;
5723 init_expr_initialized = true;
5728 protected override bool CheckBase ()
5730 if (!base.CheckBase ())
5737 conflict_symbol = Parent.FindBaseMemberWithSameName (Name, false);
5738 if (conflict_symbol == null) {
5739 if ((RootContext.WarningLevel >= 4) && ((ModFlags & Modifiers.NEW) != 0)) {
5740 Report.Warning (109, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
5745 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0) {
5746 Report.SymbolRelatedToPreviousError (conflict_symbol);
5747 Report.Warning (108, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
5748 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
5754 protected virtual bool IsFieldClsCompliant {
5756 if (FieldBuilder == null)
5759 return AttributeTester.IsClsCompliant (FieldBuilder.FieldType);
5763 public override string[] ValidAttributeTargets {
5765 return attribute_targets;
5769 protected override bool VerifyClsCompliance (DeclSpace ds)
5771 if (!base.VerifyClsCompliance (ds))
5774 if (!IsFieldClsCompliant) {
5775 Report.Error (3003, Location, "Type of `{0}' is not CLS-compliant", GetSignatureForError ());
5781 public void SetAssigned ()
5783 caching_flags |= Flags.IsAssigned;
5787 public abstract class FieldMember: FieldBase
5789 protected FieldMember (TypeContainer parent, Expression type, int mod,
5790 int allowed_mod, MemberName name, object init, Attributes attrs)
5791 : base (parent, type, mod, allowed_mod | Modifiers.ABSTRACT, name, init, attrs)
5793 if ((mod & Modifiers.ABSTRACT) != 0)
5794 Report.Error (681, Location, "The modifier 'abstract' is not valid on fields. Try using a property instead");
5797 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
5799 if (a.Type == TypeManager.field_offset_attribute_type)
5801 status |= Status.HAS_OFFSET;
5803 if (!Parent.HasExplicitLayout) {
5804 Report.Error (636, Location, "The FieldOffset attribute can only be placed on members of types marked with the StructLayout(LayoutKind.Explicit)");
5808 if ((ModFlags & Modifiers.STATIC) != 0 || this is Const) {
5809 Report.Error (637, Location, "The FieldOffset attribute is not allowed on static or const fields");
5814 if (a.Type == TypeManager.fixed_buffer_attr_type) {
5815 Report.Error (1716, Location, "Do not use 'System.Runtime.CompilerServices.FixedBuffer' attribute. Use the 'fixed' field modifier instead");
5819 base.ApplyAttributeBuilder (a, cb);
5823 public override bool Define()
5825 EmitContext ec = Parent.EmitContext;
5827 throw new InternalErrorException ("FieldMember.Define called too early");
5829 if (MemberType == null || Type == null)
5832 CheckObsoleteType (Type);
5834 if (MemberType == TypeManager.void_type) {
5835 Report.Error (1547, Location, "Keyword 'void' cannot be used in this context");
5842 if (!Parent.AsAccessible (MemberType, ModFlags)) {
5843 Report.Error (52, Location,
5844 "Inconsistent accessibility: field type `" +
5845 TypeManager.CSharpName (MemberType) + "' is less " +
5846 "accessible than field `" + GetSignatureForError () + "'");
5850 if (!IsTypePermitted ())
5853 if (MemberType.IsPointer && !UnsafeOK (Parent))
5859 public override void Emit ()
5861 if (OptAttributes != null) {
5862 EmitContext ec = new EmitContext (Parent, Location, null, FieldBuilder.FieldType, ModFlags);
5863 OptAttributes.Emit (ec, this);
5866 if (Parent.HasExplicitLayout && ((status & Status.HAS_OFFSET) == 0) && (ModFlags & Modifiers.STATIC) == 0) {
5867 Report.Error (625, Location, "`{0}': Instance field types marked with StructLayout(LayoutKind.Explicit) must have a FieldOffset attribute.", GetSignatureForError ());
5874 // Represents header string for documentation comment.
5876 public override string DocCommentHeader {
5877 get { return "F:"; }
5881 interface IFixedBuffer
5883 FieldInfo Element { get; }
5884 Type ElementType { get; }
5887 public class FixedFieldExternal: IFixedBuffer
5889 FieldInfo element_field;
5891 public FixedFieldExternal (FieldInfo fi)
5893 element_field = fi.FieldType.GetField (FixedField.FixedElementName);
5896 #region IFixedField Members
5898 public FieldInfo Element {
5900 return element_field;
5904 public Type ElementType {
5906 return element_field.FieldType;
5914 /// Fixed buffer implementation
5916 public class FixedField: FieldMember, IFixedBuffer
5918 public const string FixedElementName = "FixedElementField";
5919 static int GlobalCounter = 0;
5920 static object[] ctor_args = new object[] { (short)LayoutKind.Sequential };
5921 static FieldInfo[] fi;
5923 TypeBuilder fixed_buffer_type;
5924 FieldBuilder element;
5925 Expression size_expr;
5928 const int AllowedModifiers =
5931 Modifiers.PROTECTED |
5932 Modifiers.INTERNAL |
5935 public FixedField (TypeContainer parent, Expression type, int mod, string name,
5936 Expression size_expr, Attributes attrs, Location loc):
5937 base (parent, type, mod, AllowedModifiers, new MemberName (name, loc), null, attrs)
5939 if (RootContext.Version == LanguageVersion.ISO_1)
5940 Report.FeatureIsNotStandardized (loc, "fixed size buffers");
5942 this.size_expr = size_expr;
5945 public override bool Define()
5947 if (Parent.Kind != Kind.Struct) {
5948 Report.Error (1642, Location, "`{0}': Fixed size buffer fields may only be members of structs",
5949 GetSignatureForError ());
5953 if (!base.Define ())
5956 if (!TypeManager.IsPrimitiveType (MemberType)) {
5957 Report.Error (1663, Location, "`{0}': Fixed size buffers type must be one of the following: bool, byte, short, int, long, char, sbyte, ushort, uint, ulong, float or double",
5958 GetSignatureForError ());
5962 Constant c = size_expr.ResolveAsConstant (Parent.EmitContext, this);
5966 IntConstant buffer_size_const = c.ToInt (Location);
5967 if (buffer_size_const == null)
5970 buffer_size = buffer_size_const.Value;
5972 if (buffer_size <= 0) {
5973 Report.Error (1665, Location, "`{0}': Fixed size buffers must have a length greater than zero", GetSignatureForError ());
5977 int type_size = Expression.GetTypeSize (MemberType);
5979 if (buffer_size > int.MaxValue / type_size) {
5980 Report.Error (1664, Location, "Fixed size buffer `{0}' of length `{1}' and type `{2}' exceeded 2^31 limit",
5981 GetSignatureForError (), buffer_size.ToString (), TypeManager.CSharpName (MemberType));
5985 buffer_size *= type_size;
5988 string name = String.Format ("<{0}>__FixedBuffer{1}", Name, GlobalCounter++);
5990 fixed_buffer_type = Parent.TypeBuilder.DefineNestedType (name,
5991 TypeAttributes.NestedPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit, TypeManager.value_type);
5992 element = fixed_buffer_type.DefineField (FixedElementName, MemberType, FieldAttributes.Public);
5993 RootContext.RegisterCompilerGeneratedType (fixed_buffer_type);
5995 FieldBuilder = Parent.TypeBuilder.DefineField (Name, fixed_buffer_type, Modifiers.FieldAttr (ModFlags));
5996 TypeManager.RegisterFieldBase (FieldBuilder, this);
6001 public override void Emit()
6004 fi = new FieldInfo [] { TypeManager.struct_layout_attribute_type.GetField ("Size") };
6006 object[] fi_val = new object[1];
6007 fi_val [0] = buffer_size;
6009 CustomAttributeBuilder cab = new CustomAttributeBuilder (TypeManager.struct_layout_attribute_ctor,
6010 ctor_args, fi, fi_val);
6011 fixed_buffer_type.SetCustomAttribute (cab);
6013 cab = new CustomAttributeBuilder (TypeManager.fixed_buffer_attr_ctor, new object[] { MemberType, buffer_size } );
6014 FieldBuilder.SetCustomAttribute (cab);
6018 protected override bool IsFieldClsCompliant {
6024 #region IFixedField Members
6026 public FieldInfo Element {
6032 public Type ElementType {
6042 // The Field class is used to represents class/struct fields during parsing.
6044 public class Field : FieldMember {
6046 // Modifiers allowed in a class declaration
6048 const int AllowedModifiers =
6051 Modifiers.PROTECTED |
6052 Modifiers.INTERNAL |
6055 Modifiers.VOLATILE |
6059 public Field (TypeContainer parent, Expression type, int mod, string name,
6060 Object expr_or_array_init, Attributes attrs, Location loc)
6061 : base (parent, type, mod, AllowedModifiers, new MemberName (name, loc),
6062 expr_or_array_init, attrs)
6066 public override bool Define ()
6068 if (!base.Define ())
6071 if (RootContext.WarningLevel > 1){
6072 Type ptype = Parent.TypeBuilder.BaseType;
6074 // ptype is only null for System.Object while compiling corlib.
6076 TypeContainer.FindMembers (
6077 ptype, MemberTypes.Method,
6078 BindingFlags.Public |
6079 BindingFlags.Static | BindingFlags.Instance,
6080 System.Type.FilterName, Name);
6084 if ((ModFlags & Modifiers.VOLATILE) != 0){
6085 if (!MemberType.IsClass){
6086 Type vt = MemberType;
6088 if (TypeManager.IsEnumType (vt))
6089 vt = TypeManager.EnumToUnderlying (MemberType);
6091 if (!((vt == TypeManager.bool_type) ||
6092 (vt == TypeManager.sbyte_type) ||
6093 (vt == TypeManager.byte_type) ||
6094 (vt == TypeManager.short_type) ||
6095 (vt == TypeManager.ushort_type) ||
6096 (vt == TypeManager.int32_type) ||
6097 (vt == TypeManager.uint32_type) ||
6098 (vt == TypeManager.char_type) ||
6099 (vt == TypeManager.float_type) ||
6100 (!vt.IsValueType))){
6101 Report.Error (677, Location, "`{0}': A volatile field cannot be of the type `{1}'",
6102 GetSignatureForError (), TypeManager.CSharpName (vt));
6107 if ((ModFlags & Modifiers.READONLY) != 0){
6108 Report.Error (678, Location, "`{0}': A field cannot be both volatile and readonly",
6109 GetSignatureForError ());
6114 FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
6116 if (Parent.Kind == Kind.Struct &&
6117 ((fa & FieldAttributes.Static) == 0) &&
6118 MemberType == Parent.TypeBuilder &&
6119 !TypeManager.IsBuiltinType (MemberType)){
6120 Report.Error (523, Location, "Struct member `" + Parent.Name + "." + Name +
6121 "' causes a cycle in the structure layout");
6126 FieldBuilder = Parent.TypeBuilder.DefineField (
6127 Name, MemberType, Modifiers.FieldAttr (ModFlags));
6129 TypeManager.RegisterFieldBase (FieldBuilder, this);
6131 catch (ArgumentException) {
6132 Report.Warning (-24, Location, "The Microsoft runtime is unable to use [void|void*] as a field type, try using the Mono runtime.");
6139 protected override bool VerifyClsCompliance (DeclSpace ds)
6141 if (!base.VerifyClsCompliance (ds))
6144 if ((ModFlags & Modifiers.VOLATILE) != 0) {
6145 Report.Warning (3026, 1, Location, "CLS-compliant field `{0}' cannot be volatile", GetSignatureForError ());
6153 // `set' and `get' accessors are represented with an Accessor.
6155 public class Accessor : IIteratorContainer {
6157 // Null if the accessor is empty, or a Block if not
6159 public const int AllowedModifiers =
6161 Modifiers.PROTECTED |
6162 Modifiers.INTERNAL |
6165 public ToplevelBlock Block;
6166 public Attributes Attributes;
6167 public Location Location;
6168 public int ModFlags;
6171 public Accessor (ToplevelBlock b, int mod, Attributes attrs, Location loc)
6176 ModFlags = Modifiers.Check (AllowedModifiers, mod, 0, loc);
6179 public void SetYields ()
6185 // Ooouh Martin, templates are missing here.
6186 // When it will be possible move here a lot of child code and template method type.
6187 public abstract class AbstractPropertyEventMethod : MemberCore, IMethodData {
6188 protected MethodData method_data;
6189 protected ToplevelBlock block;
6190 protected ListDictionary declarative_security;
6192 // The accessor are created event if they are not wanted.
6193 // But we need them because their names are reserved.
6194 // Field says whether accessor will be emited or not
6195 public readonly bool IsDummy;
6197 protected readonly string prefix;
6199 ReturnParameter return_attributes;
6201 public AbstractPropertyEventMethod (MemberBase member, string prefix)
6202 : base (member.Parent, SetupName (prefix, member, member.Location), null)
6204 this.prefix = prefix;
6208 public AbstractPropertyEventMethod (MemberBase member, Accessor accessor,
6210 : base (member.Parent, SetupName (prefix, member, accessor.Location),
6211 accessor.Attributes)
6213 this.prefix = prefix;
6214 this.block = accessor.Block;
6217 static MemberName SetupName (string prefix, MemberBase member, Location loc)
6219 return new MemberName (member.MemberName.Left, prefix + member.ShortName, loc);
6222 public void UpdateName (MemberBase member)
6224 SetMemberName (SetupName (prefix, member, Location));
6227 #region IMethodData Members
6229 public ToplevelBlock Block {
6239 public CallingConventions CallingConventions {
6241 return CallingConventions.Standard;
6245 public bool IsExcluded (EmitContext ec)
6250 GenericMethod IMethodData.GenericMethod {
6256 public MemberName MethodName {
6262 public abstract Type[] ParameterTypes { get; }
6263 public abstract Type ReturnType { get; }
6264 public abstract EmitContext CreateEmitContext(TypeContainer tc, ILGenerator ig);
6268 public override void ApplyAttributeBuilder(Attribute a, CustomAttributeBuilder cb)
6270 if (a.Type == TypeManager.cls_compliant_attribute_type || a.Type == TypeManager.obsolete_attribute_type ||
6271 a.Type == TypeManager.conditional_attribute_type) {
6272 Report.Error (1667, a.Location,
6273 "Attribute `{0}' is not valid on property or event accessors. It is valid on `{1}' declarations only",
6274 TypeManager.CSharpName (a.Type), a.GetValidTargets ());
6278 if (a.Type.IsSubclassOf (TypeManager.security_attr_type) && a.CheckSecurityActionValidity (false)) {
6279 if (declarative_security == null)
6280 declarative_security = new ListDictionary ();
6281 a.ExtractSecurityPermissionSet (declarative_security);
6285 if (a.Target == AttributeTargets.Method) {
6286 method_data.MethodBuilder.SetCustomAttribute (cb);
6290 if (a.Target == AttributeTargets.ReturnValue) {
6291 if (return_attributes == null)
6292 return_attributes = new ReturnParameter (method_data.MethodBuilder, Location);
6294 return_attributes.ApplyAttributeBuilder (a, cb);
6298 ApplyToExtraTarget (a, cb);
6301 virtual protected void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb)
6303 System.Diagnostics.Debug.Fail ("You forgot to define special attribute target handling");
6306 public override bool Define()
6308 throw new NotSupportedException ();
6311 public virtual void Emit (TypeContainer container)
6313 EmitMethod (container);
6315 if (declarative_security != null) {
6316 foreach (DictionaryEntry de in declarative_security) {
6317 method_data.MethodBuilder.AddDeclarativeSecurity ((SecurityAction)de.Key, (PermissionSet)de.Value);
6324 protected virtual void EmitMethod (TypeContainer container)
6326 method_data.Emit (container, this);
6329 public override bool IsClsComplianceRequired(DeclSpace ds)
6334 public bool IsDuplicateImplementation (MethodCore method)
6336 if (!MemberName.Equals (method.MemberName))
6339 Type[] param_types = method.ParameterTypes;
6341 if (param_types.Length != ParameterTypes.Length)
6344 for (int i = 0; i < param_types.Length; i++)
6345 if (param_types [i] != ParameterTypes [i])
6348 Report.SymbolRelatedToPreviousError (method);
6349 Report.Error (111, Location, TypeContainer.Error111, method.GetSignatureForError ());
6353 public override bool IsUsed
6363 public new Location Location {
6365 return base.Location;
6370 // Represents header string for documentation comment.
6372 public override string DocCommentHeader {
6373 get { throw new InvalidOperationException ("Unexpected attempt to get doc comment from " + this.GetType () + "."); }
6379 // Properties and Indexers both generate PropertyBuilders, we use this to share
6380 // their common bits.
6382 abstract public class PropertyBase : MethodCore {
6384 public class GetMethod: PropertyMethod
6386 static string[] attribute_targets = new string [] { "method", "return" };
6388 public GetMethod (MethodCore method):
6389 base (method, "get_")
6393 public GetMethod (MethodCore method, Accessor accessor):
6394 base (method, accessor, "get_")
6398 public override MethodBuilder Define(TypeContainer container)
6400 base.Define (container);
6402 method_data = new MethodData (method, method.ParameterInfo, ModFlags, flags, this);
6404 if (!method_data.Define (container))
6407 return method_data.MethodBuilder;
6410 public override Type ReturnType {
6412 return method.MemberType;
6416 public override string[] ValidAttributeTargets {
6418 return attribute_targets;
6423 public class SetMethod: PropertyMethod {
6425 static string[] attribute_targets = new string [] { "method", "param", "return" };
6426 ImplicitParameter param_attr;
6428 public SetMethod (MethodCore method):
6429 base (method, "set_")
6433 public SetMethod (MethodCore method, Accessor accessor):
6434 base (method, accessor, "set_")
6438 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
6440 if (a.Target == AttributeTargets.Parameter) {
6441 if (param_attr == null)
6442 param_attr = new ImplicitParameter (method_data.MethodBuilder, method.Location);
6444 param_attr.ApplyAttributeBuilder (a, cb);
6448 base.ApplyAttributeBuilder (a, cb);
6451 protected virtual InternalParameters GetParameterInfo (EmitContext ec)
6453 Parameter [] parms = new Parameter [1];
6454 parms [0] = new Parameter (method.Type, "value", Parameter.Modifier.NONE, null, method.Location);
6455 Parameters parameters = new Parameters (parms, null);
6457 bool old_unsafe = ec.InUnsafe;
6458 ec.InUnsafe = InUnsafe;
6459 Type [] types = parameters.GetParameterInfo (ec);
6460 ec.InUnsafe = old_unsafe;
6462 return new InternalParameters (types, parameters);
6465 public override MethodBuilder Define (TypeContainer container)
6467 if (container.EmitContext == null)
6468 throw new InternalErrorException ("SetMethod.Define called too early");
6470 base.Define (container);
6472 method_data = new MethodData (method, GetParameterInfo (container.EmitContext), ModFlags, flags, this);
6474 if (!method_data.Define (container))
6477 return method_data.MethodBuilder;
6480 public override Type[] ParameterTypes {
6482 return new Type[] { method.MemberType };
6486 public override Type ReturnType {
6488 return TypeManager.void_type;
6492 public override string[] ValidAttributeTargets {
6494 return attribute_targets;
6499 static string[] attribute_targets = new string [] { "property" };
6501 public abstract class PropertyMethod: AbstractPropertyEventMethod {
6502 protected readonly MethodCore method;
6503 protected MethodAttributes flags;
6506 public PropertyMethod (MethodCore method, string prefix)
6507 : base (method, prefix)
6509 this.method = method;
6512 public PropertyMethod (MethodCore method, Accessor accessor, string prefix)
6513 : base (method, accessor, prefix)
6515 this.method = method;
6516 this.ModFlags = accessor.ModFlags;
6517 yields = accessor.Yields;
6519 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
6520 Report.FeatureIsNotStandardized (Location, "access modifiers on properties");
6524 public override AttributeTargets AttributeTargets {
6526 return AttributeTargets.Method;
6530 public override bool IsClsComplianceRequired(DeclSpace ds)
6532 return method.IsClsComplianceRequired (ds);
6535 public InternalParameters ParameterInfo
6538 return method_data.ParameterInfo;
6542 public virtual MethodBuilder Define (TypeContainer container)
6544 if (!method.CheckAbstractAndExtern (block != null))
6548 // Check for custom access modifier
6550 if (ModFlags == 0) {
6551 ModFlags = method.ModFlags;
6552 flags = method.flags;
6554 if (container.Kind == Kind.Interface)
6555 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
6556 GetSignatureForError ());
6558 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
6559 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
6562 CheckModifiers (container, ModFlags);
6563 ModFlags |= (method.ModFlags & (~Modifiers.Accessibility));
6564 ModFlags |= Modifiers.PROPERTY_CUSTOM;
6565 flags = Modifiers.MethodAttr (ModFlags);
6566 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
6570 // Setup iterator if we are one
6573 Iterator iterator = new Iterator (
6574 this, Parent, null, method.ParameterInfo, ModFlags);
6576 if (!iterator.DefineIterator ())
6583 public bool HasCustomAccessModifier
6586 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
6590 public override Type[] ParameterTypes {
6592 return TypeManager.NoTypes;
6596 public override EmitContext CreateEmitContext (TypeContainer tc,
6599 return new EmitContext (
6600 tc, method.ds, method.Location, ig, ReturnType,
6601 method.ModFlags, false);
6604 public override ObsoleteAttribute GetObsoleteAttribute ()
6606 return method.GetObsoleteAttribute ();
6609 public override string GetSignatureForError()
6611 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
6614 void CheckModifiers (TypeContainer container, int modflags)
6617 int mflags = method.ModFlags & Modifiers.Accessibility;
6619 if ((mflags & Modifiers.PUBLIC) != 0) {
6620 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
6622 else if ((mflags & Modifiers.PROTECTED) != 0) {
6623 if ((mflags & Modifiers.INTERNAL) != 0)
6624 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
6626 flags |= Modifiers.PRIVATE;
6628 else if ((mflags & Modifiers.INTERNAL) != 0)
6629 flags |= Modifiers.PRIVATE;
6631 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
6632 Report.Error (273, Location,
6633 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
6634 GetSignatureForError (), method.GetSignatureForError ());
6638 public override bool MarkForDuplicationCheck ()
6640 caching_flags |= Flags.TestMethodDuplication;
6645 public PropertyMethod Get, Set;
6646 public PropertyBuilder PropertyBuilder;
6647 public MethodBuilder GetBuilder, SetBuilder;
6649 protected EmitContext ec;
6651 public PropertyBase (TypeContainer parent, Expression type, int mod_flags,
6652 int allowed_mod, bool is_iface, MemberName name,
6653 Parameters parameters, Attributes attrs)
6654 : base (parent, null, type, mod_flags, allowed_mod, is_iface, name,
6659 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
6661 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
6662 a.Error_InvalidSecurityParent ();
6666 PropertyBuilder.SetCustomAttribute (cb);
6669 public override AttributeTargets AttributeTargets {
6671 return AttributeTargets.Property;
6675 public override bool Define ()
6680 if (!IsTypePermitted ())
6686 protected override bool DoDefine ()
6688 if (!base.DoDefine ())
6692 // Accessors modifiers check
6694 if (Get.ModFlags != 0 && Set.ModFlags != 0) {
6695 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
6696 GetSignatureForError ());
6700 if ((Get.IsDummy || Set.IsDummy)
6701 && (Get.ModFlags != 0 || Set.ModFlags != 0) && (ModFlags & Modifiers.OVERRIDE) == 0) {
6702 Report.Error (276, Location,
6703 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
6704 GetSignatureForError ());
6708 if (MemberType.IsAbstract && MemberType.IsSealed) {
6709 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
6713 ec = new EmitContext (Parent, Location, null, MemberType, ModFlags);
6717 protected override bool CheckForDuplications ()
6719 ArrayList ar = Parent.Indexers;
6721 int arLen = ar.Count;
6723 for (int i = 0; i < arLen; i++) {
6724 Indexer m = (Indexer) ar [i];
6725 if (IsDuplicateImplementation (m))
6730 ar = Parent.Properties;
6732 int arLen = ar.Count;
6734 for (int i = 0; i < arLen; i++) {
6735 Property m = (Property) ar [i];
6736 if (IsDuplicateImplementation (m))
6744 // TODO: rename to Resolve......
6745 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
6747 PropertyInfo base_property = container.BaseCache.FindMemberToOverride (
6748 container.TypeBuilder, Name, ParameterTypes, null, true) as PropertyInfo;
6750 if (base_property == null)
6753 base_ret_type = base_property.PropertyType;
6754 MethodInfo get_accessor = base_property.GetGetMethod (true);
6755 MethodInfo set_accessor = base_property.GetSetMethod (true);
6756 MethodAttributes get_accessor_access, set_accessor_access;
6758 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
6759 if (Get != null && !Get.IsDummy && get_accessor == null) {
6760 Report.SymbolRelatedToPreviousError (base_property);
6761 Report.Error (545, Location, "`{0}.get': cannot override because `{1}' does not have an overridable get accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6764 if (Set != null && !Set.IsDummy && set_accessor == null) {
6765 Report.SymbolRelatedToPreviousError (base_property);
6766 Report.Error (546, Location, "`{0}.set': cannot override because `{1}' does not have an overridable set accessor", GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
6771 // Check base class accessors access
6774 // TODO: rewrite to reuse Get|Set.CheckAccessModifiers and share code there
6775 get_accessor_access = set_accessor_access = 0;
6776 if ((ModFlags & Modifiers.NEW) == 0) {
6777 if (get_accessor != null) {
6778 MethodAttributes get_flags = Modifiers.MethodAttr (Get.ModFlags != 0 ? Get.ModFlags : ModFlags);
6779 get_accessor_access = (get_accessor.Attributes & MethodAttributes.MemberAccessMask);
6781 if (!Get.IsDummy && !CheckAccessModifiers (get_flags & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
6782 Error_CannotChangeAccessModifiers (get_accessor, get_accessor_access, ".get");
6785 if (set_accessor != null) {
6786 MethodAttributes set_flags = Modifiers.MethodAttr (Set.ModFlags != 0 ? Set.ModFlags : ModFlags);
6787 set_accessor_access = (set_accessor.Attributes & MethodAttributes.MemberAccessMask);
6789 if (!Set.IsDummy && !CheckAccessModifiers (set_flags & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
6790 Error_CannotChangeAccessModifiers (set_accessor, set_accessor_access, ".set");
6795 // Get the less restrictive access
6797 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
6800 public override void Emit ()
6803 // The PropertyBuilder can be null for explicit implementations, in that
6804 // case, we do not actually emit the ".property", so there is nowhere to
6805 // put the attribute
6807 if (PropertyBuilder != null && OptAttributes != null)
6808 OptAttributes.Emit (ec, this);
6820 /// Tests whether accessors are not in collision with some method (CS0111)
6822 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
6824 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
6827 public override bool IsUsed
6833 return Get.IsUsed | Set.IsUsed;
6837 protected override void SetMemberName (MemberName new_name)
6839 base.SetMemberName (new_name);
6841 Get.UpdateName (this);
6842 Set.UpdateName (this);
6845 public override string[] ValidAttributeTargets {
6847 return attribute_targets;
6852 // Represents header string for documentation comment.
6854 public override string DocCommentHeader {
6855 get { return "P:"; }
6859 public class Property : PropertyBase {
6860 const int AllowedModifiers =
6863 Modifiers.PROTECTED |
6864 Modifiers.INTERNAL |
6868 Modifiers.OVERRIDE |
6869 Modifiers.ABSTRACT |
6872 Modifiers.METHOD_YIELDS |
6875 const int AllowedInterfaceModifiers =
6878 public Property (TypeContainer ds, Expression type, int mod, bool is_iface,
6879 MemberName name, Attributes attrs, Accessor get_block,
6881 : base (ds, type, mod,
6882 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
6883 is_iface, name, Parameters.EmptyReadOnlyParameters, attrs)
6885 if (get_block == null)
6886 Get = new GetMethod (this);
6888 Get = new GetMethod (this, get_block);
6890 if (set_block == null)
6891 Set = new SetMethod (this);
6893 Set = new SetMethod (this, set_block);
6896 public override bool Define ()
6898 if (!DoDefineBase ())
6901 if (!base.Define ())
6907 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
6910 GetBuilder = Get.Define (Parent);
6911 if (GetBuilder == null)
6916 SetBuilder = Set.Define (Parent);
6917 if (SetBuilder == null)
6920 SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
6923 // FIXME - PropertyAttributes.HasDefault ?
6925 PropertyAttributes prop_attr = PropertyAttributes.None;
6927 prop_attr |= PropertyAttributes.RTSpecialName |
6928 PropertyAttributes.SpecialName;
6930 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
6931 Name, prop_attr, MemberType, null);
6934 PropertyBuilder.SetGetMethod (GetBuilder);
6937 PropertyBuilder.SetSetMethod (SetBuilder);
6944 /// Gigantic workaround for lameness in SRE follows :
6945 /// This class derives from EventInfo and attempts to basically
6946 /// wrap around the EventBuilder so that FindMembers can quickly
6947 /// return this in it search for members
6949 public class MyEventBuilder : EventInfo {
6952 // We use this to "point" to our Builder which is
6953 // not really a MemberInfo
6955 EventBuilder MyBuilder;
6958 // We "catch" and wrap these methods
6960 MethodInfo raise, remove, add;
6962 EventAttributes attributes;
6963 Type declaring_type, reflected_type, event_type;
6968 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
6970 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
6972 // And now store the values in our own fields.
6974 declaring_type = type_builder;
6976 reflected_type = type_builder;
6978 attributes = event_attr;
6981 this.event_type = event_type;
6985 // Methods that you have to override. Note that you only need
6986 // to "implement" the variants that take the argument (those are
6987 // the "abstract" methods, the others (GetAddMethod()) are
6990 public override MethodInfo GetAddMethod (bool nonPublic)
6995 public override MethodInfo GetRemoveMethod (bool nonPublic)
7000 public override MethodInfo GetRaiseMethod (bool nonPublic)
7006 // These methods make "MyEventInfo" look like a Builder
7008 public void SetRaiseMethod (MethodBuilder raiseMethod)
7010 raise = raiseMethod;
7011 MyBuilder.SetRaiseMethod (raiseMethod);
7014 public void SetRemoveOnMethod (MethodBuilder removeMethod)
7016 remove = removeMethod;
7017 MyBuilder.SetRemoveOnMethod (removeMethod);
7020 public void SetAddOnMethod (MethodBuilder addMethod)
7023 MyBuilder.SetAddOnMethod (addMethod);
7026 public void SetCustomAttribute (CustomAttributeBuilder cb)
7028 MyBuilder.SetCustomAttribute (cb);
7031 public override object [] GetCustomAttributes (bool inherit)
7033 // FIXME : There's nothing which can be seemingly done here because
7034 // we have no way of getting at the custom attribute objects of the
7039 public override object [] GetCustomAttributes (Type t, bool inherit)
7041 // FIXME : Same here !
7045 public override bool IsDefined (Type t, bool b)
7050 public override EventAttributes Attributes {
7056 public override string Name {
7062 public override Type DeclaringType {
7064 return declaring_type;
7068 public override Type ReflectedType {
7070 return reflected_type;
7074 public Type EventType {
7080 public void SetUsed ()
7082 if (my_event != null) {
7083 my_event.SetAssigned ();
7084 my_event.SetMemberIsUsed ();
7090 /// For case when event is declared like property (with add and remove accessors).
7092 public class EventProperty: Event {
7094 static string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
7096 public EventProperty (TypeContainer parent, Expression type, int mod_flags,
7097 bool is_iface, MemberName name, Object init,
7098 Attributes attrs, Accessor add, Accessor remove)
7099 : base (parent, type, mod_flags, is_iface, name, init, attrs)
7101 Add = new AddDelegateMethod (this, add);
7102 Remove = new RemoveDelegateMethod (this, remove);
7104 // For this event syntax we don't report error CS0067
7105 // because it is hard to do it.
7109 public override string[] ValidAttributeTargets {
7111 return attribute_targets;
7117 /// Event is declared like field.
7119 public class EventField: Event {
7121 static string[] attribute_targets = new string [] { "event", "field", "method" };
7122 static string[] attribute_targets_interface = new string[] { "event", "method" };
7124 public EventField (TypeContainer parent, Expression type, int mod_flags,
7125 bool is_iface, MemberName name, Object init,
7127 : base (parent, type, mod_flags, is_iface, name, init, attrs)
7129 Add = new AddDelegateMethod (this);
7130 Remove = new RemoveDelegateMethod (this);
7133 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7135 if (a.Target == AttributeTargets.Field) {
7136 FieldBuilder.SetCustomAttribute (cb);
7140 if (a.Target == AttributeTargets.Method) {
7141 Add.ApplyAttributeBuilder (a, cb);
7142 Remove.ApplyAttributeBuilder (a, cb);
7146 base.ApplyAttributeBuilder (a, cb);
7149 public override string[] ValidAttributeTargets {
7151 return IsInterface ? attribute_targets_interface : attribute_targets;
7156 public abstract class Event : FieldBase {
7158 protected sealed class AddDelegateMethod: DelegateMethod
7161 public AddDelegateMethod (Event method):
7162 base (method, "add_")
7166 public AddDelegateMethod (Event method, Accessor accessor):
7167 base (method, accessor, "add_")
7171 protected override MethodInfo DelegateMethodInfo {
7173 return TypeManager.delegate_combine_delegate_delegate;
7179 protected sealed class RemoveDelegateMethod: DelegateMethod
7181 public RemoveDelegateMethod (Event method):
7182 base (method, "remove_")
7186 public RemoveDelegateMethod (Event method, Accessor accessor):
7187 base (method, accessor, "remove_")
7191 protected override MethodInfo DelegateMethodInfo {
7193 return TypeManager.delegate_remove_delegate_delegate;
7199 public abstract class DelegateMethod: AbstractPropertyEventMethod
7201 protected readonly Event method;
7202 ImplicitParameter param_attr;
7204 static string[] attribute_targets = new string [] { "method", "param", "return" };
7206 public DelegateMethod (Event method, string prefix)
7207 : base (method, prefix)
7209 this.method = method;
7212 public DelegateMethod (Event method, Accessor accessor, string prefix)
7213 : base (method, accessor, prefix)
7215 this.method = method;
7218 protected override void ApplyToExtraTarget(Attribute a, CustomAttributeBuilder cb)
7220 if (a.Target == AttributeTargets.Parameter) {
7221 if (param_attr == null)
7222 param_attr = new ImplicitParameter (method_data.MethodBuilder, method.Location);
7224 param_attr.ApplyAttributeBuilder (a, cb);
7228 base.ApplyAttributeBuilder (a, cb);
7231 public override AttributeTargets AttributeTargets {
7233 return AttributeTargets.Method;
7237 public override bool IsClsComplianceRequired(DeclSpace ds)
7239 return method.IsClsComplianceRequired (ds);
7242 public MethodBuilder Define (TypeContainer container, InternalParameters ip)
7244 method_data = new MethodData (method, ip, method.ModFlags,
7245 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
7247 if (!method_data.Define (container))
7250 MethodBuilder mb = method_data.MethodBuilder;
7251 mb.DefineParameter (1, ParameterAttributes.None, "value");
7256 protected override void EmitMethod (TypeContainer tc)
7258 if (block != null) {
7259 base.EmitMethod (tc);
7263 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
7266 ILGenerator ig = method_data.MethodBuilder.GetILGenerator ();
7267 FieldInfo field_info = (FieldInfo)method.FieldBuilder;
7269 method_data.MethodBuilder.SetImplementationFlags (MethodImplAttributes.Synchronized);
7270 if ((method.ModFlags & Modifiers.STATIC) != 0) {
7271 ig.Emit (OpCodes.Ldsfld, field_info);
7272 ig.Emit (OpCodes.Ldarg_0);
7273 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7274 ig.Emit (OpCodes.Castclass, method.MemberType);
7275 ig.Emit (OpCodes.Stsfld, field_info);
7277 ig.Emit (OpCodes.Ldarg_0);
7278 ig.Emit (OpCodes.Ldarg_0);
7279 ig.Emit (OpCodes.Ldfld, field_info);
7280 ig.Emit (OpCodes.Ldarg_1);
7281 ig.Emit (OpCodes.Call, DelegateMethodInfo);
7282 ig.Emit (OpCodes.Castclass, method.MemberType);
7283 ig.Emit (OpCodes.Stfld, field_info);
7285 ig.Emit (OpCodes.Ret);
7288 protected abstract MethodInfo DelegateMethodInfo { get; }
7290 public override Type[] ParameterTypes {
7292 return new Type[] { method.MemberType };
7296 public override Type ReturnType {
7298 return TypeManager.void_type;
7302 public override EmitContext CreateEmitContext (TypeContainer tc,
7305 return new EmitContext (
7306 tc, method.Parent, Location, ig, ReturnType,
7307 method.ModFlags, false);
7310 public override ObsoleteAttribute GetObsoleteAttribute ()
7312 return method.GetObsoleteAttribute ();
7315 public override string[] ValidAttributeTargets {
7317 return attribute_targets;
7323 const int AllowedModifiers =
7326 Modifiers.PROTECTED |
7327 Modifiers.INTERNAL |
7332 Modifiers.OVERRIDE |
7336 const int AllowedInterfaceModifiers =
7339 public DelegateMethod Add, Remove;
7340 public MyEventBuilder EventBuilder;
7341 public MethodBuilder AddBuilder, RemoveBuilder;
7343 public Event (TypeContainer parent, Expression type, int mod_flags,
7344 bool is_iface, MemberName name, Object init, Attributes attrs)
7345 : base (parent, type, mod_flags,
7346 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7349 IsInterface = is_iface;
7352 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7354 if (a.Type.IsSubclassOf (TypeManager.security_attr_type)) {
7355 a.Error_InvalidSecurityParent ();
7359 EventBuilder.SetCustomAttribute (cb);
7362 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
7364 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
7367 public override AttributeTargets AttributeTargets {
7369 return AttributeTargets.Event;
7373 public override bool Define ()
7375 EventAttributes e_attr;
7376 e_attr = EventAttributes.None;
7378 if (!DoDefineBase ())
7384 if (init != null && ((ModFlags & Modifiers.ABSTRACT) != 0)){
7385 Report.Error (74, Location, "`" + GetSignatureForError () +
7386 "': abstract event cannot have an initializer");
7390 if (!TypeManager.IsDelegateType (MemberType)) {
7391 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
7395 EmitContext ec = Parent.EmitContext;
7397 throw new InternalErrorException ("Event.Define called too early?");
7398 bool old_unsafe = ec.InUnsafe;
7399 ec.InUnsafe = InUnsafe;
7401 Parameter [] parms = new Parameter [1];
7402 parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null, Location);
7403 Parameters parameters = new Parameters (parms, null);
7404 Type [] types = parameters.GetParameterInfo (ec);
7405 InternalParameters ip = new InternalParameters (types, parameters);
7407 ec.InUnsafe = old_unsafe;
7413 // Now define the accessors
7416 AddBuilder = Add.Define (Parent, ip);
7417 if (AddBuilder == null)
7420 RemoveBuilder = Remove.Define (Parent, ip);
7421 if (RemoveBuilder == null)
7424 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, e_attr, MemberType);
7426 if (Add.Block == null && Remove.Block == null && !IsInterface) {
7427 FieldBuilder = Parent.TypeBuilder.DefineField (
7429 FieldAttributes.Private | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
7430 TypeManager.RegisterPrivateFieldOfEvent (
7431 (EventInfo) EventBuilder, FieldBuilder);
7432 TypeManager.RegisterFieldBase (FieldBuilder, this);
7435 EventBuilder.SetAddOnMethod (AddBuilder);
7436 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
7438 TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder);
7442 protected override bool CheckBase ()
7444 if (!base.CheckBase ())
7447 if (conflict_symbol != null && (ModFlags & Modifiers.NEW) == 0) {
7448 if (!(conflict_symbol is EventInfo)) {
7449 Report.SymbolRelatedToPreviousError (conflict_symbol);
7450 Report.Error (72, Location, "Event `{0}' can override only event", GetSignatureForError ());
7458 public override void Emit ()
7460 if (OptAttributes != null) {
7461 EmitContext ec = new EmitContext (
7462 Parent, Location, null, MemberType, ModFlags);
7463 OptAttributes.Emit (ec, this);
7467 Remove.Emit (Parent);
7472 public override string GetSignatureForError ()
7474 return base.GetSignatureForError ();
7478 // Represents header string for documentation comment.
7480 public override string DocCommentHeader {
7481 get { return "E:"; }
7486 public class Indexer : PropertyBase, IIteratorContainer {
7488 class GetIndexerMethod: GetMethod
7490 public GetIndexerMethod (MethodCore method):
7495 public GetIndexerMethod (MethodCore method, Accessor accessor):
7496 base (method, accessor)
7500 public override Type[] ParameterTypes {
7502 return method.ParameterTypes;
7507 class SetIndexerMethod: SetMethod
7509 readonly Parameters parameters;
7511 public SetIndexerMethod (MethodCore method):
7516 public SetIndexerMethod (MethodCore method, Parameters parameters, Accessor accessor):
7517 base (method, accessor)
7519 this.parameters = parameters;
7522 public override Type[] ParameterTypes {
7524 int top = method.ParameterTypes.Length;
7525 Type [] set_pars = new Type [top + 1];
7526 method.ParameterTypes.CopyTo (set_pars, 0);
7527 set_pars [top] = method.MemberType;
7532 protected override InternalParameters GetParameterInfo (EmitContext ec)
7534 Parameter [] fixed_parms = parameters.FixedParameters;
7536 if (fixed_parms == null){
7537 throw new Exception ("We currently do not support only array arguments in an indexer at: " + method.Location);
7538 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7539 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7541 // Here is the problem: the `value' parameter has
7542 // to come *after* the array parameter in the declaration
7544 // X (object [] x, Type value)
7547 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7548 // BUG BUG BUG BUG BUG BUG BUG BUG BUG BUG
7552 Parameter [] tmp = new Parameter [fixed_parms.Length + 1];
7554 fixed_parms.CopyTo (tmp, 0);
7555 tmp [fixed_parms.Length] = new Parameter (
7556 method.Type, "value", Parameter.Modifier.NONE, null, method.Location);
7558 Parameters set_formal_params = new Parameters (tmp, null);
7559 Type [] types = set_formal_params.GetParameterInfo (ec);
7561 return new InternalParameters (types, set_formal_params);
7565 const int AllowedModifiers =
7568 Modifiers.PROTECTED |
7569 Modifiers.INTERNAL |
7573 Modifiers.OVERRIDE |
7578 const int AllowedInterfaceModifiers =
7582 // Are we implementing an interface ?
7584 public Indexer (TypeContainer parent, Expression type, MemberName name, int mod,
7585 bool is_iface, Parameters parameters, Attributes attrs,
7586 Accessor get_block, Accessor set_block)
7587 : base (parent, type, mod,
7588 is_iface ? AllowedInterfaceModifiers : AllowedModifiers,
7589 is_iface, name, parameters, attrs)
7591 if (get_block == null)
7592 Get = new GetIndexerMethod (this);
7594 Get = new GetIndexerMethod (this, get_block);
7596 if (set_block == null)
7597 Set = new SetIndexerMethod (this);
7599 Set = new SetIndexerMethod (this, parameters, set_block);
7602 public override bool Define ()
7604 PropertyAttributes prop_attr =
7605 PropertyAttributes.RTSpecialName |
7606 PropertyAttributes.SpecialName;
7608 if (!DoDefineBase ())
7611 if (!base.Define ())
7614 if (MemberType == TypeManager.void_type) {
7615 Report.Error (620, Location, "Indexers cannot have void type");
7619 if (OptAttributes != null) {
7620 Attribute indexer_attr = OptAttributes.Search (TypeManager.indexer_name_type, ec);
7621 if (indexer_attr != null) {
7622 // Remove the attribute from the list because it is not emitted
7623 OptAttributes.Attrs.Remove (indexer_attr);
7625 ShortName = indexer_attr.GetIndexerAttributeValue (ec);
7627 if (IsExplicitImpl) {
7628 Report.Error (415, indexer_attr.Location,
7629 "The `IndexerName' attribute is valid only on an " +
7630 "indexer that is not an explicit interface member declaration");
7634 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
7635 Report.Error (609, indexer_attr.Location,
7636 "Cannot set the `IndexerName' attribute on an indexer marked override");
7640 if (!Tokenizer.IsValidIdentifier (ShortName)) {
7641 Report.Error (633, indexer_attr.Location,
7642 "The argument to the `IndexerName' attribute must be a valid identifier");
7648 if (InterfaceType != null) {
7649 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
7650 if (base_IndexerName != Name)
7651 ShortName = base_IndexerName;
7654 if (!Parent.AddToMemberContainer (this) ||
7655 !Parent.AddToMemberContainer (Get) || !Parent.AddToMemberContainer (Set))
7661 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
7663 GetBuilder = Get.Define (Parent);
7664 if (GetBuilder == null)
7668 // Setup iterator if we are one
7670 if ((ModFlags & Modifiers.METHOD_YIELDS) != 0){
7671 Iterator iterator = new Iterator (
7672 Get, Parent, null, Get.ParameterInfo, ModFlags);
7674 if (!iterator.DefineIterator ())
7680 SetBuilder = Set.Define (Parent);
7681 if (SetBuilder == null)
7686 // Now name the parameters
7688 Parameter [] p = Parameters.FixedParameters;
7690 if ((p [0].ModFlags & Parameter.Modifier.ISBYREF) != 0) {
7691 Report.Error (631, Location, "ref and out are not valid in this context");
7697 for (i = 0; i < p.Length; ++i) {
7699 GetBuilder.DefineParameter (
7700 i + 1, p [i].Attributes, p [i].Name);
7703 SetBuilder.DefineParameter (
7704 i + 1, p [i].Attributes, p [i].Name);
7708 SetBuilder.DefineParameter (
7709 i + 1, ParameterAttributes.None, "value");
7711 if (i != ParameterTypes.Length) {
7712 Parameter array_param = Parameters.ArrayParameter;
7714 SetBuilder.DefineParameter (
7715 i + 1, array_param.Attributes, array_param.Name);
7719 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
7720 Name, prop_attr, MemberType, ParameterTypes);
7723 PropertyBuilder.SetGetMethod (GetBuilder);
7726 PropertyBuilder.SetSetMethod (SetBuilder);
7728 TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder, ParameterTypes);
7733 public override string GetSignatureForError ()
7735 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
7736 if (MemberName.Left != null) {
7738 sb.Append (MemberName.Left);
7741 sb.Append (".this");
7742 sb.Append (Parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
7743 return sb.ToString ();
7746 public override bool MarkForDuplicationCheck ()
7748 caching_flags |= Flags.TestMethodDuplication;
7753 public class Operator : MethodCore, IIteratorContainer {
7755 const int AllowedModifiers =
7761 public enum OpType : byte {
7771 // Unary and Binary operators
7794 // Implicit and Explicit
7798 // Just because of enum
7802 public readonly OpType OperatorType;
7803 public MethodBuilder OperatorMethodBuilder;
7805 public Method OperatorMethod;
7807 static string[] attribute_targets = new string [] { "method", "return" };
7809 public Operator (TypeContainer parent, OpType type, Expression ret_type,
7810 int mod_flags, Parameters parameters,
7811 ToplevelBlock block, Attributes attrs, Location loc)
7812 : base (parent, null, ret_type, mod_flags, AllowedModifiers, false,
7813 new MemberName ("op_" + type, loc), attrs, parameters)
7815 OperatorType = type;
7819 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb)
7821 OperatorMethod.ApplyAttributeBuilder (a, cb);
7824 public override AttributeTargets AttributeTargets {
7826 return AttributeTargets.Method;
7830 protected override bool CheckGenericOverride (MethodInfo method, string name)
7835 protected override bool CheckForDuplications()
7837 ArrayList ar = Parent.Operators;
7839 int arLen = ar.Count;
7841 for (int i = 0; i < arLen; i++) {
7842 Operator o = (Operator) ar [i];
7843 if (IsDuplicateImplementation (o))
7848 ar = Parent.Methods;
7850 int arLen = ar.Count;
7852 for (int i = 0; i < arLen; i++) {
7853 Method m = (Method) ar [i];
7854 if (IsDuplicateImplementation (m))
7862 public override bool Define ()
7864 const int RequiredModifiers = Modifiers.PUBLIC | Modifiers.STATIC;
7865 if ((ModFlags & RequiredModifiers) != RequiredModifiers){
7866 Report.Error (558, Location, "User-defined operator `{0}' must be declared static and public", GetSignatureForError ());
7873 if (MemberType == TypeManager.void_type) {
7874 Report.Error (590, Location, "User-defined operators cannot return void");
7878 OperatorMethod = new Method (
7879 Parent, null, Type, ModFlags, false, MemberName,
7880 Parameters, OptAttributes);
7882 OperatorMethod.Block = Block;
7883 OperatorMethod.IsOperator = this;
7884 OperatorMethod.flags |= MethodAttributes.SpecialName | MethodAttributes.HideBySig;
7885 OperatorMethod.Define ();
7887 if (OperatorMethod.MethodBuilder == null)
7890 OperatorMethodBuilder = OperatorMethod.MethodBuilder;
7892 parameter_types = OperatorMethod.ParameterTypes;
7893 Type declaring_type = OperatorMethod.MethodData.DeclaringType;
7894 Type return_type = OperatorMethod.ReturnType;
7895 Type first_arg_type = parameter_types [0];
7900 // Rules for conversion operators
7902 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
7903 if (first_arg_type == return_type && first_arg_type == declaring_type){
7904 Report.Error (555, Location,
7905 "User-defined operator cannot take an object of the enclosing type and convert to an object of the enclosing type");
7909 if (first_arg_type != declaring_type && return_type != declaring_type){
7912 "User-defined conversion must convert to or from the " +
7917 if (first_arg_type == TypeManager.object_type ||
7918 return_type == TypeManager.object_type){
7921 "User-defined conversion cannot convert to or from " +
7926 if (first_arg_type.IsInterface || return_type.IsInterface){
7927 Report.Error (552, Location, "User-defined conversion `{0}' cannot convert to or from an interface type",
7928 GetSignatureForError ());
7932 if (first_arg_type.IsSubclassOf (return_type)
7933 || return_type.IsSubclassOf (first_arg_type)){
7934 if (declaring_type.IsSubclassOf (return_type)) {
7935 Report.Error (553, Location, "User-defined conversion `{0}' cannot convert to or from base class",
7936 GetSignatureForError ());
7939 Report.Error (554, Location, "User-defined conversion `{0}' cannot convert to or from derived class",
7940 GetSignatureForError ());
7943 } else if (OperatorType == OpType.LeftShift || OperatorType == OpType.RightShift) {
7944 if (first_arg_type != declaring_type || parameter_types [1] != TypeManager.int32_type) {
7945 Report.Error (564, Location, "Overloaded shift operator must have the type of the first operand be the containing type, and the type of the second operand must be int");
7948 } else if (Parameters.FixedParameters.Length == 1) {
7949 // Checks for Unary operators
7951 if (OperatorType == OpType.Increment || OperatorType == OpType.Decrement) {
7952 if (return_type != declaring_type && !return_type.IsSubclassOf (declaring_type)) {
7953 Report.Error (448, Location,
7954 "The return type for ++ or -- operator must be the containing type or derived from the containing type");
7957 if (first_arg_type != declaring_type){
7959 559, Location, "The parameter type for ++ or -- operator must be the containing type");
7964 if (first_arg_type != declaring_type){
7967 "The parameter of a unary operator must be the " +
7972 if (OperatorType == OpType.True || OperatorType == OpType.False) {
7973 if (return_type != TypeManager.bool_type){
7976 "The return type of operator True or False " +
7983 if (OperatorType == OpType.BitwiseAnd &&
7984 (first_arg_type != return_type || first_arg_type != parameter_types [1])) {
7985 Report.Error (217, Location, "In order to be applicable as a short circuit operator a user-defined logical operator ('{0}') " +
7986 "must have the same return type as the type of its 2 parameters", GetSignatureForError ());
7990 // Checks for Binary operators
7992 if (first_arg_type != declaring_type &&
7993 parameter_types [1] != declaring_type){
7996 "One of the parameters of a binary operator must " +
7997 "be the containing type");
8005 public override void Emit ()
8008 // abstract or extern methods have no bodies
8010 if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
8013 OperatorMethod.Emit ();
8017 // Operator cannot be override
8018 protected override MethodInfo FindOutBaseMethod (TypeContainer container, ref Type base_ret_type)
8023 public static string GetName (OpType ot)
8026 case OpType.LogicalNot:
8028 case OpType.OnesComplement:
8030 case OpType.Increment:
8032 case OpType.Decrement:
8038 case OpType.Addition:
8040 case OpType.Subtraction:
8042 case OpType.UnaryPlus:
8044 case OpType.UnaryNegation:
8046 case OpType.Multiply:
8048 case OpType.Division:
8050 case OpType.Modulus:
8052 case OpType.BitwiseAnd:
8054 case OpType.BitwiseOr:
8056 case OpType.ExclusiveOr:
8058 case OpType.LeftShift:
8060 case OpType.RightShift:
8062 case OpType.Equality:
8064 case OpType.Inequality:
8066 case OpType.GreaterThan:
8068 case OpType.LessThan:
8070 case OpType.GreaterThanOrEqual:
8072 case OpType.LessThanOrEqual:
8074 case OpType.Implicit:
8076 case OpType.Explicit:
8082 public static OpType GetOperatorType (string name)
8084 if (name.StartsWith ("op_")){
8085 for (int i = 0; i < Unary.oper_names.Length; ++i) {
8086 if (Unary.oper_names [i] == name)
8090 for (int i = 0; i < Binary.oper_names.Length; ++i) {
8091 if (Binary.oper_names [i] == name)
8098 public override string GetSignatureForError ()
8100 StringBuilder sb = new StringBuilder ();
8101 if (OperatorType == OpType.Implicit || OperatorType == OpType.Explicit) {
8102 sb.AppendFormat ("{0}.{1} operator {2}", Parent.GetSignatureForError (), GetName (OperatorType), Type.Type == null ? Type.ToString () : TypeManager.CSharpName (Type.Type));
8105 sb.AppendFormat ("{0}.operator {1}", Parent.GetSignatureForError (), GetName (OperatorType));
8108 sb.Append (Parameters.GetSignatureForError ());
8109 return sb.ToString ();
8112 public override bool MarkForDuplicationCheck ()
8114 caching_flags |= Flags.TestMethodDuplication;
8118 public override string[] ValidAttributeTargets {
8120 return attribute_targets;
8126 // This is used to compare method signatures
8128 struct MethodSignature {
8130 public Type RetType;
8131 public Type [] Parameters;
8134 /// This delegate is used to extract methods which have the
8135 /// same signature as the argument
8137 public static MemberFilter method_signature_filter = new MemberFilter (MemberSignatureCompare);
8139 public MethodSignature (string name, Type ret_type, Type [] parameters)
8144 if (parameters == null)
8145 Parameters = TypeManager.NoTypes;
8147 Parameters = parameters;
8150 public override string ToString ()
8153 if (Parameters.Length != 0){
8154 System.Text.StringBuilder sb = new System.Text.StringBuilder ();
8155 for (int i = 0; i < Parameters.Length; i++){
8156 sb.Append (Parameters [i]);
8157 if (i+1 < Parameters.Length)
8160 pars = sb.ToString ();
8163 return String.Format ("{0} {1} ({2})", RetType, Name, pars);
8166 public override int GetHashCode ()
8168 return Name.GetHashCode ();
8171 public override bool Equals (Object o)
8173 MethodSignature other = (MethodSignature) o;
8175 if (other.Name != Name)
8178 if (other.RetType != RetType)
8181 if (Parameters == null){
8182 if (other.Parameters == null)
8187 if (other.Parameters == null)
8190 int c = Parameters.Length;
8191 if (other.Parameters.Length != c)
8194 for (int i = 0; i < c; i++)
8195 if (other.Parameters [i] != Parameters [i])
8201 static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
8203 MethodSignature sig = (MethodSignature) filter_criteria;
8205 if (m.Name != sig.Name)
8209 MethodInfo mi = m as MethodInfo;
8210 PropertyInfo pi = m as PropertyInfo;
8213 ReturnType = mi.ReturnType;
8214 else if (pi != null)
8215 ReturnType = pi.PropertyType;
8220 // we use sig.RetType == null to mean `do not check the
8221 // method return value.
8223 if (sig.RetType != null)
8224 if (ReturnType != sig.RetType)
8229 args = TypeManager.GetArgumentTypes (mi);
8231 args = TypeManager.GetArgumentTypes (pi);
8232 Type [] sigp = sig.Parameters;
8234 if (args.Length != sigp.Length)
8237 for (int i = args.Length; i > 0; ){
8239 if (args [i] != sigp [i])