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 // Dual licensed under the terms of the MIT X11 or GNU GPL
10 // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com)
11 // Copyright 2004-2008 Novell, Inc
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.CompilerServices;
19 using System.Runtime.InteropServices;
20 using System.Security;
21 using System.Security.Permissions;
25 using XmlElement = System.Object;
30 using Mono.CompilerServices.SymbolWriter;
32 namespace Mono.CSharp {
44 /// This is the base class for structs and classes.
46 public abstract class TypeContainer : DeclSpace, IMemberContainer
49 // Different context is needed when resolving type container base
50 // types. Type names come from the parent scope but type parameter
51 // names from the container scope.
53 struct BaseContext : IMemberContext
57 public BaseContext (TypeContainer tc)
62 #region IMemberContext Members
64 public CompilerContext Compiler {
65 get { return tc.Compiler; }
68 public Type CurrentType {
69 get { return tc.Parent.CurrentType; }
72 public TypeParameter[] CurrentTypeParameters {
73 get { return tc.PartialContainer.CurrentTypeParameters; }
76 public TypeContainer CurrentTypeDefinition {
77 get { return tc.Parent.CurrentTypeDefinition; }
80 public bool IsObsolete {
81 get { return tc.IsObsolete; }
84 public bool IsUnsafe {
85 get { return tc.IsUnsafe; }
88 public bool IsStatic {
89 get { return tc.IsStatic; }
92 public string GetSignatureForError ()
94 throw new NotImplementedException ();
97 public ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
102 public FullNamedExpression LookupNamespaceAlias (string name)
104 return tc.Parent.LookupNamespaceAlias (name);
107 public FullNamedExpression LookupNamespaceOrType (string name, Location loc, bool ignore_cs0104)
109 TypeParameter[] tp = CurrentTypeParameters;
111 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
113 return new TypeParameterExpr (t, loc);
116 return tc.Parent.LookupNamespaceOrType (name, loc, ignore_cs0104);
126 GetHashCode = 1 << 1,
127 HasStaticFieldInitializer = 1 << 2
131 // Whether this is a struct, class or interface
132 public readonly Kind Kind;
134 // Holds a list of classes and structures
135 protected List<TypeContainer> types;
137 List<MemberCore> ordered_explicit_member_list;
138 List<MemberCore> ordered_member_list;
140 // Holds the list of properties
141 List<MemberCore> properties;
143 // Holds the list of delegates
144 List<TypeContainer> delegates;
146 // Holds the list of constructors
147 protected List<MemberCore> instance_constructors;
149 // Holds the list of fields
150 protected List<MemberCore> fields;
152 // Holds a list of fields that have initializers
153 protected List<FieldInitializer> initialized_fields;
155 // Holds a list of static fields that have initializers
156 protected List<FieldInitializer> initialized_static_fields;
158 // Holds the list of constants
159 protected List<MemberCore> constants;
161 // Holds the methods.
162 List<MemberCore> methods;
165 protected List<MemberCore> events;
167 // Holds the indexers
168 List<MemberCore> indexers;
170 // Holds the operators
171 List<MemberCore> operators;
173 // Holds the compiler generated classes
174 List<CompilerGeneratedClass> compiler_generated;
177 // Pointers to the default constructor and the default static constructor
179 protected Constructor default_constructor;
180 protected Constructor default_static_constructor;
183 // Points to the first non-static field added to the container.
185 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
186 // and the first one's as good as any.
188 FieldBase first_nonstatic_field = null;
191 // This one is computed after we can distinguish interfaces
192 // from classes from the arraylist `type_bases'
195 TypeExpr[] iface_exprs;
197 GenericTypeParameterBuilder[] nested_gen_params;
199 protected List<FullNamedExpression> type_bases;
201 protected bool members_defined;
202 bool members_defined_ok;
204 // The interfaces we implement.
205 protected Type[] ifaces;
207 // The base member cache and our member cache
208 MemberCache base_cache;
209 protected MemberCache member_cache;
211 public const string DefaultIndexerName = "Item";
213 private bool seen_normal_indexers = false;
214 private string indexer_name = DefaultIndexerName;
215 protected bool requires_delayed_unmanagedtype_check;
217 private CachedMethods cached_method;
219 List<TypeContainer> partial_parts;
222 /// The pending methods that need to be implemented
223 // (interfaces or abstract methods)
225 PendingImplementation pending;
227 public TypeContainer (NamespaceEntry ns, DeclSpace parent, MemberName name,
228 Attributes attrs, Kind kind)
229 : base (ns, parent, name, attrs)
231 if (parent != null && parent.NamespaceEntry != ns)
232 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
235 this.PartialContainer = this;
238 public bool AddMember (MemberCore symbol)
240 return AddToContainer (symbol, symbol.MemberName.Basename);
243 protected virtual bool AddMemberType (DeclSpace ds)
245 return AddToContainer (ds, ds.Basename);
248 protected virtual void RemoveMemberType (DeclSpace ds)
250 RemoveFromContainer (ds.Basename);
253 public void AddConstant (Const constant)
255 if (!AddMember (constant))
258 if (constants == null)
259 constants = new List<MemberCore> ();
261 constants.Add (constant);
264 public TypeContainer AddTypeContainer (TypeContainer tc)
266 if (!AddMemberType (tc))
270 types = new List<TypeContainer> ();
276 public virtual TypeContainer AddPartial (TypeContainer next_part)
278 return AddPartial (next_part, next_part.Basename);
281 protected TypeContainer AddPartial (TypeContainer next_part, string name)
283 next_part.ModFlags |= Modifiers.PARTIAL;
284 TypeContainer tc = GetDefinition (name) as TypeContainer;
286 return AddTypeContainer (next_part);
288 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
289 Report.SymbolRelatedToPreviousError (next_part);
290 Error_MissingPartialModifier (tc);
293 if (tc.Kind != next_part.Kind) {
294 Report.SymbolRelatedToPreviousError (tc);
295 Report.Error (261, next_part.Location,
296 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
297 next_part.GetSignatureForError ());
300 if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
301 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
302 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
303 Report.SymbolRelatedToPreviousError (tc);
304 Report.Error (262, next_part.Location,
305 "Partial declarations of `{0}' have conflicting accessibility modifiers",
306 next_part.GetSignatureForError ());
309 if (tc.partial_parts == null)
310 tc.partial_parts = new List<TypeContainer> (1);
312 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
313 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
314 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
315 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
316 tc.ModFlags |= next_part.ModFlags;
318 tc.ModFlags |= next_part.ModFlags;
321 if (next_part.attributes != null) {
322 if (tc.attributes == null)
323 tc.attributes = next_part.attributes;
325 tc.attributes.AddAttributes (next_part.attributes.Attrs);
328 next_part.PartialContainer = tc;
329 tc.partial_parts.Add (next_part);
333 public virtual void RemoveTypeContainer (TypeContainer next_part)
336 types.Remove (next_part);
337 RemoveMemberType (next_part);
340 public void AddDelegate (Delegate d)
342 if (!AddMemberType (d))
345 if (delegates == null)
346 delegates = new List<TypeContainer> ();
351 private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
353 if (ordered_explicit_member_list == null) {
354 ordered_explicit_member_list = new List<MemberCore> ();
355 ordered_member_list = new List<MemberCore> ();
359 if (Kind == Kind.Interface) {
360 Report.Error (541, mc.Location,
361 "`{0}': explicit interface declaration can only be declared in a class or struct",
362 mc.GetSignatureForError ());
365 ordered_explicit_member_list.Add (mc);
366 alist.Insert (0, mc);
368 ordered_member_list.Add (mc);
374 public void AddMethod (MethodOrOperator method)
376 if (!AddToContainer (method, method.MemberName.Basename))
380 methods = new List<MemberCore> ();
382 if (method.MemberName.Left != null)
383 AddMemberToList (method, methods, true);
385 AddMemberToList (method, methods, false);
388 public void AddConstructor (Constructor c)
390 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
391 if (!AddToContainer (c, is_static ?
392 ConstructorBuilder.ConstructorName : ConstructorBuilder.TypeConstructorName))
395 if (is_static && c.Parameters.IsEmpty){
396 if (default_static_constructor != null) {
397 Report.SymbolRelatedToPreviousError (default_static_constructor);
398 Report.Error (111, c.Location,
399 "A member `{0}' is already defined. Rename this member or use different parameter types",
400 c.GetSignatureForError ());
404 default_static_constructor = c;
406 if (c.Parameters.IsEmpty)
407 default_constructor = c;
409 if (instance_constructors == null)
410 instance_constructors = new List<MemberCore> ();
412 instance_constructors.Add (c);
416 public bool AddField (FieldBase field)
418 if (!AddMember (field))
422 fields = new List<MemberCore> ();
426 if ((field.ModFlags & Modifiers.STATIC) != 0)
429 if (first_nonstatic_field == null) {
430 first_nonstatic_field = field;
434 if (Kind == Kind.Struct && first_nonstatic_field.Parent != field.Parent) {
435 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
436 Report.Warning (282, 3, field.Location,
437 "struct instance field `{0}' found in different declaration from instance field `{1}'",
438 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
443 public void AddProperty (Property prop)
445 if (!AddMember (prop) ||
446 !AddMember (prop.Get) || !AddMember (prop.Set))
449 if (properties == null)
450 properties = new List<MemberCore> ();
452 if (prop.MemberName.Left != null)
453 AddMemberToList (prop, properties, true);
455 AddMemberToList (prop, properties, false);
458 public void AddEvent (Event e)
463 if (e is EventProperty) {
464 if (!AddMember (e.Add))
467 if (!AddMember (e.Remove))
472 events = new List<MemberCore> ();
478 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
480 public void AddIndexer (Indexer i)
482 if (indexers == null)
483 indexers = new List<MemberCore> ();
485 if (i.IsExplicitImpl)
486 AddMemberToList (i, indexers, true);
488 AddMemberToList (i, indexers, false);
491 public void AddOperator (Operator op)
496 if (operators == null)
497 operators = new List<MemberCore> ();
502 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
504 Report.Debug (64, "ADD COMPILER GENERATED CLASS", this, c);
506 if (compiler_generated == null)
507 compiler_generated = new List<CompilerGeneratedClass> ();
509 compiler_generated.Add (c);
512 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
514 if (a.Type == pa.DefaultMember) {
515 if (Indexers != null) {
516 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
521 base.ApplyAttributeBuilder (a, cb, pa);
524 public override AttributeTargets AttributeTargets {
526 throw new NotSupportedException ();
530 public IList<TypeContainer> Types {
536 public IList<MemberCore> Methods {
542 public IList<MemberCore> Constants {
548 protected virtual Type BaseType {
550 return TypeBuilder.BaseType;
554 public IList<MemberCore> Fields {
560 public IList<MemberCore> InstanceConstructors {
562 return instance_constructors;
566 public IList<MemberCore> Properties {
572 public IList<MemberCore> Events {
578 public IList<MemberCore> Indexers {
584 public IList<MemberCore> Operators {
590 public IList<TypeContainer> Delegates {
596 protected override TypeAttributes TypeAttr {
598 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel) | base.TypeAttr;
602 public string IndexerName {
604 return indexers == null ? DefaultIndexerName : indexer_name;
608 public bool IsComImport {
610 if (OptAttributes == null)
613 return OptAttributes.Contains (PredefinedAttributes.Get.ComImport);
617 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
619 if ((field.ModFlags & Modifiers.STATIC) != 0){
620 if (initialized_static_fields == null) {
621 PartialContainer.HasStaticFieldInitializer = true;
622 initialized_static_fields = new List<FieldInitializer> (4);
625 initialized_static_fields.Add (expression);
627 if (initialized_fields == null)
628 initialized_fields = new List<FieldInitializer> (4);
630 initialized_fields.Add (expression);
634 public void ResolveFieldInitializers (BlockContext ec)
636 if (partial_parts != null) {
637 foreach (TypeContainer part in partial_parts) {
638 part.DoResolveFieldInitializers (ec);
641 DoResolveFieldInitializers (ec);
644 void DoResolveFieldInitializers (BlockContext ec)
647 if (initialized_static_fields == null)
650 bool has_complex_initializer = !RootContext.Optimize;
652 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
653 for (i = 0; i < initialized_static_fields.Count; ++i) {
654 FieldInitializer fi = initialized_static_fields [i];
655 ExpressionStatement s = fi.ResolveStatement (ec);
657 s = EmptyExpressionStatement.Instance;
658 } else if (fi.IsComplexInitializer) {
659 has_complex_initializer |= true;
665 for (i = 0; i < initialized_static_fields.Count; ++i) {
666 FieldInitializer fi = initialized_static_fields [i];
668 // Need special check to not optimize code like this
669 // static int a = b = 5;
672 if (!has_complex_initializer && fi.IsDefaultInitializer)
675 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
681 if (initialized_fields == null)
684 for (int i = 0; i < initialized_fields.Count; ++i) {
685 FieldInitializer fi = (FieldInitializer) initialized_fields [i];
686 ExpressionStatement s = fi.ResolveStatement (ec);
691 // Field is re-initialized to its default value => removed
693 if (fi.IsDefaultInitializer && RootContext.Optimize)
696 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
700 public override string DocComment {
712 public PendingImplementation PendingImplementations {
713 get { return pending; }
716 public override bool GetClsCompliantAttributeValue ()
718 if (PartialContainer != this)
719 return PartialContainer.GetClsCompliantAttributeValue ();
721 return base.GetClsCompliantAttributeValue ();
724 public virtual void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
726 // FIXME: get rid of partial_parts and store lists of bases of each part here
727 // assumed, not verified: 'part' is in 'partial_parts'
728 ((TypeContainer) part).type_bases = bases;
732 /// This function computes the Base class and also the
733 /// list of interfaces that the class or struct @c implements.
735 /// The return value is an array (might be null) of
736 /// interfaces implemented (as Types).
738 /// The @base_class argument is set to the base object or null
739 /// if this is `System.Object'.
741 protected virtual TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
744 if (type_bases == null)
747 int count = type_bases.Count;
748 TypeExpr [] ifaces = null;
749 IMemberContext base_context = new BaseContext (this);
750 for (int i = 0, j = 0; i < count; i++){
751 FullNamedExpression fne = (FullNamedExpression) type_bases [i];
754 // Standard ResolveAsTypeTerminal cannot be used in this case because
755 // it does ObsoleteAttribute and constraint checks which require
756 // base type to be set
758 TypeExpr fne_resolved = fne.ResolveAsBaseTerminal (base_context, false);
759 if (fne_resolved == null)
762 if (i == 0 && Kind == Kind.Class && !fne_resolved.Type.IsInterface) {
763 if (fne_resolved is DynamicTypeExpr)
764 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
765 GetSignatureForError ());
767 base_class = fne_resolved;
772 ifaces = new TypeExpr [count - i];
774 if (fne_resolved.Type.IsInterface) {
775 for (int ii = 0; ii < j; ++ii) {
776 if (TypeManager.IsEqual (fne_resolved.Type, ifaces [ii].Type)) {
777 Report.Error (528, Location, "`{0}' is already listed in interface list",
778 fne_resolved.GetSignatureForError ());
783 if (Kind == Kind.Interface && !IsAccessibleAs (fne_resolved.Type)) {
784 Report.Error (61, fne.Location,
785 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
786 fne_resolved.GetSignatureForError (), GetSignatureForError ());
789 Report.SymbolRelatedToPreviousError (fne_resolved.Type);
790 if (Kind != Kind.Class) {
791 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
792 } else if (base_class != null)
793 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
794 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
796 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
797 GetSignatureForError (), fne_resolved.GetSignatureForError ());
801 ifaces [j++] = fne_resolved;
807 TypeExpr[] GetNormalPartialBases (ref TypeExpr base_class)
809 var ifaces = new List<TypeExpr> (0);
810 if (iface_exprs != null)
811 ifaces.AddRange (iface_exprs);
813 foreach (TypeContainer part in partial_parts) {
814 TypeExpr new_base_class;
815 TypeExpr[] new_ifaces = part.ResolveBaseTypes (out new_base_class);
816 if (new_base_class != TypeManager.system_object_expr) {
817 if (base_class == TypeManager.system_object_expr)
818 base_class = new_base_class;
820 if (new_base_class != null && !TypeManager.IsEqual (new_base_class.Type, base_class.Type)) {
821 Report.SymbolRelatedToPreviousError (base_class.Location, "");
822 Report.Error (263, part.Location,
823 "Partial declarations of `{0}' must not specify different base classes",
824 part.GetSignatureForError ());
831 if (new_ifaces == null)
834 foreach (TypeExpr iface in new_ifaces) {
835 if (ifaces.Contains (iface))
842 if (ifaces.Count == 0)
845 return ifaces.ToArray ();
849 // Checks that some operators come in pairs:
855 // They are matched based on the return type and the argument types
857 void CheckPairedOperators ()
859 bool has_equality_or_inequality = false;
860 var operators = this.operators.ToArray ();
861 bool[] has_pair = new bool[operators.Length];
863 for (int i = 0; i < operators.Length; ++i) {
864 if (operators[i] == null)
867 Operator o_a = (Operator) operators[i];
868 Operator.OpType o_type = o_a.OperatorType;
869 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
870 has_equality_or_inequality = true;
872 Operator.OpType matching_type = o_a.GetMatchingOperator ();
873 if (matching_type == Operator.OpType.TOP) {
878 for (int ii = 0; ii < operators.Length; ++ii) {
879 Operator o_b = (Operator) operators[ii];
880 if (o_b == null || o_b.OperatorType != matching_type)
883 if (!TypeManager.IsEqual (o_a.ReturnType, o_b.ReturnType))
886 if (!TypeManager.IsEqual (o_a.ParameterTypes, o_b.ParameterTypes))
892 // Used to ignore duplicate user conversions
898 for (int i = 0; i < operators.Length; ++i) {
899 if (operators[i] == null || has_pair[i])
902 Operator o = (Operator) operators [i];
903 Report.Error (216, o.Location,
904 "The operator `{0}' requires a matching operator `{1}' to also be defined",
905 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
908 if (has_equality_or_inequality) {
909 if (Methods == null || !HasEquals)
910 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
911 GetSignatureForError ());
913 if (Methods == null || !HasGetHashCode)
914 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
915 GetSignatureForError ());
919 bool CheckGenericInterfaces (Type[] ifaces)
921 var already_checked = new List<Type> ();
923 for (int i = 0; i < ifaces.Length; i++) {
924 Type iface = ifaces [i];
925 foreach (Type t in already_checked) {
929 Type[] inferred = new Type [CountTypeParameters];
930 if (!TypeManager.MayBecomeEqualGenericInstances (iface, t, inferred, null))
933 Report.Error (695, Location,
934 "`{0}' cannot implement both `{1}' and `{2}' " +
935 "because they may unify for some type parameter substitutions",
936 TypeManager.CSharpName (TypeBuilder), TypeManager.CSharpName (iface),
937 TypeManager.CSharpName (t));
941 already_checked.Add (iface);
949 bool CreateTypeBuilder ()
952 Type default_parent = null;
953 if (Kind == Kind.Struct)
954 default_parent = TypeManager.value_type;
955 else if (Kind == Kind.Enum)
956 default_parent = TypeManager.enum_type;
957 else if (Kind == Kind.Delegate)
958 default_parent = TypeManager.multicast_delegate_type;
961 // Sets .size to 1 for structs with no instance fields
963 int type_size = Kind == Kind.Struct && first_nonstatic_field == null ? 1 : 0;
966 if (GlobalRootNamespace.Instance.IsNamespace (Name)) {
967 Report.Error (519, Location, "`{0}' clashes with a predefined namespace", Name);
971 ModuleBuilder builder = Module.Compiled.Builder;
972 TypeBuilder = builder.DefineType (
973 Name, TypeAttr, default_parent, type_size);
975 TypeBuilder builder = Parent.TypeBuilder;
977 TypeBuilder = builder.DefineNestedType (
978 Basename, TypeAttr, default_parent, type_size);
980 } catch (ArgumentException) {
981 Report.RuntimeMissingSupport (Location, "static classes");
985 TypeManager.AddUserType (this);
988 string[] param_names = new string [TypeParameters.Length];
989 for (int i = 0; i < TypeParameters.Length; i++)
990 param_names [i] = TypeParameters [i].Name;
992 GenericTypeParameterBuilder[] gen_params = TypeBuilder.DefineGenericParameters (param_names);
994 int offset = CountTypeParameters;
995 if (CurrentTypeParameters != null)
996 offset -= CurrentTypeParameters.Length;
999 nested_gen_params = new GenericTypeParameterBuilder [offset];
1000 Array.Copy (gen_params, nested_gen_params, offset);
1003 for (int i = offset; i < gen_params.Length; i++)
1004 CurrentTypeParameters [i - offset].Define (gen_params [i]);
1010 bool DefineBaseTypes ()
1012 iface_exprs = ResolveBaseTypes (out base_type);
1013 if (partial_parts != null) {
1014 iface_exprs = GetNormalPartialBases (ref base_type);
1018 // GetClassBases calls ResolveBaseTypeExpr() on the various type expressions involved,
1019 // which in turn should have called DefineType()s on base types if necessary.
1021 // None of the code below should trigger DefineType()s on classes that we depend on.
1022 // Thus, we are eligible to be on the topological sort `type_container_resolve_order'.
1024 // Let's do it as soon as possible, since code below can call DefineType() on classes
1025 // that depend on us to be populated before they are.
1027 if (!(this is CompilerGeneratedClass) && !(this is Delegate))
1028 RootContext.RegisterOrder (this);
1030 if (!CheckRecursiveDefinition (this))
1033 if (base_type != null && base_type.Type != null) {
1034 TypeBuilder.SetParent (base_type.Type);
1037 // add interfaces that were not added at type creation
1038 if (iface_exprs != null) {
1039 ifaces = TypeManager.ExpandInterfaces (iface_exprs);
1043 foreach (Type itype in ifaces)
1044 TypeBuilder.AddInterfaceImplementation (itype);
1046 if (!CheckGenericInterfaces (ifaces))
1049 TypeManager.RegisterBuilder (TypeBuilder, ifaces);
1056 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1058 public TypeBuilder CreateType ()
1060 if (TypeBuilder != null)
1066 if (!CreateTypeBuilder ()) {
1071 if (partial_parts != null) {
1072 foreach (TypeContainer part in partial_parts)
1073 part.TypeBuilder = TypeBuilder;
1076 if (Types != null) {
1077 foreach (TypeContainer tc in Types) {
1078 if (tc.CreateType () == null) {
1090 public override TypeBuilder DefineType ()
1097 type_defined = true;
1099 if (CreateType () == null) {
1104 if (!DefineBaseTypes ()) {
1109 if (!DefineNestedTypes ()) {
1117 public override void SetParameterInfo (List<Constraints> constraints_list)
1119 base.SetParameterInfo (constraints_list);
1121 if (!is_generic || PartialContainer == this)
1124 TypeParameter[] tc_names = PartialContainer.TypeParameters;
1125 for (int i = 0; i < tc_names.Length; ++i) {
1126 if (tc_names [i].Name != type_params [i].Name) {
1127 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1128 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1129 GetSignatureForError ());
1133 if (tc_names [i].Variance != type_params [i].Variance) {
1134 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1135 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1136 GetSignatureForError ());
1142 void UpdateTypeParameterConstraints (TypeContainer part)
1144 TypeParameter[] current_params = type_params;
1145 for (int i = 0; i < current_params.Length; i++) {
1146 Constraints c = part.type_params [i].Constraints;
1150 if (current_params [i].UpdateConstraints (part, c))
1153 Report.SymbolRelatedToPreviousError (Location, "");
1154 Report.Error (265, part.Location,
1155 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1156 GetSignatureForError (), current_params [i].GetSignatureForError ());
1160 public bool ResolveType ()
1162 if (!DoResolveType ())
1165 if (compiler_generated != null) {
1166 foreach (CompilerGeneratedClass c in compiler_generated)
1167 if (!c.ResolveType ())
1174 protected virtual bool DoResolveType ()
1179 if (PartialContainer != this)
1180 throw new InternalErrorException ();
1182 TypeExpr current_type = null;
1183 if (CurrentTypeParameters != null) {
1184 foreach (TypeParameter type_param in CurrentTypeParameters) {
1185 if (!type_param.Resolve (this)) {
1191 if (partial_parts != null) {
1192 foreach (TypeContainer part in partial_parts)
1193 UpdateTypeParameterConstraints (part);
1197 for (int i = 0; i < TypeParameters.Length; ++i) {
1199 // FIXME: Same should be done for delegates
1200 // TODO: Quite ugly way how to propagate constraints to
1203 if (nested_gen_params != null && i < nested_gen_params.Length) {
1204 TypeParameters [i].SetConstraints (nested_gen_params [i]);
1206 if (!TypeParameters [i].DefineType (this)) {
1213 // TODO: Very strange, why not simple make generic type from
1214 // current type parameters
1215 current_type = new GenericTypeExpr (this, Location);
1216 current_type = current_type.ResolveAsTypeTerminal (this, false);
1217 if (current_type == null) {
1222 currentType = current_type.Type;
1226 protected virtual bool DefineNestedTypes ()
1228 if (Types != null) {
1229 foreach (TypeContainer tc in Types)
1230 if (tc.DefineType () == null)
1234 if (Delegates != null) {
1235 foreach (Delegate d in Delegates)
1236 if (d.DefineType () == null)
1243 TypeContainer InTransit;
1245 protected bool CheckRecursiveDefinition (TypeContainer tc)
1247 if (InTransit != null) {
1248 Report.SymbolRelatedToPreviousError (this);
1249 if (this is Interface)
1251 529, tc.Location, "Inherited interface `{0}' causes a " +
1252 "cycle in the interface hierarchy of `{1}'",
1253 GetSignatureForError (), tc.GetSignatureForError ());
1256 146, tc.Location, "Circular base class dependency " +
1257 "involving `{0}' and `{1}'",
1258 tc.GetSignatureForError (), GetSignatureForError ());
1264 if (base_type != null && base_type.Type != null) {
1265 Type t = TypeManager.DropGenericTypeArguments (base_type.Type);
1266 TypeContainer ptc = TypeManager.LookupTypeContainer (t);
1267 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1271 if (iface_exprs != null) {
1272 foreach (TypeExpr iface in iface_exprs) {
1273 Type itype = TypeManager.DropGenericTypeArguments (iface.Type);
1274 TypeContainer ptc = TypeManager.LookupTypeContainer (itype);
1275 if ((ptc != null) && !ptc.CheckRecursiveDefinition (this))
1280 if (!IsTopLevel && !Parent.PartialContainer.CheckRecursiveDefinition (this))
1287 public override TypeParameter[] CurrentTypeParameters {
1289 return PartialContainer.type_params;
1294 /// Populates our TypeBuilder with fields and methods
1296 public sealed override bool Define ()
1298 if (members_defined)
1299 return members_defined_ok;
1301 members_defined_ok = DoDefineMembers ();
1302 members_defined = true;
1304 return members_defined_ok;
1307 protected virtual bool DoDefineMembers ()
1309 if (iface_exprs != null) {
1310 foreach (TypeExpr iface in iface_exprs) {
1311 ObsoleteAttribute oa = AttributeTester.GetObsoleteAttribute (iface.Type);
1312 if ((oa != null) && !IsObsolete)
1313 AttributeTester.Report_ObsoleteMessage (
1314 oa, iface.GetSignatureForError (), Location, Report);
1316 GenericTypeExpr ct = iface as GenericTypeExpr;
1318 // TODO: passing `this' is wrong, should be base type iface instead
1319 TypeManager.CheckTypeVariance (ct.Type, Variance.Covariant, this);
1321 if (!ct.CheckConstraints (this))
1324 if (ct.HasDynamicArguments ()) {
1325 Report.Error (1966, iface.Location,
1326 "`{0}': cannot implement a dynamic interface `{1}'",
1327 GetSignatureForError (), iface.GetSignatureForError ());
1334 if (base_type != null) {
1335 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (base_type.Type);
1336 if (obsolete_attr != null && !IsObsolete)
1337 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), Location, Report);
1339 GenericTypeExpr ct = base_type as GenericTypeExpr;
1340 if ((ct != null) && !ct.CheckConstraints (this))
1343 TypeContainer baseContainer = TypeManager.LookupTypeContainer(base_type.Type);
1344 if (baseContainer != null)
1345 baseContainer.Define();
1347 member_cache = new MemberCache (base_type.Type, this);
1348 } else if (Kind == Kind.Interface) {
1349 member_cache = new MemberCache (null, this);
1350 Type [] ifaces = TypeManager.GetInterfaces (TypeBuilder);
1351 for (int i = 0; i < ifaces.Length; ++i)
1352 member_cache.AddInterface (TypeManager.LookupMemberCache (ifaces [i]));
1354 member_cache = new MemberCache (null, this);
1358 foreach (TypeContainer tc in types)
1359 member_cache.AddNestedType (tc);
1361 if (delegates != null)
1362 foreach (Delegate d in delegates)
1363 member_cache.AddNestedType (d);
1365 if (partial_parts != null) {
1366 foreach (TypeContainer part in partial_parts)
1367 part.member_cache = member_cache;
1371 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Basename, false);
1372 if (conflict_symbol == null) {
1373 if ((ModFlags & Modifiers.NEW) != 0)
1374 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
1376 if ((ModFlags & Modifiers.NEW) == 0) {
1377 Report.SymbolRelatedToPreviousError (conflict_symbol);
1378 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1379 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
1384 DefineContainerMembers (constants);
1385 DefineContainerMembers (fields);
1387 if (Kind == Kind.Struct || Kind == Kind.Class) {
1388 pending = PendingImplementation.GetPendingImplementations (this);
1390 if (requires_delayed_unmanagedtype_check) {
1391 requires_delayed_unmanagedtype_check = false;
1392 foreach (FieldBase f in fields) {
1393 if (f.MemberType != null && f.MemberType.IsPointer)
1394 TypeManager.VerifyUnmanaged (Compiler, f.MemberType, f.Location);
1400 // Constructors are not in the defined_names array
1402 DefineContainerMembers (instance_constructors);
1404 DefineContainerMembers (events);
1405 DefineContainerMembers (ordered_explicit_member_list);
1406 DefineContainerMembers (ordered_member_list);
1408 if (operators != null) {
1409 DefineContainerMembers (operators);
1410 CheckPairedOperators ();
1413 DefineContainerMembers (delegates);
1415 ComputeIndexerName();
1416 CheckEqualsAndGetHashCode();
1418 if (CurrentType != null) {
1419 GenericType = CurrentType;
1423 // FIXME: This hack is needed because member cache does not work
1424 // with generic types, we rely on runtime to inflate dynamic types.
1425 // TODO: This hack requires member cache refactoring to be removed
1427 if (TypeManager.IsGenericType (TypeBuilder))
1428 member_cache = new MemberCache (this);
1433 protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
1436 foreach (MemberCore mc in mcal) {
1439 } catch (Exception e) {
1440 throw new InternalErrorException (mc, e);
1446 protected virtual void ComputeIndexerName ()
1448 if (indexers == null)
1451 string class_indexer_name = null;
1454 // If there's both an explicit and an implicit interface implementation, the
1455 // explicit one actually implements the interface while the other one is just
1456 // a normal indexer. See bug #37714.
1459 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1460 foreach (Indexer i in indexers) {
1461 if (i.InterfaceType != null) {
1462 if (seen_normal_indexers)
1463 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1467 seen_normal_indexers = true;
1469 if (class_indexer_name == null) {
1470 class_indexer_name = i.ShortName;
1474 if (i.ShortName != class_indexer_name)
1475 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");
1478 if (class_indexer_name != null)
1479 indexer_name = class_indexer_name;
1482 protected virtual void EmitIndexerName ()
1484 if (!seen_normal_indexers)
1487 PredefinedAttribute pa = PredefinedAttributes.Get.DefaultMember;
1488 if (pa.Constructor == null &&
1489 !pa.ResolveConstructor (Location, TypeManager.string_type))
1492 CustomAttributeBuilder cb = new CustomAttributeBuilder (pa.Constructor, new string [] { IndexerName });
1493 TypeBuilder.SetCustomAttribute (cb);
1496 protected virtual void CheckEqualsAndGetHashCode ()
1498 if (methods == null)
1501 if (HasEquals && !HasGetHashCode) {
1502 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1506 public MemberInfo FindBaseMemberWithSameName (string name, bool ignore_methods)
1508 return BaseCache == null ? null : BaseCache.FindMemberWithSameName (name, ignore_methods, null);
1512 /// This function is based by a delegate to the FindMembers routine
1514 static bool AlwaysAccept (MemberInfo m, object filterCriteria)
1520 /// This filter is used by FindMembers, and we just keep
1521 /// a global for the filter to `AlwaysAccept'
1523 static MemberFilter accepting_filter;
1526 static TypeContainer ()
1528 accepting_filter = new MemberFilter (AlwaysAccept);
1531 public MethodInfo[] GetMethods ()
1533 var members = new List<MethodInfo> ();
1537 if (methods != null) {
1538 int len = methods.Count;
1539 for (int i = 0; i < len; i++) {
1540 Method m = (Method) methods [i];
1542 members.Add (m.MethodBuilder);
1546 if (operators != null) {
1547 int len = operators.Count;
1548 for (int i = 0; i < len; i++) {
1549 Operator o = (Operator) operators [i];
1551 members.Add (o.MethodBuilder);
1555 if (properties != null) {
1556 int len = properties.Count;
1557 for (int i = 0; i < len; i++) {
1558 Property p = (Property) properties [i];
1560 if (p.GetBuilder != null)
1561 members.Add (p.GetBuilder);
1562 if (p.SetBuilder != null)
1563 members.Add (p.SetBuilder);
1567 if (indexers != null) {
1568 int len = indexers.Count;
1569 for (int i = 0; i < len; i++) {
1570 Indexer ix = (Indexer) indexers [i];
1572 if (ix.GetBuilder != null)
1573 members.Add (ix.GetBuilder);
1574 if (ix.SetBuilder != null)
1575 members.Add (ix.SetBuilder);
1579 if (events != null) {
1580 int len = events.Count;
1581 for (int i = 0; i < len; i++) {
1582 Event e = (Event) events [i];
1584 if (e.AddBuilder != null)
1585 members.Add (e.AddBuilder);
1586 if (e.RemoveBuilder != null)
1587 members.Add (e.RemoveBuilder);
1591 return members.ToArray ();
1594 // Indicated whether container has StructLayout attribute set Explicit
1595 public bool HasExplicitLayout {
1596 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1597 set { caching_flags |= Flags.HasExplicitLayout; }
1600 public bool HasStructLayout {
1601 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1602 set { caching_flags |= Flags.HasStructLayout; }
1606 // Return the nested type with name @name. Ensures that the nested type
1607 // is defined if necessary. Do _not_ use this when you have a MemberCache handy.
1609 public Type FindNestedType (string name)
1611 if (PartialContainer != this)
1612 throw new InternalErrorException ("should not happen");
1614 var lists = new[] { types, delegates };
1616 for (int j = 0; j < lists.Length; ++j) {
1617 var list = lists [j];
1621 int len = list.Count;
1622 for (int i = 0; i < len; ++i) {
1624 if (ds.Basename == name) {
1625 return ds.DefineType ();
1633 private void FindMembers_NestedTypes (Modifiers modflags,
1634 BindingFlags bf, MemberFilter filter, object criteria,
1635 ref List<MemberInfo> members)
1637 var lists = new[] { types, delegates };
1639 for (int j = 0; j < lists.Length; ++j) {
1640 var list = lists [j];
1644 int len = list.Count;
1645 for (int i = 0; i < len; i++) {
1648 if ((ds.ModFlags & modflags) == 0)
1651 TypeBuilder tb = ds.TypeBuilder;
1653 if (!(criteria is string) || ds.Basename.Equals (criteria))
1654 tb = ds.DefineType ();
1657 if (tb != null && (filter (tb, criteria) == true)) {
1658 if (members == null)
1659 members = new List<MemberInfo> ();
1668 /// This method returns the members of this type just like Type.FindMembers would
1669 /// Only, we need to use this for types which are _being_ defined because MS'
1670 /// implementation can't take care of that.
1673 // FIXME: return an empty static array instead of null, that cleans up
1674 // some code and is consistent with some coding conventions I just found
1678 // Notice that in various cases we check if our field is non-null,
1679 // something that would normally mean that there was a bug elsewhere.
1681 // The problem happens while we are defining p-invoke methods, as those
1682 // will trigger a FindMembers, but this happens before things are defined
1684 // Since the whole process is a no-op, it is fine to check for null here.
1686 // TODO: This approach will be one day completely removed, it's already
1687 // used at few places only
1690 public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
1691 MemberFilter filter, object criteria)
1693 List<MemberInfo> members = null;
1695 Modifiers modflags = 0;
1696 if ((bf & BindingFlags.Public) != 0)
1697 modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
1699 if ((bf & BindingFlags.NonPublic) != 0)
1700 modflags |= Modifiers.PRIVATE;
1702 Modifiers static_mask = 0, static_flags = 0;
1703 switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
1704 case BindingFlags.Static:
1705 static_mask = static_flags = Modifiers.STATIC;
1708 case BindingFlags.Instance:
1709 static_mask = Modifiers.STATIC;
1714 static_mask = static_flags = 0;
1718 Timer.StartTimer (TimerType.TcFindMembers);
1721 filter = accepting_filter;
1723 if ((mt & MemberTypes.Field) != 0) {
1724 if (fields != null) {
1725 int len = fields.Count;
1726 for (int i = 0; i < len; i++) {
1727 FieldBase f = (FieldBase) fields [i];
1729 if ((f.ModFlags & modflags) == 0)
1731 if ((f.ModFlags & static_mask) != static_flags)
1734 FieldBuilder fb = f.FieldBuilder;
1735 if (fb != null && filter (fb, criteria) == true) {
1736 if (members == null)
1737 members = new List<MemberInfo> ();
1744 if (constants != null) {
1745 int len = constants.Count;
1746 for (int i = 0; i < len; i++) {
1747 Const con = (Const) constants [i];
1749 if ((con.ModFlags & modflags) == 0)
1751 if ((con.ModFlags & static_mask) != static_flags)
1754 FieldBuilder fb = con.FieldBuilder;
1756 // Define parent and not member, otherwise membercache can be null
1757 if (con.Parent.Define ())
1758 fb = con.FieldBuilder;
1760 if (fb != null && filter (fb, criteria) == true) {
1761 if (members == null)
1762 members = new List<MemberInfo> ();
1770 if ((mt & MemberTypes.Method) != 0) {
1771 if (methods != null) {
1772 int len = methods.Count;
1773 for (int i = 0; i < len; i++) {
1774 MethodOrOperator m = (MethodOrOperator) methods [i];
1776 if ((m.ModFlags & modflags) == 0)
1778 if ((m.ModFlags & static_mask) != static_flags)
1781 MethodBuilder mb = m.MethodBuilder;
1783 if (mb != null && filter (mb, criteria) == true) {
1784 if (members == null)
1785 members = new List<MemberInfo> ();
1792 if (operators != null) {
1793 int len = operators.Count;
1794 for (int i = 0; i < len; i++) {
1795 Operator o = (Operator) operators [i];
1797 if ((o.ModFlags & modflags) == 0)
1799 if ((o.ModFlags & static_mask) != static_flags)
1802 MethodBuilder ob = o.MethodBuilder;
1803 if (ob != null && filter (ob, criteria) == true) {
1804 if (members == null)
1805 members = new List<MemberInfo> ();
1812 if (events != null) {
1813 foreach (Event e in events) {
1814 if ((e.ModFlags & modflags) == 0)
1816 if ((e.ModFlags & static_mask) != static_flags)
1819 MethodBuilder b = e.AddBuilder;
1820 if (b != null && filter (b, criteria)) {
1821 if (members == null)
1822 members = new List<MemberInfo> ();
1827 b = e.RemoveBuilder;
1828 if (b != null && filter (b, criteria)) {
1829 if (members == null)
1830 members = new List<MemberInfo> ();
1837 if (properties != null) {
1838 int len = properties.Count;
1839 for (int i = 0; i < len; i++) {
1840 Property p = (Property) properties [i];
1842 if ((p.ModFlags & modflags) == 0)
1844 if ((p.ModFlags & static_mask) != static_flags)
1850 if (b != null && filter (b, criteria) == true) {
1851 if (members == null)
1852 members = new List<MemberInfo> ();
1858 if (b != null && filter (b, criteria) == true) {
1859 if (members == null)
1860 members = new List<MemberInfo> ();
1867 if (indexers != null) {
1868 int len = indexers.Count;
1869 for (int i = 0; i < len; i++) {
1870 Indexer ix = (Indexer) indexers [i];
1872 if ((ix.ModFlags & modflags) == 0)
1874 if ((ix.ModFlags & static_mask) != static_flags)
1880 if (b != null && filter (b, criteria) == true) {
1881 if (members == null)
1882 members = new List<MemberInfo> ();
1888 if (b != null && filter (b, criteria) == true) {
1889 if (members == null)
1890 members = new List<MemberInfo> ();
1898 if ((mt & MemberTypes.Event) != 0) {
1899 if (events != null) {
1900 int len = events.Count;
1901 for (int i = 0; i < len; i++) {
1902 Event e = (Event) events [i];
1904 if ((e.ModFlags & modflags) == 0)
1906 if ((e.ModFlags & static_mask) != static_flags)
1909 MemberInfo eb = e.EventBuilder;
1910 if (eb != null && filter (eb, criteria) == true) {
1911 if (members == null)
1912 members = new List<MemberInfo> ();
1914 members.Add (e.EventBuilder);
1920 if ((mt & MemberTypes.Property) != 0){
1921 if (properties != null) {
1922 int len = properties.Count;
1923 for (int i = 0; i < len; i++) {
1924 Property p = (Property) properties [i];
1926 if ((p.ModFlags & modflags) == 0)
1928 if ((p.ModFlags & static_mask) != static_flags)
1931 MemberInfo pb = p.PropertyBuilder;
1932 if (pb != null && filter (pb, criteria) == true) {
1933 if (members == null)
1934 members = new List<MemberInfo> ();
1936 members.Add (p.PropertyBuilder);
1941 if (indexers != null) {
1942 int len = indexers.Count;
1943 for (int i = 0; i < len; i++) {
1944 Indexer ix = (Indexer) indexers [i];
1946 if ((ix.ModFlags & modflags) == 0)
1948 if ((ix.ModFlags & static_mask) != static_flags)
1951 MemberInfo ib = ix.PropertyBuilder;
1952 if (ib != null && filter (ib, criteria) == true) {
1953 if (members == null)
1954 members = new List<MemberInfo> ();
1956 members.Add (ix.PropertyBuilder);
1962 if ((mt & MemberTypes.NestedType) != 0)
1963 FindMembers_NestedTypes (modflags, bf, filter, criteria, ref members);
1965 if ((mt & MemberTypes.Constructor) != 0){
1966 if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
1967 int len = instance_constructors.Count;
1968 for (int i = 0; i < len; i++) {
1969 Constructor c = (Constructor) instance_constructors [i];
1971 ConstructorBuilder cb = c.ConstructorBuilder;
1972 if (cb != null && filter (cb, criteria) == true) {
1973 if (members == null)
1974 members = new List<MemberInfo> ();
1981 if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
1982 ConstructorBuilder cb =
1983 default_static_constructor.ConstructorBuilder;
1985 if (cb != null && filter (cb, criteria) == true) {
1986 if (members == null)
1987 members = new List<MemberInfo> ();
1995 // Lookup members in base if requested.
1997 if ((bf & BindingFlags.DeclaredOnly) == 0) {
1998 if (TypeBuilder.BaseType != null) {
1999 MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
2000 if (list.Count > 0) {
2001 if (members == null)
2002 members = new List<MemberInfo> ();
2004 members.AddRange (list);
2009 Timer.StopTimer (TimerType.TcFindMembers);
2011 if (members == null)
2012 return MemberList.Empty;
2014 return new MemberList (members);
2017 public override MemberCache MemberCache {
2019 return member_cache;
2023 public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
2024 MemberFilter filter, object criteria)
2026 DeclSpace ds = TypeManager.LookupDeclSpace (t);
2029 return ds.FindMembers (mt, bf, filter, criteria);
2031 return new MemberList (t.FindMembers (mt, bf, filter, criteria));
2035 /// Emits the values for the constants
2037 public void EmitConstants ()
2039 if (constants != null)
2040 foreach (Const con in constants)
2045 void CheckMemberUsage (List<MemberCore> al, string member_type)
2050 foreach (MemberCore mc in al) {
2051 if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
2054 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
2055 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
2060 public virtual void VerifyMembers ()
2063 // Check for internal or private fields that were never assigned
2065 if (Report.WarningLevel >= 3) {
2066 CheckMemberUsage (properties, "property");
2067 CheckMemberUsage (methods, "method");
2068 CheckMemberUsage (constants, "constant");
2070 if (fields != null){
2071 bool is_type_exposed = Kind == Kind.Struct || IsExposedFromAssembly ();
2072 foreach (FieldBase f in fields) {
2073 if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2074 if (is_type_exposed)
2077 f.SetMemberIsUsed ();
2081 if ((f.caching_flags & Flags.IsAssigned) == 0)
2082 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
2084 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
2085 f.GetSignatureForError ());
2091 // Only report 649 on level 4
2093 if (Report.WarningLevel < 4)
2096 if ((f.caching_flags & Flags.IsAssigned) != 0)
2100 // Don't be pendatic over serializable attributes
2102 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2105 Constant c = New.Constantify (f.MemberType);
2106 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value `{1}'",
2107 f.GetSignatureForError (), c == null ? "null" : c.AsString ());
2113 // TODO: move to ClassOrStruct
2114 void EmitConstructors ()
2116 if (instance_constructors == null)
2119 if (TypeBuilder.IsSubclassOf (TypeManager.attribute_type) && RootContext.VerifyClsCompliance && IsClsComplianceRequired ()) {
2120 bool has_compliant_args = false;
2122 foreach (Constructor c in instance_constructors) {
2126 catch (Exception e) {
2127 throw new InternalErrorException (c, e);
2130 if (has_compliant_args)
2133 has_compliant_args = c.HasCompliantArgs;
2135 if (!has_compliant_args)
2136 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2138 foreach (Constructor c in instance_constructors) {
2142 catch (Exception e) {
2143 throw new InternalErrorException (c, e);
2150 /// Emits the code, this step is performed after all
2151 /// the types, enumerations, constructors
2153 public virtual void EmitType ()
2155 if (OptAttributes != null)
2156 OptAttributes.Emit ();
2160 EmitConstructors ();
2162 // Can not continue if constants are broken
2164 if (Report.Errors > 0)
2167 if (default_static_constructor != null)
2168 default_static_constructor.Emit ();
2170 if (operators != null)
2171 foreach (Operator o in operators)
2174 if (properties != null)
2175 foreach (Property p in properties)
2178 if (indexers != null) {
2179 foreach (Indexer indx in indexers)
2184 if (events != null){
2185 foreach (Event e in Events)
2189 if (methods != null) {
2190 for (int i = 0; i < methods.Count; ++i)
2191 ((MethodOrOperator) methods [i]).Emit ();
2195 foreach (FieldBase f in fields)
2198 if (delegates != null) {
2199 foreach (Delegate d in Delegates) {
2204 if (pending != null)
2205 pending.VerifyPendingMethods (Report);
2207 if (Report.Errors > 0)
2210 if (compiler_generated != null) {
2211 for (int i = 0; i < compiler_generated.Count; ++i)
2212 ((CompilerGeneratedClass) compiler_generated [i]).EmitType ();
2216 public override void CloseType ()
2218 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2222 caching_flags |= Flags.CloseTypeCreated;
2223 TypeBuilder.CreateType ();
2224 } catch (TypeLoadException){
2226 // This is fine, the code still created the type
2228 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2229 // Console.WriteLine (e.Message);
2230 } catch (Exception e) {
2231 throw new InternalErrorException (this, e);
2235 foreach (TypeContainer tc in Types)
2236 if (tc.Kind == Kind.Struct)
2239 foreach (TypeContainer tc in Types)
2240 if (tc.Kind != Kind.Struct)
2244 if (Delegates != null)
2245 foreach (Delegate d in Delegates)
2248 if (compiler_generated != null)
2249 foreach (CompilerGeneratedClass c in compiler_generated)
2252 PartialContainer = null;
2254 // properties = null;
2257 initialized_fields = null;
2258 initialized_static_fields = null;
2260 ordered_explicit_member_list = null;
2261 ordered_member_list = null;
2266 compiler_generated = null;
2267 default_constructor = null;
2268 default_static_constructor = null;
2270 OptAttributes = null;
2273 member_cache = null;
2277 // Performs the validation on a Method's modifiers (properties have
2278 // the same properties).
2280 public bool MethodModifiersValid (MemberCore mc)
2282 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2283 const Modifiers va = (Modifiers.VIRTUAL | Modifiers.ABSTRACT);
2284 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2286 var flags = mc.ModFlags;
2289 // At most one of static, virtual or override
2291 if ((flags & Modifiers.STATIC) != 0){
2292 if ((flags & vao) != 0){
2293 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2294 mc.GetSignatureForError ());
2299 if (Kind == Kind.Struct){
2300 if ((flags & va) != 0){
2301 ModifiersExtensions.Error_InvalidModifier (mc.Location, "virtual or abstract", Report);
2306 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2307 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2308 mc.GetSignatureForError ());
2313 // If the declaration includes the abstract modifier, then the
2314 // declaration does not include static, virtual or extern
2316 if ((flags & Modifiers.ABSTRACT) != 0){
2317 if ((flags & Modifiers.EXTERN) != 0){
2319 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2323 if ((flags & Modifiers.SEALED) != 0) {
2324 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2328 if ((flags & Modifiers.VIRTUAL) != 0){
2329 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2333 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2334 Report.SymbolRelatedToPreviousError (this);
2335 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2336 mc.GetSignatureForError (), GetSignatureForError ());
2341 if ((flags & Modifiers.PRIVATE) != 0){
2342 if ((flags & vao) != 0){
2343 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2348 if ((flags & Modifiers.SEALED) != 0){
2349 if ((flags & Modifiers.OVERRIDE) == 0){
2350 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2358 public Constructor DefaultStaticConstructor {
2359 get { return default_static_constructor; }
2362 protected override bool VerifyClsCompliance ()
2364 if (!base.VerifyClsCompliance ())
2369 Type base_type = TypeBuilder.BaseType;
2370 if (base_type != null && !AttributeTester.IsClsCompliant (base_type)) {
2371 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant", GetSignatureForError (), TypeManager.CSharpName (base_type));
2378 /// Checks whether container name is CLS Compliant
2380 void VerifyClsName ()
2382 Dictionary<string, object> base_members = base_cache == null ?
2383 new Dictionary<string, object> () :
2384 base_cache.GetPublicMembers ();
2385 var this_members = new Dictionary<string, object> ();
2387 foreach (var entry in defined_names) {
2388 MemberCore mc = entry.Value;
2389 if (!mc.IsClsComplianceRequired ())
2392 string name = entry.Key;
2393 string basename = name.Substring (name.LastIndexOf ('.') + 1);
2395 string lcase = basename.ToLower (System.Globalization.CultureInfo.InvariantCulture);
2397 if (!base_members.TryGetValue (lcase, out found)) {
2398 if (!this_members.TryGetValue (lcase, out found)) {
2399 this_members.Add (lcase, mc);
2404 if ((mc.ModFlags & Modifiers.OVERRIDE) != 0)
2407 if (found is MemberInfo) {
2408 if (basename == ((MemberInfo) found).Name)
2410 Report.SymbolRelatedToPreviousError ((MemberInfo) found);
2412 Report.SymbolRelatedToPreviousError ((MemberCore) found);
2415 Report.Warning (3005, 1, mc.Location, "Identifier `{0}' differing only in case is not CLS-compliant", mc.GetSignatureForError ());
2421 /// Performs checks for an explicit interface implementation. First it
2422 /// checks whether the `interface_type' is a base inteface implementation.
2423 /// Then it checks whether `name' exists in the interface type.
2425 public bool VerifyImplements (InterfaceMemberBase mb)
2427 if (ifaces != null) {
2428 foreach (Type t in ifaces){
2429 if (TypeManager.IsEqual (t, mb.InterfaceType))
2434 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2435 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2436 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2440 public override Type LookupAnyGeneric (string typeName)
2442 if (types != null) {
2443 foreach (TypeContainer tc in types) {
2447 int pos = tc.Basename.LastIndexOf ('`');
2448 if (pos == typeName.Length && String.Compare (typeName, 0, tc.Basename, 0, pos) == 0)
2449 return tc.TypeBuilder;
2453 return base.LookupAnyGeneric (typeName);
2456 public void Mark_HasEquals ()
2458 cached_method |= CachedMethods.Equals;
2461 public void Mark_HasGetHashCode ()
2463 cached_method |= CachedMethods.GetHashCode;
2467 /// Method container contains Equals method
2469 public bool HasEquals {
2471 return (cached_method & CachedMethods.Equals) != 0;
2476 /// Method container contains GetHashCode method
2478 public bool HasGetHashCode {
2480 return (cached_method & CachedMethods.GetHashCode) != 0;
2484 public bool HasStaticFieldInitializer {
2486 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2490 cached_method |= CachedMethods.HasStaticFieldInitializer;
2492 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2500 string IMemberContainer.Name {
2506 Type IMemberContainer.Type {
2512 bool IMemberContainer.IsInterface {
2514 return Kind == Kind.Interface;
2518 MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
2520 BindingFlags new_bf = bf | BindingFlags.DeclaredOnly;
2522 if (GenericType != null)
2523 return TypeManager.FindMembers (GenericType, mt, new_bf,
2526 return FindMembers (mt, new_bf, null, null);
2530 // Generates xml doc comments (if any), and if required,
2531 // handle warning report.
2533 internal override void GenerateDocComment (DeclSpace ds)
2535 DocUtil.GenerateTypeDocComment (this, ds, Report);
2538 public override string DocCommentHeader {
2539 get { return "T:"; }
2542 public MemberCache BaseCache {
2544 if (base_cache != null)
2546 if (TypeBuilder.BaseType != null)
2547 base_cache = TypeManager.LookupMemberCache (TypeBuilder.BaseType);
2548 if (TypeBuilder.IsInterface)
2549 base_cache = TypeManager.LookupBaseInterfacesCache (TypeBuilder);
2555 public abstract class ClassOrStruct : TypeContainer
2557 Dictionary<SecurityAction, PermissionSet> declarative_security;
2559 public ClassOrStruct (NamespaceEntry ns, DeclSpace parent,
2560 MemberName name, Attributes attrs, Kind kind)
2561 : base (ns, parent, name, attrs, kind)
2565 protected override bool AddToContainer (MemberCore symbol, string name)
2567 if (name == MemberName.Name) {
2568 if (symbol is TypeParameter) {
2569 Report.Error (694, symbol.Location,
2570 "Type parameter `{0}' has same name as containing type, or method",
2571 symbol.GetSignatureForError ());
2575 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2576 if (imb == null || !imb.IsExplicitImpl) {
2577 Report.SymbolRelatedToPreviousError (this);
2578 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2579 symbol.GetSignatureForError ());
2584 return base.AddToContainer (symbol, name);
2587 public override void VerifyMembers ()
2589 base.VerifyMembers ();
2591 if ((events != null) && Report.WarningLevel >= 3) {
2592 foreach (Event e in events){
2593 // Note: The event can be assigned from same class only, so we can report
2594 // this warning for all accessibility modes
2595 if ((e.caching_flags & Flags.IsUsed) == 0)
2596 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2601 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2603 if (a.IsValidSecurityAttribute ()) {
2604 if (declarative_security == null)
2605 declarative_security = new Dictionary<SecurityAction, PermissionSet> ();
2607 a.ExtractSecurityPermissionSet (declarative_security);
2611 if (a.Type == pa.StructLayout) {
2612 PartialContainer.HasStructLayout = true;
2614 if (a.GetLayoutKindValue () == LayoutKind.Explicit)
2615 PartialContainer.HasExplicitLayout = true;
2618 if (a.Type == pa.Dynamic) {
2619 a.Error_MisusedDynamicAttribute ();
2623 base.ApplyAttributeBuilder (a, cb, pa);
2627 /// Defines the default constructors
2629 protected void DefineDefaultConstructor (bool is_static)
2631 // The default instance constructor is public
2632 // If the class is abstract, the default constructor is protected
2633 // The default static constructor is private
2637 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2639 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2642 Constructor c = new Constructor (this, MemberName.Name, mods,
2643 null, ParametersCompiled.EmptyReadOnlyParameters,
2644 new GeneratedBaseInitializer (Location),
2648 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2651 protected override bool DoDefineMembers ()
2653 CheckProtectedModifier ();
2655 base.DoDefineMembers ();
2657 if (default_static_constructor != null)
2658 default_static_constructor.Define ();
2663 public override void Emit ()
2665 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2666 DefineDefaultConstructor (true);
2667 default_static_constructor.Define ();
2672 if (declarative_security != null) {
2673 foreach (var de in declarative_security) {
2674 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2679 public override ExtensionMethodGroupExpr LookupExtensionMethod (Type extensionType, string name, Location loc)
2681 DeclSpace top_level = Parent;
2682 if (top_level != null) {
2683 while (top_level.Parent != null)
2684 top_level = top_level.Parent;
2686 var candidates = NamespaceEntry.NS.LookupExtensionMethod (extensionType, this, name);
2687 if (candidates != null)
2688 return new ExtensionMethodGroupExpr (candidates, NamespaceEntry, extensionType, loc);
2691 return NamespaceEntry.LookupExtensionMethod (extensionType, name, loc);
2694 protected override TypeAttributes TypeAttr {
2696 if (default_static_constructor == null)
2697 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2699 return base.TypeAttr;
2705 // TODO: should be sealed
2706 public class Class : ClassOrStruct {
2707 const Modifiers AllowedModifiers =
2710 Modifiers.PROTECTED |
2711 Modifiers.INTERNAL |
2713 Modifiers.ABSTRACT |
2718 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2720 public Class (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
2722 : base (ns, parent, name, attrs, Kind.Class)
2724 var accmods = Parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2725 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2727 if (IsStatic && RootContext.Version == LanguageVersion.ISO_1) {
2728 Report.FeatureIsNotAvailable (Location, "static classes");
2732 public override void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
2734 if (part.Name == "System.Object")
2735 Report.Error (537, part.Location,
2736 "The class System.Object cannot have a base class or implement an interface.");
2737 base.AddBasesForPart (part, bases);
2740 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2742 if (a.Type == pa.AttributeUsage) {
2743 if (!TypeManager.IsAttributeType (BaseType) &&
2744 TypeBuilder.FullName != "System.Attribute") {
2745 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2749 if (a.Type == pa.Conditional && !TypeManager.IsAttributeType (BaseType)) {
2750 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2754 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2755 a.Error_MissingGuidAttribute ();
2759 if (a.Type == pa.Extension) {
2760 a.Error_MisusedExtensionAttribute ();
2764 if (AttributeTester.IsAttributeExcluded (a.Type, Location))
2767 base.ApplyAttributeBuilder (a, cb, pa);
2770 public override AttributeTargets AttributeTargets {
2772 return AttributeTargets.Class;
2776 protected override void DefineContainerMembers (System.Collections.IList list)
2782 base.DefineContainerMembers (list);
2786 foreach (MemberCore m in list) {
2787 if (m is Operator) {
2788 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2792 if (m is Destructor) {
2793 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2798 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2802 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2805 if (m is Constructor) {
2806 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2810 Method method = m as Method;
2811 if (method != null && method.Parameters.HasExtensionMethodType) {
2812 Report.Error (1105, m.Location, "`{0}': Extension methods must be declared static", m.GetSignatureForError ());
2816 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2819 base.DefineContainerMembers (list);
2822 protected override bool DoDefineMembers ()
2824 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2825 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2828 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2829 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2832 if (InstanceConstructors == null && !IsStatic)
2833 DefineDefaultConstructor (false);
2835 return base.DoDefineMembers ();
2838 public override void Emit ()
2842 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2843 PredefinedAttributes.Get.Extension.EmitAttribute (TypeBuilder);
2846 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
2848 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
2850 if (base_class == null) {
2851 if (RootContext.StdLib)
2852 base_class = TypeManager.system_object_expr;
2853 else if (Name != "System.Object")
2854 base_class = TypeManager.system_object_expr;
2856 if (Kind == Kind.Class && TypeManager.IsGenericParameter (base_class.Type)){
2858 689, base_class.Location,
2859 "Cannot derive from `{0}' because it is a type parameter",
2860 base_class.GetSignatureForError ());
2864 if (IsGeneric && TypeManager.IsAttributeType (base_class.Type)) {
2865 Report.Error (698, base_class.Location,
2866 "A generic type cannot derive from `{0}' because it is an attribute class",
2867 base_class.GetSignatureForError ());
2870 if (base_class.IsSealed){
2871 Report.SymbolRelatedToPreviousError (base_class.Type);
2872 if (base_class.Type.IsAbstract) {
2873 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2874 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2876 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2877 GetSignatureForError (), TypeManager.CSharpName (base_class.Type));
2882 if (!base_class.CanInheritFrom ()){
2883 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2884 GetSignatureForError (), base_class.GetSignatureForError ());
2888 if (!IsAccessibleAs (base_class.Type)) {
2889 Report.SymbolRelatedToPreviousError (base_class.Type);
2890 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2891 TypeManager.CSharpName (base_class.Type), GetSignatureForError ());
2895 if (PartialContainer.IsStaticClass) {
2896 if (base_class.Type != TypeManager.object_type) {
2897 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2898 GetSignatureForError (), base_class.GetSignatureForError ());
2902 if (ifaces != null) {
2903 foreach (TypeExpr t in ifaces)
2904 Report.SymbolRelatedToPreviousError (t.Type);
2905 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2912 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2913 /// Valid only for attribute classes.
2914 public bool IsExcluded ()
2916 if ((caching_flags & Flags.Excluded_Undetected) == 0)
2917 return (caching_flags & Flags.Excluded) != 0;
2919 caching_flags &= ~Flags.Excluded_Undetected;
2921 if (OptAttributes == null)
2924 Attribute[] attrs = OptAttributes.SearchMulti (PredefinedAttributes.Get.Conditional);
2928 foreach (Attribute a in attrs) {
2929 string condition = a.GetConditionalAttributeValue ();
2930 if (Location.CompilationUnit.IsConditionalDefined (condition))
2934 caching_flags |= Flags.Excluded;
2939 // FIXME: How do we deal with the user specifying a different
2942 protected override TypeAttributes TypeAttr {
2944 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2946 ta |= StaticClassAttribute;
2952 public sealed class Struct : ClassOrStruct {
2954 bool is_unmanaged, has_unmanaged_check_done;
2957 // Modifiers allowed in a struct declaration
2959 const Modifiers AllowedModifiers =
2962 Modifiers.PROTECTED |
2963 Modifiers.INTERNAL |
2967 public Struct (NamespaceEntry ns, DeclSpace parent, MemberName name,
2968 Modifiers mod, Attributes attrs)
2969 : base (ns, parent, name, attrs, Kind.Struct)
2971 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2973 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2975 this.ModFlags |= Modifiers.SEALED;
2978 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
2980 base.ApplyAttributeBuilder (a, cb, pa);
2983 // When struct constains fixed fixed and struct layout has explicitly
2984 // set CharSet, its value has to be propagated to compiler generated
2985 // fixed field types
2987 if (a.Type == pa.StructLayout && Fields != null && a.HasField ("CharSet")) {
2988 for (int i = 0; i < Fields.Count; ++i) {
2989 FixedField ff = Fields [i] as FixedField;
2991 ff.SetCharSet (TypeBuilder.Attributes);
2996 public override AttributeTargets AttributeTargets {
2998 return AttributeTargets.Struct;
3002 public override bool IsUnmanagedType ()
3007 if (requires_delayed_unmanagedtype_check)
3010 if (has_unmanaged_check_done)
3011 return is_unmanaged;
3013 has_unmanaged_check_done = true;
3015 foreach (FieldBase f in fields) {
3016 if ((f.ModFlags & Modifiers.STATIC) != 0)
3019 // It can happen when recursive unmanaged types are defined
3020 // struct S { S* s; }
3021 Type mt = f.MemberType;
3023 has_unmanaged_check_done = false;
3024 requires_delayed_unmanagedtype_check = true;
3028 // TODO: Remove when pointer types are under mcs control
3029 while (mt.IsPointer)
3030 mt = TypeManager.GetElementType (mt);
3031 if (TypeManager.IsEqual (mt, TypeBuilder))
3034 if (TypeManager.IsUnmanagedType (mt))
3040 is_unmanaged = true;
3044 protected override TypeExpr[] ResolveBaseTypes (out TypeExpr base_class)
3046 TypeExpr[] ifaces = base.ResolveBaseTypes (out base_class);
3048 // If we are compiling our runtime,
3049 // and we are defining ValueType, then our
3050 // base is `System.Object'.
3052 if (base_class == null) {
3053 if (!RootContext.StdLib && Name == "System.ValueType")
3054 base_class = TypeManager.system_object_expr;
3056 base_class = TypeManager.system_valuetype_expr;
3063 // FIXME: Allow the user to specify a different set of attributes
3064 // in some cases (Sealed for example is mandatory for a class,
3065 // but what SequentialLayout can be changed
3067 protected override TypeAttributes TypeAttr {
3069 const TypeAttributes DefaultTypeAttributes =
3070 TypeAttributes.SequentialLayout |
3071 TypeAttributes.Sealed;
3073 return base.TypeAttr | DefaultTypeAttributes;
3077 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3079 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3080 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3081 field.GetSignatureForError ());
3084 base.RegisterFieldForInitialization (field, expression);
3092 public sealed class Interface : TypeContainer, IMemberContainer {
3095 /// Modifiers allowed in a class declaration
3097 public const Modifiers AllowedModifiers =
3100 Modifiers.PROTECTED |
3101 Modifiers.INTERNAL |
3105 public Interface (NamespaceEntry ns, DeclSpace parent, MemberName name, Modifiers mod,
3107 : base (ns, parent, name, attrs, Kind.Interface)
3109 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3111 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3114 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3116 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3117 a.Error_MissingGuidAttribute ();
3121 base.ApplyAttributeBuilder (a, cb, pa);
3125 public override AttributeTargets AttributeTargets {
3127 return AttributeTargets.Interface;
3131 protected override TypeAttributes TypeAttr {
3133 const TypeAttributes DefaultTypeAttributes =
3134 TypeAttributes.AutoLayout |
3135 TypeAttributes.Abstract |
3136 TypeAttributes.Interface;
3138 return base.TypeAttr | DefaultTypeAttributes;
3142 protected override bool VerifyClsCompliance ()
3144 if (!base.VerifyClsCompliance ())
3147 if (ifaces != null) {
3148 foreach (Type t in ifaces) {
3149 if (AttributeTester.IsClsCompliant (t))
3152 Report.SymbolRelatedToPreviousError (t);
3153 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3154 GetSignatureForError (), TypeManager.CSharpName (t));
3162 // It is used as a base class for all property based members
3163 // This includes properties, indexers, and events
3164 public abstract class PropertyBasedMember : InterfaceMemberBase
3166 public PropertyBasedMember (DeclSpace parent, GenericMethod generic,
3167 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3168 MemberName name, Attributes attrs)
3169 : base (parent, generic, type, mod, allowed_mod, name, attrs)
3173 protected override bool VerifyClsCompliance ()
3175 if (!base.VerifyClsCompliance ())
3178 if (!AttributeTester.IsClsCompliant (MemberType)) {
3179 Report.Warning (3003, 1, Location, "Type of `{0}' is not CLS-compliant",
3180 GetSignatureForError ());
3187 public abstract class InterfaceMemberBase : MemberBase {
3189 // Whether this is an interface member.
3191 public bool IsInterface;
3194 // If true, this is an explicit interface implementation
3196 public bool IsExplicitImpl;
3198 protected bool is_external_implementation;
3201 // The interface type we are explicitly implementing
3203 public Type InterfaceType;
3206 // The method we're overriding if this is an override method.
3208 protected MethodInfo base_method;
3210 readonly Modifiers explicit_mod_flags;
3211 public MethodAttributes flags;
3213 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3214 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3215 MemberName name, Attributes attrs)
3216 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3219 IsInterface = parent.PartialContainer.Kind == Kind.Interface;
3220 IsExplicitImpl = (MemberName.Left != null);
3221 explicit_mod_flags = mod;
3224 protected override bool CheckBase ()
3226 if (!base.CheckBase ())
3229 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3230 CheckForDuplications ();
3235 // Is null for System.Object while compiling corlib and base interfaces
3236 if (Parent.PartialContainer.BaseCache == null) {
3237 if ((ModFlags & Modifiers.NEW) != 0) {
3238 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3243 Type base_ret_type = null;
3244 base_method = FindOutBaseMethod (ref base_ret_type);
3246 // method is override
3247 if (base_method != null) {
3248 if (!CheckMethodAgainstBase (base_ret_type))
3251 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3252 ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (base_method);
3254 if (OptAttributes == null || !OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3255 Report.SymbolRelatedToPreviousError (base_method);
3256 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3257 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3260 if (OptAttributes != null && OptAttributes.Contains (PredefinedAttributes.Get.Obsolete)) {
3261 Report.SymbolRelatedToPreviousError (base_method);
3262 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3263 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3270 MemberInfo conflict_symbol = Parent.PartialContainer.FindBaseMemberWithSameName (Name, !((this is Event) || (this is Property)));
3271 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3272 if (conflict_symbol != null) {
3273 Report.SymbolRelatedToPreviousError (conflict_symbol);
3275 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3276 else if (this is PropertyBase)
3277 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3279 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method", GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3281 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3282 GetSignatureForError (), SimpleName.GetMemberType (this));
3287 if (conflict_symbol == null) {
3288 if ((ModFlags & Modifiers.NEW) != 0) {
3289 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required", GetSignatureForError ());
3294 if ((ModFlags & Modifiers.NEW) == 0) {
3295 if (this is MethodOrOperator && conflict_symbol.MemberType == MemberTypes.Method)
3298 Report.SymbolRelatedToPreviousError (conflict_symbol);
3299 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3300 GetSignatureForError (), TypeManager.GetFullNameSignature (conflict_symbol));
3306 protected virtual bool CheckForDuplications ()
3308 return Parent.MemberCache.CheckExistingMembersOverloads (
3309 this, GetFullName (MemberName), ParametersCompiled.EmptyReadOnlyParameters, Report);
3313 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3314 // that have been defined.
3316 // `name' is the user visible name for reporting errors (this is used to
3317 // provide the right name regarding method names and properties)
3319 bool CheckMethodAgainstBase (Type base_method_type)
3323 if ((ModFlags & Modifiers.OVERRIDE) != 0){
3324 if (!(base_method.IsAbstract || base_method.IsVirtual)){
3325 Report.SymbolRelatedToPreviousError (base_method);
3326 Report.Error (506, Location,
3327 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3328 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3332 // Now we check that the overriden method is not final
3334 if (base_method.IsFinal) {
3335 Report.SymbolRelatedToPreviousError (base_method);
3336 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3337 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3341 // Check that the permissions are not being changed
3343 MethodAttributes thisp = flags & MethodAttributes.MemberAccessMask;
3344 MethodAttributes base_classp = base_method.Attributes & MethodAttributes.MemberAccessMask;
3346 if (!CheckAccessModifiers (thisp, base_classp, base_method)) {
3347 Error_CannotChangeAccessModifiers (Location, base_method, base_classp, null);
3351 if (!TypeManager.IsEqual (MemberType, TypeManager.TypeToCoreType (base_method_type))) {
3352 Report.SymbolRelatedToPreviousError (base_method);
3353 if (this is PropertyBasedMember) {
3354 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3355 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3358 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3359 GetSignatureForError (), TypeManager.CSharpName (base_method_type), TypeManager.CSharpSignature (base_method));
3365 if ((ModFlags & Modifiers.NEW) == 0) {
3366 if ((ModFlags & Modifiers.OVERRIDE) == 0) {
3367 ModFlags |= Modifiers.NEW;
3368 Report.SymbolRelatedToPreviousError (base_method);
3369 if (!IsInterface && (base_method.IsVirtual || base_method.IsAbstract)) {
3370 Report.Warning (114, 2, Location, "`{0}' hides inherited member `{1}'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword",
3371 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3372 if (base_method.IsAbstract){
3373 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3374 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3378 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3379 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3383 if (base_method.IsAbstract && !IsInterface) {
3384 Report.SymbolRelatedToPreviousError (base_method);
3385 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3386 GetSignatureForError (), TypeManager.CSharpSignature (base_method));
3394 protected bool CheckAccessModifiers (MethodAttributes thisp, MethodAttributes base_classp, MethodInfo base_method)
3396 if ((base_classp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3398 // when overriding protected internal, the method can be declared
3399 // protected internal only within the same assembly or assembly
3400 // which has InternalsVisibleTo
3402 if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
3403 return TypeManager.IsThisOrFriendAssembly (Parent.Module.Assembly, base_method.DeclaringType.Assembly);
3404 } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
3406 // if it's not "protected internal", it must be "protected"
3410 } else if (Parent.TypeBuilder.Assembly == base_method.DeclaringType.Assembly) {
3412 // protected within the same assembly - an error
3415 } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
3416 (base_classp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
3418 // protected ok, but other attributes differ - report an error
3424 return (thisp == base_classp);
3428 public override bool Define ()
3431 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3432 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3434 flags = MethodAttributes.Public |
3435 MethodAttributes.Abstract |
3436 MethodAttributes.HideBySig |
3437 MethodAttributes.NewSlot |
3438 MethodAttributes.Virtual;
3440 Parent.PartialContainer.MethodModifiersValid (this);
3442 flags = ModifiersExtensions.MethodAttr (ModFlags);
3445 if (IsExplicitImpl) {
3446 TypeExpr iface_texpr = MemberName.Left.GetTypeExpression ().ResolveAsTypeTerminal (this, false);
3447 if (iface_texpr == null)
3450 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3451 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3452 GetSignatureForError ());
3455 InterfaceType = iface_texpr.Type;
3457 if (!InterfaceType.IsInterface) {
3458 Report.SymbolRelatedToPreviousError (InterfaceType);
3459 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3460 TypeManager.CSharpName (InterfaceType));
3462 Parent.PartialContainer.VerifyImplements (this);
3465 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3468 return base.Define ();
3471 protected bool DefineParameters (ParametersCompiled parameters)
3473 if (!parameters.Resolve (this))
3477 for (int i = 0; i < parameters.Count; ++i) {
3478 Parameter p = parameters [i];
3480 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3481 p.Warning_UselessOptionalParameter (Report);
3483 if (p.CheckAccessibility (this))
3486 Type t = parameters.Types [i];
3487 Report.SymbolRelatedToPreviousError (t);
3488 if (this is Indexer)
3489 Report.Error (55, Location,
3490 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3491 TypeManager.CSharpName (t), GetSignatureForError ());
3492 else if (this is Operator)
3493 Report.Error (57, Location,
3494 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3495 TypeManager.CSharpName (t), GetSignatureForError ());
3497 Report.Error (51, Location,
3498 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3499 TypeManager.CSharpName (t), GetSignatureForError ());
3505 public override void Emit()
3507 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3508 // We are more strict than csc and report this as an error because SRE does not allow emit that
3509 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3510 if (this is Constructor) {
3511 Report.Error (824, Location,
3512 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3514 Report.Error (626, Location,
3515 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3516 GetSignatureForError ());
3523 public override bool EnableOverloadChecks (MemberCore overload)
3526 // Two members can differ in their explicit interface
3527 // type parameter only
3529 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3530 if (imb != null && imb.IsExplicitImpl) {
3531 if (IsExplicitImpl) {
3532 caching_flags |= Flags.MethodOverloadsExist;
3537 return IsExplicitImpl;
3540 protected void Error_CannotChangeAccessModifiers (Location loc, MemberInfo base_method, MethodAttributes ma, string suffix)
3542 Report.SymbolRelatedToPreviousError (base_method);
3543 string base_name = TypeManager.GetFullNameSignature (base_method);
3544 string this_name = GetSignatureForError ();
3545 if (suffix != null) {
3546 base_name += suffix;
3547 this_name += suffix;
3550 Report.Error (507, loc, "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3551 this_name, ModifiersExtensions.GetDescription (ma), base_name);
3554 protected static string Error722 {
3556 return "`{0}': static types cannot be used as return types";
3561 /// Gets base method and its return type
3563 protected abstract MethodInfo FindOutBaseMethod (ref Type base_ret_type);
3566 // The "short" name of this property / indexer / event. This is the
3567 // name without the explicit interface.
3569 public string ShortName
3571 get { return MemberName.Name; }
3572 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3576 // Returns full metadata method name
3578 public string GetFullName (MemberName name)
3580 if (!IsExplicitImpl)
3584 // When dealing with explicit members a full interface type
3585 // name is added to member name to avoid possible name conflicts
3587 // We use CSharpName which gets us full name with benefit of
3588 // replacing predefined names which saves some space and name
3591 return TypeManager.CSharpName (InterfaceType) + "." + name.Name;
3594 protected override bool VerifyClsCompliance ()
3596 if (!base.VerifyClsCompliance ()) {
3597 if (IsInterface && HasClsCompliantAttribute && Parent.IsClsComplianceRequired ()) {
3598 Report.Warning (3010, 1, Location, "`{0}': CLS-compliant interfaces must have only CLS-compliant members", GetSignatureForError ());
3601 if ((ModFlags & Modifiers.ABSTRACT) != 0 && Parent.TypeBuilder.IsClass && IsExposedFromAssembly () && Parent.IsClsComplianceRequired ()) {
3602 Report.Warning (3011, 1, Location, "`{0}': only CLS-compliant members can be abstract", GetSignatureForError ());
3607 if (GenericMethod != null)
3608 GenericMethod.VerifyClsCompliance ();
3613 public override bool IsUsed
3615 get { return IsExplicitImpl || base.IsUsed; }
3620 public abstract class MemberBase : MemberCore
3622 protected FullNamedExpression type_name;
3623 protected Type member_type;
3625 public readonly DeclSpace ds;
3626 public readonly GenericMethod GenericMethod;
3628 protected MemberBase (DeclSpace parent, GenericMethod generic,
3629 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod,
3630 MemberName name, Attributes attrs)
3631 : base (parent, name, attrs)
3633 this.ds = generic != null ? generic : (DeclSpace) parent;
3634 this.type_name = type;
3635 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3636 GenericMethod = generic;
3637 if (GenericMethod != null)
3638 GenericMethod.ModFlags = ModFlags;
3642 // Main member define entry
3644 public override bool Define ()
3646 DoMemberTypeIndependentChecks ();
3649 // Returns false only when type resolution failed
3651 if (!ResolveMemberType ())
3654 DoMemberTypeDependentChecks ();
3659 // Any type_name independent checks
3661 protected virtual void DoMemberTypeIndependentChecks ()
3663 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3664 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3665 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3666 GetSignatureForError (), Parent.GetSignatureForError ());
3671 // Any type_name dependent checks
3673 protected virtual void DoMemberTypeDependentChecks ()
3675 // verify accessibility
3676 if (!IsAccessibleAs (MemberType)) {
3677 Report.SymbolRelatedToPreviousError (MemberType);
3678 if (this is Property)
3679 Report.Error (53, Location,
3680 "Inconsistent accessibility: property type `" +
3681 TypeManager.CSharpName (MemberType) + "' is less " +
3682 "accessible than property `" + GetSignatureForError () + "'");
3683 else if (this is Indexer)
3684 Report.Error (54, Location,
3685 "Inconsistent accessibility: indexer return type `" +
3686 TypeManager.CSharpName (MemberType) + "' is less " +
3687 "accessible than indexer `" + GetSignatureForError () + "'");
3688 else if (this is MethodCore) {
3689 if (this is Operator)
3690 Report.Error (56, Location,
3691 "Inconsistent accessibility: return type `" +
3692 TypeManager.CSharpName (MemberType) + "' is less " +
3693 "accessible than operator `" + GetSignatureForError () + "'");
3695 Report.Error (50, Location,
3696 "Inconsistent accessibility: return type `" +
3697 TypeManager.CSharpName (MemberType) + "' is less " +
3698 "accessible than method `" + GetSignatureForError () + "'");
3700 Report.Error (52, Location,
3701 "Inconsistent accessibility: field type `" +
3702 TypeManager.CSharpName (MemberType) + "' is less " +
3703 "accessible than field `" + GetSignatureForError () + "'");
3707 Variance variance = this is Event ? Variance.Contravariant : Variance.Covariant;
3708 TypeManager.CheckTypeVariance (MemberType, variance, this);
3711 protected bool IsTypePermitted ()
3713 if (TypeManager.IsSpecialType (MemberType)) {
3714 Report.Error (610, Location, "Field or property cannot be of type `{0}'", TypeManager.CSharpName (MemberType));
3720 protected virtual bool CheckBase ()
3722 CheckProtectedModifier ();
3727 public Type MemberType {
3728 get { return member_type; }
3731 protected virtual bool ResolveMemberType ()
3733 if (member_type != null)
3734 throw new InternalErrorException ("Multi-resolve");
3736 TypeExpr te = type_name.ResolveAsTypeTerminal (this, false);
3741 // Replace original type name, error reporting can use fully resolved name
3745 member_type = te.Type;
3751 // `set' and `get' accessors are represented with an Accessor.
3753 public class Accessor {
3755 // Null if the accessor is empty, or a Block if not
3757 public const Modifiers AllowedModifiers =
3759 Modifiers.PROTECTED |
3760 Modifiers.INTERNAL |
3763 public ToplevelBlock Block;
3764 public Attributes Attributes;
3765 public Location Location;
3766 public Modifiers ModFlags;
3767 public ParametersCompiled Parameters;
3769 public Accessor (ToplevelBlock b, Modifiers mod, Attributes attrs, ParametersCompiled p, Location loc)
3775 ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, 0, loc, RootContext.ToplevelTypes.Compiler.Report);
3780 // Properties and Indexers both generate PropertyBuilders, we use this to share
3781 // their common bits.
3783 abstract public class PropertyBase : PropertyBasedMember {
3785 public class GetMethod : PropertyMethod
3787 static string[] attribute_targets = new string [] { "method", "return" };
3789 public GetMethod (PropertyBase method):
3790 base (method, "get_")
3794 public GetMethod (PropertyBase method, Accessor accessor):
3795 base (method, accessor, "get_")
3799 public override MethodBuilder Define (DeclSpace parent)
3801 base.Define (parent);
3806 method_data = new MethodData (method, ModFlags, flags, this);
3808 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
3811 return method_data.MethodBuilder;
3814 public override Type ReturnType {
3816 return method.MemberType;
3820 public override ParametersCompiled ParameterInfo {
3822 return ParametersCompiled.EmptyReadOnlyParameters;
3826 public override string[] ValidAttributeTargets {
3828 return attribute_targets;
3833 public class SetMethod : PropertyMethod {
3835 static string[] attribute_targets = new string [] { "method", "param", "return" };
3836 ImplicitParameter param_attr;
3837 protected ParametersCompiled parameters;
3839 public SetMethod (PropertyBase method) :
3840 base (method, "set_")
3842 parameters = new ParametersCompiled (Compiler,
3843 new Parameter (method.type_name, "value", Parameter.Modifier.NONE, null, Location));
3846 public SetMethod (PropertyBase method, Accessor accessor):
3847 base (method, accessor, "set_")
3849 this.parameters = accessor.Parameters;
3852 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3854 if (a.Target == AttributeTargets.Parameter) {
3855 if (param_attr == null)
3856 param_attr = new ImplicitParameter (method_data.MethodBuilder);
3858 param_attr.ApplyAttributeBuilder (a, cb, pa);
3862 base.ApplyAttributeBuilder (a, cb, pa);
3865 public override ParametersCompiled ParameterInfo {
3871 public override MethodBuilder Define (DeclSpace parent)
3873 parameters.Resolve (this);
3875 base.Define (parent);
3880 method_data = new MethodData (method, ModFlags, flags, this);
3882 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
3885 return method_data.MethodBuilder;
3888 public override Type ReturnType {
3890 return TypeManager.void_type;
3894 public override string[] ValidAttributeTargets {
3896 return attribute_targets;
3901 static string[] attribute_targets = new string [] { "property" };
3903 public abstract class PropertyMethod : AbstractPropertyEventMethod
3905 protected readonly PropertyBase method;
3906 protected MethodAttributes flags;
3908 public PropertyMethod (PropertyBase method, string prefix)
3909 : base (method, prefix)
3911 this.method = method;
3912 this.ModFlags = method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE);
3915 public PropertyMethod (PropertyBase method, Accessor accessor,
3917 : base (method, accessor, prefix)
3919 this.method = method;
3920 this.ModFlags = accessor.ModFlags | (method.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE));
3922 if (accessor.ModFlags != 0 && RootContext.Version == LanguageVersion.ISO_1) {
3923 Report.FeatureIsNotAvailable (Location, "access modifiers on properties");
3927 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
3929 if (a.IsInternalMethodImplAttribute) {
3930 method.is_external_implementation = true;
3933 base.ApplyAttributeBuilder (a, cb, pa);
3936 public override AttributeTargets AttributeTargets {
3938 return AttributeTargets.Method;
3942 public override bool IsClsComplianceRequired ()
3944 return method.IsClsComplianceRequired ();
3947 public virtual MethodBuilder Define (DeclSpace parent)
3949 CheckForDuplications ();
3952 if (method.InterfaceType != null && parent.PartialContainer.PendingImplementations != null) {
3953 MethodInfo mi = parent.PartialContainer.PendingImplementations.IsInterfaceMethod (
3954 MethodName.Name, method.InterfaceType, new MethodData (method, ModFlags, flags, this));
3956 Report.SymbolRelatedToPreviousError (mi);
3957 Report.Error (551, Location, "Explicit interface implementation `{0}' is missing accessor `{1}'",
3958 method.GetSignatureForError (), TypeManager.CSharpSignature (mi, true));
3964 TypeContainer container = parent.PartialContainer;
3967 // Check for custom access modifier
3969 if ((ModFlags & Modifiers.AccessibilityMask) == 0) {
3970 ModFlags |= method.ModFlags;
3971 flags = method.flags;
3973 if (container.Kind == Kind.Interface)
3974 Report.Error (275, Location, "`{0}': accessibility modifiers may not be used on accessors in an interface",
3975 GetSignatureForError ());
3977 if ((method.ModFlags & Modifiers.ABSTRACT) != 0 && (ModFlags & Modifiers.PRIVATE) != 0) {
3978 Report.Error (442, Location, "`{0}': abstract properties cannot have private accessors", GetSignatureForError ());
3981 CheckModifiers (ModFlags);
3982 ModFlags |= (method.ModFlags & (~Modifiers.AccessibilityMask));
3983 ModFlags |= Modifiers.PROPERTY_CUSTOM;
3984 flags = ModifiersExtensions.MethodAttr (ModFlags);
3985 flags |= (method.flags & (~MethodAttributes.MemberAccessMask));
3988 CheckAbstractAndExtern (block != null);
3989 CheckProtectedModifier ();
3991 if (block != null && block.IsIterator)
3992 Iterator.CreateIterator (this, Parent.PartialContainer, ModFlags, Compiler);
3997 public bool HasCustomAccessModifier {
3999 return (ModFlags & Modifiers.PROPERTY_CUSTOM) != 0;
4003 public PropertyBase Property {
4009 public override ObsoleteAttribute GetObsoleteAttribute ()
4011 return method.GetObsoleteAttribute ();
4014 public override string GetSignatureForError()
4016 return method.GetSignatureForError () + '.' + prefix.Substring (0, 3);
4019 void CheckModifiers (Modifiers modflags)
4021 modflags &= Modifiers.AccessibilityMask;
4022 Modifiers flags = 0;
4023 Modifiers mflags = method.ModFlags & Modifiers.AccessibilityMask;
4025 if ((mflags & Modifiers.PUBLIC) != 0) {
4026 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL | Modifiers.PRIVATE;
4028 else if ((mflags & Modifiers.PROTECTED) != 0) {
4029 if ((mflags & Modifiers.INTERNAL) != 0)
4030 flags |= Modifiers.PROTECTED | Modifiers.INTERNAL;
4032 flags |= Modifiers.PRIVATE;
4033 } else if ((mflags & Modifiers.INTERNAL) != 0)
4034 flags |= Modifiers.PRIVATE;
4036 if ((mflags == modflags) || (modflags & (~flags)) != 0) {
4037 Report.Error (273, Location,
4038 "The accessibility modifier of the `{0}' accessor must be more restrictive than the modifier of the property or indexer `{1}'",
4039 GetSignatureForError (), method.GetSignatureForError ());
4043 protected bool CheckForDuplications ()
4045 if ((caching_flags & Flags.MethodOverloadsExist) == 0)
4048 return Parent.MemberCache.CheckExistingMembersOverloads (this, Name, ParameterInfo, Report);
4052 public PropertyMethod Get, Set;
4053 public PropertyBuilder PropertyBuilder;
4054 public MethodBuilder GetBuilder, SetBuilder;
4056 protected bool define_set_first = false;
4058 public PropertyBase (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
4059 Modifiers allowed_mod, MemberName name,
4060 Attributes attrs, bool define_set_first)
4061 : base (parent, null, type, mod_flags, allowed_mod, name, attrs)
4063 this.define_set_first = define_set_first;
4066 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4068 if (a.HasSecurityAttribute) {
4069 a.Error_InvalidSecurityParent ();
4073 if (a.Type == pa.Dynamic) {
4074 a.Error_MisusedDynamicAttribute ();
4078 PropertyBuilder.SetCustomAttribute (cb);
4081 public override AttributeTargets AttributeTargets {
4083 return AttributeTargets.Property;
4087 protected override void DoMemberTypeDependentChecks ()
4089 base.DoMemberTypeDependentChecks ();
4093 if (MemberType.IsGenericParameter)
4097 if ((MemberType.Attributes & Class.StaticClassAttribute) == Class.StaticClassAttribute) {
4098 Report.Error (722, Location, Error722, TypeManager.CSharpName (MemberType));
4102 protected override void DoMemberTypeIndependentChecks ()
4104 base.DoMemberTypeIndependentChecks ();
4107 // Accessors modifiers check
4109 if ((Get.ModFlags & Modifiers.AccessibilityMask) != 0 &&
4110 (Set.ModFlags & Modifiers.AccessibilityMask) != 0) {
4111 Report.Error (274, Location, "`{0}': Cannot specify accessibility modifiers for both accessors of the property or indexer",
4112 GetSignatureForError ());
4115 if ((ModFlags & Modifiers.OVERRIDE) == 0 &&
4116 (Get.IsDummy && (Set.ModFlags & Modifiers.AccessibilityMask) != 0) ||
4117 (Set.IsDummy && (Get.ModFlags & Modifiers.AccessibilityMask) != 0)) {
4118 Report.Error (276, Location,
4119 "`{0}': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor",
4120 GetSignatureForError ());
4126 GetBuilder = Get.Define (Parent);
4127 return (Get.IsDummy) ? true : GetBuilder != null;
4130 bool DefineSet (bool define)
4135 SetBuilder = Set.Define (Parent);
4136 return (Set.IsDummy) ? true : SetBuilder != null;
4139 protected bool DefineAccessors ()
4141 return DefineSet (define_set_first) &&
4143 DefineSet (!define_set_first);
4146 protected abstract PropertyInfo ResolveBaseProperty ();
4148 // TODO: rename to Resolve......
4149 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
4151 PropertyInfo base_property = ResolveBaseProperty ();
4152 if (base_property == null)
4155 base_ret_type = base_property.PropertyType;
4156 MethodInfo get_accessor = base_property.GetGetMethod (true);
4157 MethodInfo set_accessor = base_property.GetSetMethod (true);
4158 MethodAttributes get_accessor_access = 0, set_accessor_access = 0;
4161 // Check base property accessors conflict
4163 if ((ModFlags & (Modifiers.OVERRIDE | Modifiers.NEW)) == Modifiers.OVERRIDE) {
4164 if (get_accessor == null) {
4165 if (Get != null && !Get.IsDummy) {
4166 Report.SymbolRelatedToPreviousError (base_property);
4167 Report.Error (545, Location,
4168 "`{0}.get': cannot override because `{1}' does not have an overridable get accessor",
4169 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
4172 get_accessor_access = get_accessor.Attributes & MethodAttributes.MemberAccessMask;
4174 if (!Get.IsDummy && !CheckAccessModifiers (
4175 ModifiersExtensions.MethodAttr (Get.ModFlags) & MethodAttributes.MemberAccessMask, get_accessor_access, get_accessor))
4176 Error_CannotChangeAccessModifiers (Get.Location, get_accessor, get_accessor_access, ".get");
4179 if (set_accessor == null) {
4180 if (Set != null && !Set.IsDummy) {
4181 Report.SymbolRelatedToPreviousError (base_property);
4182 Report.Error (546, Location,
4183 "`{0}.set': cannot override because `{1}' does not have an overridable set accessor",
4184 GetSignatureForError (), TypeManager.GetFullNameSignature (base_property));
4187 set_accessor_access = set_accessor.Attributes & MethodAttributes.MemberAccessMask;
4189 if (!Set.IsDummy && !CheckAccessModifiers (
4190 ModifiersExtensions.MethodAttr (Set.ModFlags) & MethodAttributes.MemberAccessMask, set_accessor_access, set_accessor))
4191 Error_CannotChangeAccessModifiers (Set.Location, set_accessor, set_accessor_access, ".set");
4195 // When one accessor does not exist and property hides base one
4196 // we need to propagate this upwards
4197 if (set_accessor == null)
4198 set_accessor = get_accessor;
4201 // Get the less restrictive access
4203 return get_accessor_access > set_accessor_access ? get_accessor : set_accessor;
4206 public override void Emit ()
4209 // The PropertyBuilder can be null for explicit implementations, in that
4210 // case, we do not actually emit the ".property", so there is nowhere to
4211 // put the attribute
4213 if (PropertyBuilder != null) {
4214 if (OptAttributes != null)
4215 OptAttributes.Emit ();
4217 if (TypeManager.IsDynamicType (member_type)) {
4218 PredefinedAttributes.Get.Dynamic.EmitAttribute (PropertyBuilder);
4220 var trans_flags = TypeManager.HasDynamicTypeUsed (member_type);
4221 if (trans_flags != null) {
4222 var pa = PredefinedAttributes.Get.DynamicTransform;
4223 if (pa.Constructor != null || pa.ResolveConstructor (Location, TypeManager.bool_type.MakeArrayType ())) {
4224 PropertyBuilder.SetCustomAttribute (
4225 new CustomAttributeBuilder (pa.Constructor, new object [] { trans_flags }));
4241 /// Tests whether accessors are not in collision with some method (CS0111)
4243 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
4245 return Get.IsDuplicateImplementation (mc) || Set.IsDuplicateImplementation (mc);
4248 public override bool IsUsed
4254 return Get.IsUsed | Set.IsUsed;
4258 protected override void SetMemberName (MemberName new_name)
4260 base.SetMemberName (new_name);
4262 Get.UpdateName (this);
4263 Set.UpdateName (this);
4266 public override string[] ValidAttributeTargets {
4268 return attribute_targets;
4273 // Represents header string for documentation comment.
4275 public override string DocCommentHeader {
4276 get { return "P:"; }
4280 public class Property : PropertyBase
4282 public sealed class BackingField : Field
4284 readonly Property property;
4286 public BackingField (Property p)
4287 : base (p.Parent, p.type_name,
4288 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (p.ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
4289 new MemberName ("<" + p.GetFullName (p.MemberName) + ">k__BackingField", p.Location), null)
4294 public override string GetSignatureForError ()
4296 return property.GetSignatureForError ();
4300 const Modifiers AllowedModifiers =
4303 Modifiers.PROTECTED |
4304 Modifiers.INTERNAL |
4308 Modifiers.OVERRIDE |
4309 Modifiers.ABSTRACT |
4314 const Modifiers AllowedInterfaceModifiers =
4317 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
4318 MemberName name, Attributes attrs, Accessor get_block,
4319 Accessor set_block, bool define_set_first)
4320 : this (parent, type, mod, name, attrs, get_block, set_block,
4321 define_set_first, null)
4325 public Property (DeclSpace parent, FullNamedExpression type, Modifiers mod,
4326 MemberName name, Attributes attrs, Accessor get_block,
4327 Accessor set_block, bool define_set_first, Block current_block)
4328 : base (parent, type, mod,
4329 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4330 name, attrs, define_set_first)
4332 if (get_block == null)
4333 Get = new GetMethod (this);
4335 Get = new GetMethod (this, get_block);
4337 if (set_block == null)
4338 Set = new SetMethod (this);
4340 Set = new SetMethod (this, set_block);
4342 if (!IsInterface && (mod & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0 &&
4343 get_block != null && get_block.Block == null &&
4344 set_block != null && set_block.Block == null) {
4345 if (RootContext.Version <= LanguageVersion.ISO_2)
4346 Report.FeatureIsNotAvailable (Location, "automatically implemented properties");
4348 Get.ModFlags |= Modifiers.COMPILER_GENERATED;
4349 Set.ModFlags |= Modifiers.COMPILER_GENERATED;
4353 void CreateAutomaticProperty ()
4355 // Create backing field
4356 Field field = new BackingField (this);
4357 if (!field.Define ())
4360 Parent.PartialContainer.AddField (field);
4362 FieldExpr fe = new FieldExpr (field, Location);
4363 if ((field.ModFlags & Modifiers.STATIC) == 0)
4364 fe.InstanceExpression = new CompilerGeneratedThis (fe.Type, Location);
4367 Get.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
4368 Return r = new Return (fe, Location);
4369 Get.Block.AddStatement (r);
4372 Set.Block = new ToplevelBlock (Compiler, Set.ParameterInfo, Location);
4373 Assign a = new SimpleAssign (fe, new SimpleName ("value", Location));
4374 Set.Block.AddStatement (new StatementExpression (a));
4377 public override bool Define ()
4379 if (!base.Define ())
4382 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
4384 if ((Get.ModFlags & Modifiers.COMPILER_GENERATED) != 0)
4385 CreateAutomaticProperty ();
4387 if (!DefineAccessors ())
4393 // FIXME - PropertyAttributes.HasDefault ?
4395 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
4396 GetFullName (MemberName), PropertyAttributes.None, MemberType, null);
4399 PropertyBuilder.SetGetMethod (GetBuilder);
4400 Parent.MemberCache.AddMember (GetBuilder, Get);
4404 PropertyBuilder.SetSetMethod (SetBuilder);
4405 Parent.MemberCache.AddMember (SetBuilder, Set);
4408 TypeManager.RegisterProperty (PropertyBuilder, this);
4409 Parent.MemberCache.AddMember (PropertyBuilder, this);
4413 public override void Emit ()
4415 if (((Set.ModFlags | Get.ModFlags) & (Modifiers.STATIC | Modifiers.COMPILER_GENERATED)) == Modifiers.COMPILER_GENERATED && Parent.PartialContainer.HasExplicitLayout) {
4416 Report.Error (842, Location,
4417 "Automatically implemented property `{0}' cannot be used inside a type with an explicit StructLayout attribute",
4418 GetSignatureForError ());
4424 protected override PropertyInfo ResolveBaseProperty ()
4426 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
4427 Parent.TypeBuilder, Name, ParametersCompiled.EmptyReadOnlyParameters, null, true) as PropertyInfo;
4432 /// Gigantic workaround for lameness in SRE follows :
4433 /// This class derives from EventInfo and attempts to basically
4434 /// wrap around the EventBuilder so that FindMembers can quickly
4435 /// return this in it search for members
4437 public class MyEventBuilder : EventInfo {
4440 // We use this to "point" to our Builder which is
4441 // not really a MemberInfo
4443 EventBuilder MyBuilder;
4446 // We "catch" and wrap these methods
4448 MethodInfo raise, remove, add;
4450 EventAttributes attributes;
4451 Type declaring_type, reflected_type, event_type;
4456 public MyEventBuilder (Event ev, TypeBuilder type_builder, string name, EventAttributes event_attr, Type event_type)
4458 MyBuilder = type_builder.DefineEvent (name, event_attr, event_type);
4460 // And now store the values in our own fields.
4462 declaring_type = type_builder;
4464 reflected_type = type_builder;
4466 attributes = event_attr;
4469 this.event_type = event_type;
4473 // Methods that you have to override. Note that you only need
4474 // to "implement" the variants that take the argument (those are
4475 // the "abstract" methods, the others (GetAddMethod()) are
4478 public override MethodInfo GetAddMethod (bool nonPublic)
4483 public override MethodInfo GetRemoveMethod (bool nonPublic)
4488 public override MethodInfo GetRaiseMethod (bool nonPublic)
4494 // These methods make "MyEventInfo" look like a Builder
4496 public void SetRaiseMethod (MethodBuilder raiseMethod)
4498 raise = raiseMethod;
4499 MyBuilder.SetRaiseMethod (raiseMethod);
4502 public void SetRemoveOnMethod (MethodBuilder removeMethod)
4504 remove = removeMethod;
4505 MyBuilder.SetRemoveOnMethod (removeMethod);
4508 public void SetAddOnMethod (MethodBuilder addMethod)
4511 MyBuilder.SetAddOnMethod (addMethod);
4514 public void SetCustomAttribute (CustomAttributeBuilder cb)
4516 MyBuilder.SetCustomAttribute (cb);
4519 public override object [] GetCustomAttributes (bool inherit)
4521 // FIXME : There's nothing which can be seemingly done here because
4522 // we have no way of getting at the custom attribute objects of the
4527 public override object [] GetCustomAttributes (Type t, bool inherit)
4529 // FIXME : Same here !
4533 public override bool IsDefined (Type t, bool b)
4538 public override EventAttributes Attributes {
4544 public override string Name {
4550 public override Type DeclaringType {
4552 return declaring_type;
4556 public override Type ReflectedType {
4558 return reflected_type;
4562 public Type EventType {
4568 public void SetUsed ()
4570 if (my_event != null) {
4571 // my_event.SetAssigned ();
4572 my_event.SetMemberIsUsed ();
4578 /// For case when event is declared like property (with add and remove accessors).
4580 public class EventProperty: Event {
4581 abstract class AEventPropertyAccessor : AEventAccessor
4583 protected AEventPropertyAccessor (EventProperty method, Accessor accessor, string prefix)
4584 : base (method, accessor, prefix)
4588 public override MethodBuilder Define (DeclSpace ds)
4590 CheckAbstractAndExtern (block != null);
4591 return base.Define (ds);
4594 public override string GetSignatureForError ()
4596 return method.GetSignatureForError () + "." + prefix.Substring (0, prefix.Length - 1);
4600 sealed class AddDelegateMethod: AEventPropertyAccessor
4602 public AddDelegateMethod (EventProperty method, Accessor accessor):
4603 base (method, accessor, AddPrefix)
4608 sealed class RemoveDelegateMethod: AEventPropertyAccessor
4610 public RemoveDelegateMethod (EventProperty method, Accessor accessor):
4611 base (method, accessor, RemovePrefix)
4617 static readonly string[] attribute_targets = new string [] { "event" }; // "property" target was disabled for 2.0 version
4619 public EventProperty (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags,
4621 Attributes attrs, Accessor add, Accessor remove)
4622 : base (parent, type, mod_flags, name, attrs)
4624 Add = new AddDelegateMethod (this, add);
4625 Remove = new RemoveDelegateMethod (this, remove);
4628 public override bool Define()
4630 if (!base.Define ())
4637 public override string[] ValidAttributeTargets {
4639 return attribute_targets;
4645 /// Event is declared like field.
4647 public class EventField : Event {
4648 abstract class EventFieldAccessor : AEventAccessor
4650 protected EventFieldAccessor (EventField method, string prefix)
4651 : base (method, prefix)
4655 public override void Emit (DeclSpace parent)
4657 if ((method.ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) == 0) {
4658 if (parent is Class) {
4659 MethodBuilder mb = method_data.MethodBuilder;
4660 mb.SetImplementationFlags (mb.GetMethodImplementationFlags () | MethodImplAttributes.Synchronized);
4663 var field_info = ((EventField) method).BackingField;
4664 FieldExpr f_expr = new FieldExpr (field_info, Location);
4665 if ((method.ModFlags & Modifiers.STATIC) == 0)
4666 f_expr.InstanceExpression = new CompilerGeneratedThis (field_info.Spec.FieldType, Location);
4668 block = new ToplevelBlock (Compiler, ParameterInfo, Location);
4669 block.AddStatement (new StatementExpression (
4670 new CompoundAssign (Operation,
4672 block.GetParameterReference (ParameterInfo[0].Name, Location))));
4678 protected abstract Binary.Operator Operation { get; }
4681 sealed class AddDelegateMethod: EventFieldAccessor
4683 public AddDelegateMethod (EventField method):
4684 base (method, AddPrefix)
4688 protected override Binary.Operator Operation {
4689 get { return Binary.Operator.Addition; }
4693 sealed class RemoveDelegateMethod: EventFieldAccessor
4695 public RemoveDelegateMethod (EventField method):
4696 base (method, RemovePrefix)
4700 protected override Binary.Operator Operation {
4701 get { return Binary.Operator.Subtraction; }
4706 static readonly string[] attribute_targets = new string [] { "event", "field", "method" };
4707 static readonly string[] attribute_targets_interface = new string[] { "event", "method" };
4709 public Field BackingField;
4710 public Expression Initializer;
4712 public EventField (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
4713 : base (parent, type, mod_flags, name, attrs)
4715 Add = new AddDelegateMethod (this);
4716 Remove = new RemoveDelegateMethod (this);
4719 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4721 if (a.Target == AttributeTargets.Field) {
4722 BackingField.ApplyAttributeBuilder (a, cb, pa);
4726 if (a.Target == AttributeTargets.Method) {
4727 int errors = Report.Errors;
4728 Add.ApplyAttributeBuilder (a, cb, pa);
4729 if (errors == Report.Errors)
4730 Remove.ApplyAttributeBuilder (a, cb, pa);
4734 base.ApplyAttributeBuilder (a, cb, pa);
4737 public override bool Define()
4739 if (!base.Define ())
4742 if (Initializer != null && (ModFlags & Modifiers.ABSTRACT) != 0) {
4743 Report.Error (74, Location, "`{0}': abstract event cannot have an initializer",
4744 GetSignatureForError ());
4747 if (!HasBackingField) {
4752 // FIXME: We are unable to detect whether generic event is used because
4753 // we are using FieldExpr instead of EventExpr for event access in that
4754 // case. When this issue will be fixed this hack can be removed.
4755 if (TypeManager.IsGenericType (MemberType) || Parent.IsGeneric)
4758 if (Add.IsInterfaceImplementation)
4761 TypeManager.RegisterEventField (EventBuilder, this);
4763 BackingField = new Field (Parent,
4764 new TypeExpression (MemberType, Location),
4765 Modifiers.BACKING_FIELD | Modifiers.COMPILER_GENERATED | Modifiers.PRIVATE | (ModFlags & (Modifiers.STATIC | Modifiers.UNSAFE)),
4768 Parent.PartialContainer.AddField (BackingField);
4769 BackingField.Initializer = Initializer;
4770 BackingField.ModFlags &= ~Modifiers.COMPILER_GENERATED;
4772 // Call define because we passed fields definition
4773 return BackingField.Define ();
4776 bool HasBackingField {
4778 return !IsInterface && (ModFlags & Modifiers.ABSTRACT) == 0;
4782 public override string[] ValidAttributeTargets
4785 return HasBackingField ? attribute_targets : attribute_targets_interface;
4790 public abstract class Event : PropertyBasedMember {
4791 public abstract class AEventAccessor : AbstractPropertyEventMethod
4793 protected readonly Event method;
4794 ImplicitParameter param_attr;
4796 static readonly string[] attribute_targets = new string [] { "method", "param", "return" };
4798 public const string AddPrefix = "add_";
4799 public const string RemovePrefix = "remove_";
4801 protected AEventAccessor (Event method, string prefix)
4802 : base (method, prefix)
4804 this.method = method;
4805 this.ModFlags = method.ModFlags;
4808 protected AEventAccessor (Event method, Accessor accessor, string prefix)
4809 : base (method, accessor, prefix)
4811 this.method = method;
4812 this.ModFlags = method.ModFlags;
4815 public bool IsInterfaceImplementation {
4816 get { return method_data.implementing != null; }
4819 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4821 if (a.IsInternalMethodImplAttribute) {
4822 method.is_external_implementation = true;
4825 base.ApplyAttributeBuilder (a, cb, pa);
4828 protected override void ApplyToExtraTarget (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4830 if (a.Target == AttributeTargets.Parameter) {
4831 if (param_attr == null)
4832 param_attr = new ImplicitParameter (method_data.MethodBuilder);
4834 param_attr.ApplyAttributeBuilder (a, cb, pa);
4838 base.ApplyAttributeBuilder (a, cb, pa);
4841 public override AttributeTargets AttributeTargets {
4843 return AttributeTargets.Method;
4847 public override bool IsClsComplianceRequired ()
4849 return method.IsClsComplianceRequired ();
4852 public virtual MethodBuilder Define (DeclSpace parent)
4854 method_data = new MethodData (method, method.ModFlags,
4855 method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this);
4857 if (!method_data.Define (parent, method.GetFullName (MemberName), Report))
4860 MethodBuilder mb = method_data.MethodBuilder;
4861 ParameterInfo.ApplyAttributes (mb);
4865 public override Type ReturnType {
4867 return TypeManager.void_type;
4871 public override ObsoleteAttribute GetObsoleteAttribute ()
4873 return method.GetObsoleteAttribute ();
4876 public override string[] ValidAttributeTargets {
4878 return attribute_targets;
4882 public override ParametersCompiled ParameterInfo {
4884 return method.parameters;
4890 const Modifiers AllowedModifiers =
4893 Modifiers.PROTECTED |
4894 Modifiers.INTERNAL |
4899 Modifiers.OVERRIDE |
4901 Modifiers.ABSTRACT |
4904 const Modifiers AllowedInterfaceModifiers =
4907 public AEventAccessor Add, Remove;
4908 public MyEventBuilder EventBuilder;
4909 public MethodBuilder AddBuilder, RemoveBuilder;
4911 ParametersCompiled parameters;
4913 protected Event (DeclSpace parent, FullNamedExpression type, Modifiers mod_flags, MemberName name, Attributes attrs)
4914 : base (parent, null, type, mod_flags,
4915 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
4920 public override void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa)
4922 if ((a.HasSecurityAttribute)) {
4923 a.Error_InvalidSecurityParent ();
4927 EventBuilder.SetCustomAttribute (cb);
4930 public bool AreAccessorsDuplicateImplementation (MethodCore mc)
4932 return Add.IsDuplicateImplementation (mc) || Remove.IsDuplicateImplementation (mc);
4935 public override AttributeTargets AttributeTargets {
4937 return AttributeTargets.Event;
4941 public override bool Define ()
4943 if (!base.Define ())
4946 if (!TypeManager.IsDelegateType (MemberType)) {
4947 Report.Error (66, Location, "`{0}': event must be of a delegate type", GetSignatureForError ());
4950 parameters = ParametersCompiled.CreateFullyResolved (
4951 new Parameter (null, "value", Parameter.Modifier.NONE, null, Location), MemberType);
4956 if (TypeManager.delegate_combine_delegate_delegate == null) {
4957 TypeManager.delegate_combine_delegate_delegate = TypeManager.GetPredefinedMethod (
4958 TypeManager.delegate_type, "Combine", Location,
4959 TypeManager.delegate_type, TypeManager.delegate_type);
4961 if (TypeManager.delegate_remove_delegate_delegate == null) {
4962 TypeManager.delegate_remove_delegate_delegate = TypeManager.GetPredefinedMethod (
4963 TypeManager.delegate_type, "Remove", Location,
4964 TypeManager.delegate_type, TypeManager.delegate_type);
4968 // Now define the accessors
4971 AddBuilder = Add.Define (Parent);
4972 if (AddBuilder == null)
4975 RemoveBuilder = Remove.Define (Parent);
4976 if (RemoveBuilder == null)
4979 EventBuilder = new MyEventBuilder (this, Parent.TypeBuilder, Name, EventAttributes.None, MemberType);
4980 EventBuilder.SetAddOnMethod (AddBuilder);
4981 EventBuilder.SetRemoveOnMethod (RemoveBuilder);
4983 Parent.MemberCache.AddMember (EventBuilder, this);
4984 Parent.MemberCache.AddMember (AddBuilder, Add);
4985 Parent.MemberCache.AddMember (RemoveBuilder, Remove);
4990 public override void Emit ()
4992 if (OptAttributes != null) {
4993 OptAttributes.Emit ();
4997 Remove.Emit (Parent);
5002 protected override MethodInfo FindOutBaseMethod (ref Type base_ret_type)
5004 MethodInfo mi = (MethodInfo) Parent.PartialContainer.BaseCache.FindBaseEvent (
5005 Parent.TypeBuilder, Name);
5010 AParametersCollection pd = TypeManager.GetParameterData (mi);
5011 base_ret_type = pd.Types [0];
5016 // Represents header string for documentation comment.
5018 public override string DocCommentHeader {
5019 get { return "E:"; }
5024 public class Indexer : PropertyBase
5026 public class GetIndexerMethod : GetMethod
5028 ParametersCompiled parameters;
5030 public GetIndexerMethod (Indexer method):
5033 this.parameters = method.parameters;
5036 public GetIndexerMethod (PropertyBase method, Accessor accessor):
5037 base (method, accessor)
5039 parameters = accessor.Parameters;
5042 public override MethodBuilder Define (DeclSpace parent)
5044 parameters.Resolve (this);
5045 return base.Define (parent);
5048 public override bool EnableOverloadChecks (MemberCore overload)
5050 if (base.EnableOverloadChecks (overload)) {
5051 overload.caching_flags |= Flags.MethodOverloadsExist;
5058 public override ParametersCompiled ParameterInfo {
5065 public class SetIndexerMethod: SetMethod
5067 public SetIndexerMethod (Indexer method):
5070 parameters = ParametersCompiled.MergeGenerated (Compiler, method.parameters, false, parameters [0], null);
5073 public SetIndexerMethod (PropertyBase method, Accessor accessor):
5074 base (method, accessor)
5076 parameters = method.Get.IsDummy ? accessor.Parameters : accessor.Parameters.Clone ();
5079 public override bool EnableOverloadChecks (MemberCore overload)
5081 if (base.EnableOverloadChecks (overload)) {
5082 overload.caching_flags |= Flags.MethodOverloadsExist;
5090 const Modifiers AllowedModifiers =
5093 Modifiers.PROTECTED |
5094 Modifiers.INTERNAL |
5098 Modifiers.OVERRIDE |
5103 const Modifiers AllowedInterfaceModifiers =
5106 public readonly ParametersCompiled parameters;
5108 public Indexer (DeclSpace parent, FullNamedExpression type, MemberName name, Modifiers mod,
5109 ParametersCompiled parameters, Attributes attrs,
5110 Accessor get_block, Accessor set_block, bool define_set_first)
5111 : base (parent, type, mod,
5112 parent.PartialContainer.Kind == Kind.Interface ? AllowedInterfaceModifiers : AllowedModifiers,
5113 name, attrs, define_set_first)
5115 this.parameters = parameters;
5117 if (get_block == null)
5118 Get = new GetIndexerMethod (this);
5120 Get = new GetIndexerMethod (this, get_block);
5122 if (set_block == null)
5123 Set = new SetIndexerMethod (this);
5125 Set = new SetIndexerMethod (this, set_block);
5128 protected override bool CheckForDuplications ()
5130 return Parent.MemberCache.CheckExistingMembersOverloads (this, GetFullName (MemberName), parameters, Report);
5133 public override bool Define ()
5135 if (!base.Define ())
5138 if (!DefineParameters (parameters))
5141 if (OptAttributes != null) {
5142 Attribute indexer_attr = OptAttributes.Search (PredefinedAttributes.Get.IndexerName);
5143 if (indexer_attr != null) {
5144 // Remove the attribute from the list because it is not emitted
5145 OptAttributes.Attrs.Remove (indexer_attr);
5147 string name = indexer_attr.GetIndexerAttributeValue ();
5153 if (IsExplicitImpl) {
5154 Report.Error (415, indexer_attr.Location,
5155 "The `IndexerName' attribute is valid only on an " +
5156 "indexer that is not an explicit interface member declaration");
5160 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
5161 Report.Error (609, indexer_attr.Location,
5162 "Cannot set the `IndexerName' attribute on an indexer marked override");
5168 if (InterfaceType != null) {
5169 string base_IndexerName = TypeManager.IndexerPropertyName (InterfaceType);
5170 if (base_IndexerName != Name)
5171 ShortName = base_IndexerName;
5174 if (!Parent.PartialContainer.AddMember (this) ||
5175 !Parent.PartialContainer.AddMember (Get) || !Parent.PartialContainer.AddMember (Set))
5178 flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
5180 if (!DefineAccessors ())
5187 // Now name the parameters
5189 PropertyBuilder = Parent.TypeBuilder.DefineProperty (
5190 GetFullName (MemberName), PropertyAttributes.None, MemberType, parameters.GetEmitTypes ());
5193 PropertyBuilder.SetGetMethod (GetBuilder);
5194 Parent.MemberCache.AddMember (GetBuilder, Get);
5198 PropertyBuilder.SetSetMethod (SetBuilder);
5199 Parent.MemberCache.AddMember (SetBuilder, Set);
5202 TypeManager.RegisterIndexer (PropertyBuilder, parameters);
5203 Parent.MemberCache.AddMember (PropertyBuilder, this);
5207 public override bool EnableOverloadChecks (MemberCore overload)
5209 if (overload is Indexer) {
5210 caching_flags |= Flags.MethodOverloadsExist;
5214 return base.EnableOverloadChecks (overload);
5217 public override string GetDocCommentName (DeclSpace ds)
5219 return DocUtil.GetMethodDocCommentName (this, parameters, ds);
5222 public override string GetSignatureForError ()
5224 StringBuilder sb = new StringBuilder (Parent.GetSignatureForError ());
5225 if (MemberName.Left != null) {
5227 sb.Append (MemberName.Left.GetSignatureForError ());
5230 sb.Append (".this");
5231 sb.Append (parameters.GetSignatureForError ().Replace ('(', '[').Replace (')', ']'));
5232 return sb.ToString ();
5235 protected override PropertyInfo ResolveBaseProperty ()
5237 return Parent.PartialContainer.BaseCache.FindMemberToOverride (
5238 Parent.TypeBuilder, Name, parameters, null, true) as PropertyInfo;
5241 protected override bool VerifyClsCompliance ()
5243 if (!base.VerifyClsCompliance ())
5246 parameters.VerifyClsCompliance (this);