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@gmail.com)
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-2011 Novell, Inc
12 // Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
16 using System.Collections.Generic;
17 using System.Runtime.InteropServices;
18 using System.Security;
19 using System.Security.Permissions;
23 using XmlElement = System.Object;
27 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
28 using IKVM.Reflection;
29 using IKVM.Reflection.Emit;
31 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
32 using System.Reflection;
33 using System.Reflection.Emit;
39 public interface ITypesContainer
41 Location Location { get; }
42 MemberName MemberName { get; }
46 /// This is the base class for structs and classes.
48 public abstract class TypeContainer : DeclSpace, ITypeDefinition, ITypesContainer
51 // Different context is needed when resolving type container base
52 // types. Type names come from the parent scope but type parameter
53 // names from the container scope.
55 public struct BaseContext : IMemberContext
59 public BaseContext (TypeContainer tc)
64 #region IMemberContext Members
66 public CompilerContext Compiler {
67 get { return tc.Compiler; }
70 public TypeSpec CurrentType {
71 get { return tc.Parent.CurrentType; }
74 public TypeParameter[] CurrentTypeParameters {
75 get { return tc.PartialContainer.CurrentTypeParameters; }
78 public MemberCore CurrentMemberDefinition {
82 public bool IsObsolete {
83 get { return tc.IsObsolete; }
86 public bool IsUnsafe {
87 get { return tc.IsUnsafe; }
90 public bool IsStatic {
91 get { return tc.IsStatic; }
94 public ModuleContainer Module {
95 get { return tc.Module; }
98 public string GetSignatureForError ()
100 return tc.GetSignatureForError ();
103 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
108 public FullNamedExpression LookupNamespaceAlias (string name)
110 return tc.Parent.LookupNamespaceAlias (name);
113 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
116 TypeParameter[] tp = CurrentTypeParameters;
118 TypeParameter t = TypeParameter.FindTypeParameter (tp, name);
120 return new TypeParameterExpr (t, loc);
124 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
134 GetHashCode = 1 << 1,
135 HasStaticFieldInitializer = 1 << 2
139 // Whether this is a struct, class or interface
140 public readonly MemberKind Kind;
142 // Holds a list of classes and structures
143 protected List<TypeContainer> types;
145 List<MemberCore> ordered_explicit_member_list;
146 List<MemberCore> ordered_member_list;
148 // Holds the list of properties
149 List<MemberCore> properties;
151 // Holds the list of constructors
152 protected List<Constructor> instance_constructors;
154 // Holds the list of fields
155 protected List<FieldBase> fields;
157 // Holds a list of fields that have initializers
158 protected List<FieldInitializer> initialized_fields;
160 // Holds a list of static fields that have initializers
161 protected List<FieldInitializer> initialized_static_fields;
163 // Holds the list of constants
164 protected List<MemberCore> constants;
166 // Holds the methods.
167 List<MemberCore> methods;
170 protected List<MemberCore> events;
172 // Holds the indexers
173 List<MemberCore> indexers;
175 // Holds the operators
176 List<MemberCore> operators;
178 // Holds the compiler generated classes
179 protected List<CompilerGeneratedClass> compiler_generated;
181 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
183 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
186 // Pointers to the default constructor and the default static constructor
188 protected Constructor default_constructor;
189 protected Constructor default_static_constructor;
192 // Points to the first non-static field added to the container.
194 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
195 // and the first one's as good as any.
197 FieldBase first_nonstatic_field;
200 // This one is computed after we can distinguish interfaces
201 // from classes from the arraylist `type_bases'
203 protected TypeSpec base_type;
204 FullNamedExpression base_type_expr; // TODO: It's temporary variable
205 protected TypeSpec[] iface_exprs;
207 protected List<FullNamedExpression> type_bases;
209 bool members_defined;
210 bool members_defined_ok;
213 TypeContainer InTransit;
215 GenericTypeParameterBuilder[] all_tp_builders;
217 public const string DefaultIndexerName = "Item";
219 private bool seen_normal_indexers = false;
220 private string indexer_name = DefaultIndexerName;
221 protected bool requires_delayed_unmanagedtype_check;
224 private CachedMethods cached_method;
226 protected TypeSpec spec;
227 TypeSpec current_type;
229 List<TypeContainer> partial_parts;
231 public int DynamicSitesCounter;
234 /// The pending methods that need to be implemented
235 // (interfaces or abstract methods)
237 PendingImplementation pending;
239 public TypeContainer (NamespaceContainer ns, DeclSpace parent, MemberName name,
240 Attributes attrs, MemberKind kind)
241 : base (ns, parent, name, attrs)
243 if (parent != null && parent.NamespaceEntry != ns)
244 throw new InternalErrorException ("A nested type should be in the same NamespaceEntry as its enclosing class");
247 this.PartialContainer = this;
252 public List<FullNamedExpression> BaseTypeExpressions {
258 public override TypeSpec CurrentType {
260 if (current_type == null) {
263 // Switch to inflated version as it's used by all expressions
265 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Select (l => l.Type).ToArray ();
266 current_type = spec.MakeGenericType (this, targs);
276 public override TypeParameter[] CurrentTypeParameters {
278 return PartialContainer.type_params;
282 int CurrentTypeParametersStartIndex {
284 int total = all_tp_builders.Length;
285 if (CurrentTypeParameters != null) {
286 return total - CurrentTypeParameters.Length;
292 public virtual AssemblyDefinition DeclaringAssembly {
294 return Module.DeclaringAssembly;
298 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
300 return Module.DeclaringAssembly;
304 public TypeSpec Definition {
310 public bool HasMembersDefined {
312 return members_defined;
316 public TypeSpec[] Interfaces {
324 public override void Accept (StructuralVisitor visitor)
326 visitor.Visit (this);
329 public bool AddMember (MemberCore symbol)
331 return AddToContainer (symbol, symbol.MemberName.Basename);
334 public bool AddMember (MemberCore symbol, string name)
336 return AddToContainer (symbol, name);
339 protected virtual bool AddMemberType (TypeContainer ds)
341 return AddToContainer (ds, ds.Basename);
344 protected virtual void RemoveMemberType (TypeContainer ds)
346 RemoveFromContainer (ds.Basename);
349 public void AddConstant (Const constant)
351 if (!AddMember (constant))
354 if (constants == null)
355 constants = new List<MemberCore> ();
357 constants.Add (constant);
360 public TypeContainer AddTypeContainer (TypeContainer tc)
362 if (!AddMemberType (tc))
366 types = new List<TypeContainer> ();
372 public virtual TypeContainer AddPartial (TypeContainer next_part)
374 return AddPartial (next_part, next_part.Basename);
377 protected TypeContainer AddPartial (TypeContainer next_part, string name)
379 next_part.ModFlags |= Modifiers.PARTIAL;
380 TypeContainer tc = GetDefinition (name) as TypeContainer;
382 return AddTypeContainer (next_part);
384 if ((tc.ModFlags & Modifiers.PARTIAL) == 0) {
385 Report.SymbolRelatedToPreviousError (next_part);
386 Error_MissingPartialModifier (tc);
389 if (tc.Kind != next_part.Kind) {
390 Report.SymbolRelatedToPreviousError (tc);
391 Report.Error (261, next_part.Location,
392 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
393 next_part.GetSignatureForError ());
396 if ((tc.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
397 ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
398 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
399 Report.SymbolRelatedToPreviousError (tc);
400 Report.Error (262, next_part.Location,
401 "Partial declarations of `{0}' have conflicting accessibility modifiers",
402 next_part.GetSignatureForError ());
405 if (tc.partial_parts == null)
406 tc.partial_parts = new List<TypeContainer> (1);
408 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
409 tc.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
410 } else if ((tc.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
411 tc.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
412 tc.ModFlags |= next_part.ModFlags;
414 tc.ModFlags |= next_part.ModFlags;
417 tc.spec.Modifiers = tc.ModFlags;
419 if (next_part.attributes != null) {
420 if (tc.attributes == null)
421 tc.attributes = next_part.attributes;
423 tc.attributes.AddAttributes (next_part.attributes.Attrs);
426 next_part.PartialContainer = tc;
427 tc.partial_parts.Add (next_part);
431 public virtual void RemoveTypeContainer (TypeContainer next_part)
434 types.Remove (next_part);
436 Cache.Remove (next_part.Basename);
437 RemoveMemberType (next_part);
440 public void AddDelegate (Delegate d)
442 AddTypeContainer (d);
445 private void AddMemberToList (MemberCore mc, List<MemberCore> alist, bool isexplicit)
447 if (ordered_explicit_member_list == null) {
448 ordered_explicit_member_list = new List<MemberCore> ();
449 ordered_member_list = new List<MemberCore> ();
453 if (Kind == MemberKind.Interface) {
454 Report.Error (541, mc.Location,
455 "`{0}': explicit interface declaration can only be declared in a class or struct",
456 mc.GetSignatureForError ());
459 ordered_explicit_member_list.Add (mc);
460 alist.Insert (0, mc);
462 ordered_member_list.Add (mc);
468 public void AddMethod (MethodOrOperator method)
470 if (!AddToContainer (method, method.MemberName.Basename))
474 methods = new List<MemberCore> ();
476 if (method.MemberName.Left != null)
477 AddMemberToList (method, methods, true);
479 AddMemberToList (method, methods, false);
482 public void AddConstructor (Constructor c)
484 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
485 if (!AddToContainer (c, is_static ? Constructor.ConstructorName : Constructor.TypeConstructorName))
488 if (is_static && c.ParameterInfo.IsEmpty){
489 if (default_static_constructor != null) {
490 Report.SymbolRelatedToPreviousError (default_static_constructor);
491 Report.Error (111, c.Location,
492 "A member `{0}' is already defined. Rename this member or use different parameter types",
493 c.GetSignatureForError ());
497 default_static_constructor = c;
499 if (c.ParameterInfo.IsEmpty)
500 default_constructor = c;
502 if (instance_constructors == null)
503 instance_constructors = new List<Constructor> ();
505 instance_constructors.Add (c);
509 public bool AddField (FieldBase field)
511 if (!AddMember (field))
515 fields = new List<FieldBase> ();
519 if ((field.ModFlags & Modifiers.STATIC) != 0)
522 if (first_nonstatic_field == null) {
523 first_nonstatic_field = field;
527 if (Kind == MemberKind.Struct && first_nonstatic_field.Parent != field.Parent) {
528 Report.SymbolRelatedToPreviousError (first_nonstatic_field.Parent);
529 Report.Warning (282, 3, field.Location,
530 "struct instance field `{0}' found in different declaration from instance field `{1}'",
531 field.GetSignatureForError (), first_nonstatic_field.GetSignatureForError ());
536 public void AddProperty (Property prop)
538 if (!AddMember (prop))
541 if (properties == null)
542 properties = new List<MemberCore> ();
544 if (prop.MemberName.Left != null)
545 AddMemberToList (prop, properties, true);
547 AddMemberToList (prop, properties, false);
550 public void AddEvent (Event e)
556 events = new List<MemberCore> ();
562 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
564 public void AddIndexer (Indexer i)
566 if (indexers == null)
567 indexers = new List<MemberCore> ();
569 if (i.IsExplicitImpl)
570 AddMemberToList (i, indexers, true);
572 AddMemberToList (i, indexers, false);
575 public void AddOperator (Operator op)
580 if (operators == null)
581 operators = new List<MemberCore> ();
586 public void AddCompilerGeneratedClass (CompilerGeneratedClass c)
588 if (compiler_generated == null)
589 compiler_generated = new List<CompilerGeneratedClass> ();
591 compiler_generated.Add (c);
594 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
596 if (a.Type == pa.DefaultMember) {
597 if (Indexers != null) {
598 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
603 if (a.Type == pa.Required) {
604 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
608 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
611 public override AttributeTargets AttributeTargets {
613 throw new NotSupportedException ();
617 public IList<TypeContainer> Types {
623 public IList<MemberCore> Methods {
629 public IList<MemberCore> Constants {
635 public TypeSpec BaseType {
637 return spec.BaseType;
641 public IList<FieldBase> Fields {
647 public IList<Constructor> InstanceConstructors {
649 return instance_constructors;
653 public IList<MemberCore> Properties {
659 public IList<MemberCore> Events {
665 public IList<MemberCore> Indexers {
671 public IList<MemberCore> Operators {
677 protected override TypeAttributes TypeAttr {
679 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
683 public int TypeParametersCount {
685 return MemberName.Arity;
689 TypeParameterSpec[] ITypeDefinition.TypeParameters {
691 // TODO MemberCache: this is going to hurt
692 return PartialContainer.type_params.Select (l => l.Type).ToArray ();
696 public string GetAttributeDefaultMember ()
698 return indexers == null ? DefaultIndexerName : indexer_name;
701 public bool IsComImport {
703 if (OptAttributes == null)
706 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
710 string ITypeDefinition.Namespace {
712 return NamespaceEntry.NS.MemberName.GetSignatureForError ();
716 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
718 if ((field.ModFlags & Modifiers.STATIC) != 0){
719 if (initialized_static_fields == null) {
720 PartialContainer.HasStaticFieldInitializer = true;
721 initialized_static_fields = new List<FieldInitializer> (4);
724 initialized_static_fields.Add (expression);
726 if (initialized_fields == null)
727 initialized_fields = new List<FieldInitializer> (4);
729 initialized_fields.Add (expression);
733 public void ResolveFieldInitializers (BlockContext ec)
735 if (partial_parts != null) {
736 foreach (TypeContainer part in partial_parts) {
737 part.DoResolveFieldInitializers (ec);
740 DoResolveFieldInitializers (ec);
743 void DoResolveFieldInitializers (BlockContext ec)
746 if (initialized_static_fields == null)
749 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
751 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
752 for (i = 0; i < initialized_static_fields.Count; ++i) {
753 FieldInitializer fi = initialized_static_fields [i];
754 ExpressionStatement s = fi.ResolveStatement (ec);
756 s = EmptyExpressionStatement.Instance;
757 } else if (!fi.IsSideEffectFree) {
758 has_complex_initializer |= true;
764 for (i = 0; i < initialized_static_fields.Count; ++i) {
765 FieldInitializer fi = initialized_static_fields [i];
767 // Need special check to not optimize code like this
768 // static int a = b = 5;
771 if (!has_complex_initializer && fi.IsDefaultInitializer)
774 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
780 if (initialized_fields == null)
783 for (int i = 0; i < initialized_fields.Count; ++i) {
784 FieldInitializer fi = initialized_fields [i];
785 ExpressionStatement s = fi.ResolveStatement (ec);
790 // Field is re-initialized to its default value => removed
792 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
795 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
799 public override string DocComment {
811 public PendingImplementation PendingImplementations {
812 get { return pending; }
815 internal override void GenerateDocComment (DocumentationBuilder builder)
817 base.GenerateDocComment (builder);
819 if (DefaultStaticConstructor != null)
820 DefaultStaticConstructor.GenerateDocComment (builder);
822 if (InstanceConstructors != null)
823 foreach (Constructor c in InstanceConstructors)
824 c.GenerateDocComment (builder);
827 foreach (TypeContainer tc in Types)
828 tc.GenerateDocComment (builder);
830 if (Constants != null)
831 foreach (Const c in Constants)
832 c.GenerateDocComment (builder);
835 foreach (FieldBase f in Fields)
836 f.GenerateDocComment (builder);
839 foreach (Event e in Events)
840 e.GenerateDocComment (builder);
842 if (Indexers != null)
843 foreach (Indexer ix in Indexers)
844 ix.GenerateDocComment (builder);
846 if (Properties != null)
847 foreach (Property p in Properties)
848 p.GenerateDocComment (builder);
851 foreach (MethodOrOperator m in Methods)
852 m.GenerateDocComment (builder);
854 if (Operators != null)
855 foreach (Operator o in Operators)
856 o.GenerateDocComment (builder);
859 public TypeSpec GetAttributeCoClass ()
861 if (OptAttributes == null)
864 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
868 return a.GetCoClassAttributeValue ();
871 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
874 if (OptAttributes != null) {
875 a = OptAttributes.Search (pa);
881 return a.GetAttributeUsageAttribute ();
884 public virtual void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
886 // FIXME: get rid of partial_parts and store lists of bases of each part here
887 // assumed, not verified: 'part' is in 'partial_parts'
888 ((TypeContainer) part).type_bases = bases;
892 /// This function computes the Base class and also the
893 /// list of interfaces that the class or struct @c implements.
895 /// The return value is an array (might be null) of
896 /// interfaces implemented (as Types).
898 /// The @base_class argument is set to the base object or null
899 /// if this is `System.Object'.
901 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
904 if (type_bases == null)
907 int count = type_bases.Count;
908 TypeSpec[] ifaces = null;
909 var base_context = new BaseContext (this);
910 for (int i = 0, j = 0; i < count; i++){
911 FullNamedExpression fne = type_bases [i];
913 var fne_resolved = fne.ResolveAsType (base_context);
914 if (fne_resolved == null)
917 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
918 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
919 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
920 GetSignatureForError ());
925 base_type = fne_resolved;
931 ifaces = new TypeSpec [count - i];
933 if (fne_resolved.IsInterface) {
934 for (int ii = 0; ii < j; ++ii) {
935 if (fne_resolved == ifaces [ii]) {
936 Report.Error (528, Location, "`{0}' is already listed in interface list",
937 fne_resolved.GetSignatureForError ());
942 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
943 Report.Error (61, fne.Location,
944 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
945 fne_resolved.GetSignatureForError (), GetSignatureForError ());
948 Report.SymbolRelatedToPreviousError (fne_resolved);
949 if (Kind != MemberKind.Class) {
950 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
951 } else if (base_class != null)
952 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
953 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
955 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
956 GetSignatureForError (), fne_resolved.GetSignatureForError ());
960 ifaces [j++] = fne_resolved;
966 TypeSpec[] GetNormalPartialBases ()
968 var ifaces = new List<TypeSpec> (0);
969 if (iface_exprs != null)
970 ifaces.AddRange (iface_exprs);
972 foreach (TypeContainer part in partial_parts) {
973 FullNamedExpression new_base_class;
974 var new_ifaces = part.ResolveBaseTypes (out new_base_class);
975 if (new_base_class != null) {
976 if (base_type_expr != null && part.base_type != base_type) {
977 Report.SymbolRelatedToPreviousError (new_base_class.Location, "");
978 Report.Error (263, part.Location,
979 "Partial declarations of `{0}' must not specify different base classes",
980 part.GetSignatureForError ());
982 base_type_expr = new_base_class;
983 base_type = part.base_type;
987 if (new_ifaces == null)
990 foreach (var iface in new_ifaces) {
991 if (ifaces.Contains (iface))
998 if (ifaces.Count == 0)
1001 return ifaces.ToArray ();
1005 // Checks that some operators come in pairs:
1011 // They are matched based on the return type and the argument types
1013 void CheckPairedOperators ()
1015 bool has_equality_or_inequality = false;
1016 var operators = this.operators.ToArray ();
1017 bool[] has_pair = new bool[operators.Length];
1019 for (int i = 0; i < operators.Length; ++i) {
1020 if (operators[i] == null)
1023 Operator o_a = (Operator) operators[i];
1024 Operator.OpType o_type = o_a.OperatorType;
1025 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1026 has_equality_or_inequality = true;
1028 Operator.OpType matching_type = o_a.GetMatchingOperator ();
1029 if (matching_type == Operator.OpType.TOP) {
1030 operators[i] = null;
1034 for (int ii = 0; ii < operators.Length; ++ii) {
1035 Operator o_b = (Operator) operators[ii];
1036 if (o_b == null || o_b.OperatorType != matching_type)
1039 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1042 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1045 operators[i] = null;
1048 // Used to ignore duplicate user conversions
1050 has_pair[ii] = true;
1054 for (int i = 0; i < operators.Length; ++i) {
1055 if (operators[i] == null || has_pair[i])
1058 Operator o = (Operator) operators [i];
1059 Report.Error (216, o.Location,
1060 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1061 o.GetSignatureForError (), Operator.GetName (o.GetMatchingOperator ()));
1064 if (has_equality_or_inequality) {
1065 if (Methods == null || !HasEquals)
1066 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1067 GetSignatureForError ());
1069 if (Methods == null || !HasGetHashCode)
1070 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1071 GetSignatureForError ());
1075 bool CreateTypeBuilder ()
1078 // Sets .size to 1 for structs with no instance fields
1080 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
1083 TypeBuilder = Module.CreateBuilder (Name, TypeAttr, type_size);
1085 TypeBuilder = Parent.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1088 if (DeclaringAssembly.Importer != null)
1089 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1091 spec.SetMetaInfo (TypeBuilder);
1092 spec.MemberCache = new MemberCache (this);
1093 spec.DeclaringType = Parent.CurrentType;
1096 Parent.MemberCache.AddMember (spec);
1099 string[] param_names = new string[TypeParameters.Length];
1100 for (int i = 0; i < TypeParameters.Length; i++)
1101 param_names [i] = TypeParameters[i].Name;
1103 all_tp_builders = TypeBuilder.DefineGenericParameters (param_names);
1105 int offset = CurrentTypeParametersStartIndex;
1106 for (int i = offset; i < all_tp_builders.Length; i++) {
1107 CurrentTypeParameters [i - offset].Define (all_tp_builders [i], spec);
1115 // Creates a proxy base method call inside this container for hoisted base member calls
1117 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1119 Method proxy_method;
1122 // One proxy per base method is enough
1124 if (hoisted_base_call_proxies == null) {
1125 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1126 proxy_method = null;
1128 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1131 if (proxy_method == null) {
1132 string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1133 var base_parameters = new Parameter[method.Parameters.Count];
1134 for (int i = 0; i < base_parameters.Length; ++i) {
1135 var base_param = method.Parameters.FixedParameters[i];
1136 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1137 base_param.Name, base_param.ModFlags, null, Location);
1138 base_parameters[i].Resolve (this, i);
1141 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1142 if (method.Parameters.HasArglist) {
1143 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1144 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1147 GenericMethod generic_method;
1148 MemberName member_name;
1149 TypeArguments targs = null;
1150 if (method.IsGeneric) {
1152 // Copy all base generic method type parameters info
1154 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1155 var type_params = new TypeParameter[hoisted_tparams.Length];
1156 targs = new TypeArguments ();
1157 targs.Arguments = new TypeSpec[type_params.Length];
1158 for (int i = 0; i < type_params.Length; ++i) {
1159 var tp = hoisted_tparams[i];
1160 targs.Add (new TypeParameterName (tp.Name, null, Location));
1161 targs.Arguments[i] = tp;
1162 type_params[i] = new TypeParameter (tp, this, null, new MemberName (tp.Name), null);
1165 member_name = new MemberName (name, targs, Location);
1166 generic_method = new GenericMethod (NamespaceEntry, this, member_name, type_params,
1167 new TypeExpression (method.ReturnType, Location), cloned_params);
1169 member_name = new MemberName (name);
1170 generic_method = null;
1173 // Compiler generated proxy
1174 proxy_method = new Method (this, generic_method, new TypeExpression (method.ReturnType, Location),
1175 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1176 member_name, cloned_params, null);
1178 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location);
1180 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1181 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1183 mg.SetTypeArguments (rc, targs);
1185 // Get all the method parameters and pass them as arguments
1186 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1187 Statement statement;
1188 if (method.ReturnType.Kind == MemberKind.Void)
1189 statement = new StatementExpression (real_base_call);
1191 statement = new Return (real_base_call, Location);
1193 block.AddStatement (statement);
1194 proxy_method.Block = block;
1196 methods.Add (proxy_method);
1197 proxy_method.Define ();
1199 hoisted_base_call_proxies.Add (method, proxy_method);
1202 return proxy_method.Spec;
1205 bool DefineBaseTypes ()
1207 iface_exprs = ResolveBaseTypes (out base_type_expr);
1208 if (partial_parts != null) {
1209 iface_exprs = GetNormalPartialBases ();
1212 var cycle = CheckRecursiveDefinition (this);
1213 if (cycle != null) {
1214 Report.SymbolRelatedToPreviousError (cycle);
1215 if (this is Interface) {
1216 Report.Error (529, Location,
1217 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1218 GetSignatureForError (), cycle.GetSignatureForError ());
1222 Report.Error (146, Location,
1223 "Circular base class dependency involving `{0}' and `{1}'",
1224 GetSignatureForError (), cycle.GetSignatureForError ());
1230 if (iface_exprs != null) {
1231 foreach (var iface_type in iface_exprs) {
1232 // Prevents a crash, the interface might not have been resolved: 442144
1233 if (iface_type == null)
1236 if (!spec.AddInterfaceDefined (iface_type))
1239 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1241 // Ensure the base is always setup
1242 var compiled_iface = iface_type.MemberDefinition as Interface;
1243 if (compiled_iface != null) {
1244 // TODO: Need DefineBaseType only
1245 compiled_iface.DefineType ();
1248 if (iface_type.Interfaces != null) {
1249 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1250 for (int i = 0; i < base_ifaces.Count; ++i) {
1251 var ii_iface_type = base_ifaces[i];
1252 if (spec.AddInterfaceDefined (ii_iface_type)) {
1253 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1255 if (ii_iface_type.Interfaces != null)
1256 base_ifaces.AddRange (ii_iface_type.Interfaces);
1263 if (Kind == MemberKind.Interface) {
1264 spec.BaseType = Compiler.BuiltinTypes.Object;
1268 if (base_type != null) {
1269 spec.BaseType = base_type;
1271 // Set base type after type creation
1272 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1274 TypeBuilder.SetParent (null);
1280 public virtual void DefineConstants ()
1282 if (constants != null) {
1283 foreach (Const c in constants) {
1288 if (instance_constructors != null) {
1289 foreach (MethodCore m in instance_constructors) {
1290 var p = m.ParameterInfo;
1292 p.ResolveDefaultValues (m);
1297 if (methods != null) {
1298 foreach (MethodCore m in methods) {
1299 var p = m.ParameterInfo;
1301 p.ResolveDefaultValues (m);
1306 if (indexers != null) {
1307 foreach (Indexer i in indexers) {
1308 i.ParameterInfo.ResolveDefaultValues (i);
1312 if (types != null) {
1313 foreach (var t in types)
1314 t.DefineConstants ();
1319 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1321 public bool CreateType ()
1323 if (TypeBuilder != null)
1329 if (!CreateTypeBuilder ()) {
1334 if (partial_parts != null) {
1335 foreach (TypeContainer part in partial_parts) {
1337 part.current_type = current_type;
1338 part.TypeBuilder = TypeBuilder;
1342 if (Types != null) {
1343 foreach (TypeContainer tc in Types) {
1351 public override void DefineType ()
1358 type_defined = true;
1360 // TODO: Driver resolves only first level of namespace, do the rest here for now
1361 if (IsTopLevel && (ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
1362 NamespaceEntry.Resolve ();
1365 if (!DefineBaseTypes ()) {
1370 if (!DefineNestedTypes ()) {
1376 public override void SetParameterInfo (List<Constraints> constraints_list)
1378 base.SetParameterInfo (constraints_list);
1380 if (PartialContainer.CurrentTypeParameters == null || PartialContainer == this)
1383 TypeParameter[] tc_names = PartialContainer.CurrentTypeParameters;
1384 for (int i = 0; i < tc_names.Length; ++i) {
1385 if (tc_names [i].Name != type_params [i].Name) {
1386 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1387 Report.Error (264, Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
1388 GetSignatureForError ());
1392 if (tc_names [i].Variance != type_params [i].Variance) {
1393 Report.SymbolRelatedToPreviousError (PartialContainer.Location, "");
1394 Report.Error (1067, Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
1395 GetSignatureForError ());
1402 // Replaces normal spec with predefined one when compiling corlib
1403 // and this type container defines predefined type
1405 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1407 // When compiling build-in types we start with two
1408 // version of same type. One is of BuiltinTypeSpec and
1409 // second one is ordinary TypeSpec. The unification
1410 // happens at later stage when we know which type
1411 // really matches the builtin type signature. However
1412 // that means TypeSpec create during CreateType of this
1413 // type has to be replaced with builtin one
1415 spec.SetMetaInfo (TypeBuilder);
1416 spec.MemberCache = this.spec.MemberCache;
1417 spec.DeclaringType = this.spec.DeclaringType;
1420 current_type = null;
1423 void UpdateTypeParameterConstraints (TypeContainer part)
1425 TypeParameter[] current_params = type_params;
1426 for (int i = 0; i < current_params.Length; i++) {
1427 if (current_params [i].AddPartialConstraints (part, part.type_params [i]))
1430 Report.SymbolRelatedToPreviousError (Location, "");
1431 Report.Error (265, part.Location,
1432 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1433 GetSignatureForError (), current_params [i].GetSignatureForError ());
1437 public bool ResolveTypeParameters ()
1439 if (!DoResolveTypeParameters ())
1442 if (types != null) {
1443 foreach (var type in types)
1444 if (!type.ResolveTypeParameters ())
1448 if (compiler_generated != null) {
1449 foreach (CompilerGeneratedClass c in compiler_generated)
1450 if (!c.ResolveTypeParameters ())
1457 protected virtual bool DoResolveTypeParameters ()
1459 if (CurrentTypeParameters == null)
1462 if (PartialContainer != this)
1463 throw new InternalErrorException ();
1465 var base_context = new BaseContext (this);
1466 foreach (TypeParameter type_param in CurrentTypeParameters) {
1467 if (!type_param.ResolveConstraints (base_context)) {
1473 if (partial_parts != null) {
1474 foreach (TypeContainer part in partial_parts)
1475 UpdateTypeParameterConstraints (part);
1481 protected virtual bool DefineNestedTypes ()
1483 if (Types != null) {
1484 foreach (TypeContainer tc in Types)
1491 TypeSpec CheckRecursiveDefinition (TypeContainer tc)
1493 if (InTransit != null)
1498 if (base_type != null) {
1499 var ptc = base_type.MemberDefinition as TypeContainer;
1500 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1504 if (iface_exprs != null) {
1505 foreach (var iface in iface_exprs) {
1506 // the interface might not have been resolved, prevents a crash, see #442144
1509 var ptc = iface.MemberDefinition as Interface;
1510 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1515 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1523 /// Populates our TypeBuilder with fields and methods
1525 public sealed override bool Define ()
1527 if (members_defined)
1528 return members_defined_ok;
1530 members_defined_ok = DoDefineMembers ();
1531 members_defined = true;
1533 if (types != null) {
1534 foreach (var nested in types)
1538 return members_defined_ok;
1541 protected virtual bool DoDefineMembers ()
1543 if (iface_exprs != null) {
1544 foreach (var iface_type in iface_exprs) {
1545 if (iface_type == null)
1548 // Ensure the base is always setup
1549 var compiled_iface = iface_type.MemberDefinition as Interface;
1550 if (compiled_iface != null)
1551 compiled_iface.Define ();
1553 if (Kind == MemberKind.Interface)
1554 MemberCache.AddInterface (iface_type);
1556 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1557 if (oa != null && !IsObsolete)
1558 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1560 if (iface_type.Arity > 0) {
1561 // TODO: passing `this' is wrong, should be base type iface instead
1562 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1564 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1565 Report.Error (1966, Location,
1566 "`{0}': cannot implement a dynamic interface `{1}'",
1567 GetSignatureForError (), iface_type.GetSignatureForError ());
1572 if (iface_type.IsGenericOrParentIsGeneric) {
1573 if (spec.Interfaces != null) {
1574 foreach (var prev_iface in iface_exprs) {
1575 if (prev_iface == iface_type)
1578 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1581 Report.Error (695, Location,
1582 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1583 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1590 if (base_type != null) {
1592 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1594 if (base_type_expr != null) {
1595 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1596 if (obsolete_attr != null && !IsObsolete)
1597 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1599 if (IsGeneric && base_type.IsAttribute) {
1600 Report.Error (698, base_type_expr.Location,
1601 "A generic type cannot derive from `{0}' because it is an attribute class",
1602 base_type.GetSignatureForError ());
1606 if (base_type.Interfaces != null) {
1607 foreach (var iface in base_type.Interfaces)
1608 spec.AddInterface (iface);
1611 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1612 if (baseContainer != null) {
1613 baseContainer.Define ();
1616 // It can trigger define of this type (for generic types only)
1618 if (HasMembersDefined)
1623 DefineContainerMembers (constants);
1624 DefineContainerMembers (fields);
1626 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1627 pending = PendingImplementation.GetPendingImplementations (this);
1629 if (requires_delayed_unmanagedtype_check) {
1630 requires_delayed_unmanagedtype_check = false;
1631 foreach (FieldBase f in fields) {
1632 if (f.MemberType != null && f.MemberType.IsPointer)
1633 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1639 // Constructors are not in the defined_names array
1641 DefineContainerMembers (instance_constructors);
1643 DefineContainerMembers (events);
1644 DefineContainerMembers (ordered_explicit_member_list);
1645 DefineContainerMembers (ordered_member_list);
1647 if (operators != null) {
1648 DefineContainerMembers (operators);
1649 CheckPairedOperators ();
1652 ComputeIndexerName();
1653 CheckEqualsAndGetHashCode();
1655 if (Kind == MemberKind.Interface && iface_exprs != null) {
1656 MemberCache.RemoveHiddenMembers (spec);
1662 protected virtual void DefineContainerMembers (System.Collections.IList mcal) // IList<MemberCore>
1665 for (int i = 0; i < mcal.Count; ++i) {
1666 MemberCore mc = (MemberCore) mcal[i];
1669 } catch (Exception e) {
1670 throw new InternalErrorException (mc, e);
1676 protected virtual void ComputeIndexerName ()
1678 if (indexers == null)
1681 string class_indexer_name = null;
1684 // If there's both an explicit and an implicit interface implementation, the
1685 // explicit one actually implements the interface while the other one is just
1686 // a normal indexer. See bug #37714.
1689 // Invariant maintained by AddIndexer(): All explicit interface indexers precede normal indexers
1690 foreach (Indexer i in indexers) {
1691 if (i.InterfaceType != null) {
1692 if (seen_normal_indexers)
1693 throw new Exception ("Internal Error: 'Indexers' array not sorted properly.");
1697 seen_normal_indexers = true;
1699 if (class_indexer_name == null) {
1700 class_indexer_name = i.ShortName;
1704 if (i.ShortName != class_indexer_name)
1705 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");
1708 if (class_indexer_name != null)
1709 indexer_name = class_indexer_name;
1712 void EmitIndexerName ()
1714 if (!seen_normal_indexers)
1717 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1721 var encoder = new AttributeEncoder ();
1722 encoder.Encode (GetAttributeDefaultMember ());
1723 encoder.EncodeEmptyNamedArguments ();
1725 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1728 protected virtual void CheckEqualsAndGetHashCode ()
1730 if (methods == null)
1733 if (HasEquals && !HasGetHashCode) {
1734 Report.Warning (659, 3, this.Location, "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", this.GetSignatureForError ());
1738 // Indicated whether container has StructLayout attribute set Explicit
1739 public bool HasExplicitLayout {
1740 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
1741 set { caching_flags |= Flags.HasExplicitLayout; }
1744 public bool HasStructLayout {
1745 get { return (caching_flags & Flags.HasStructLayout) != 0; }
1746 set { caching_flags |= Flags.HasStructLayout; }
1749 public MemberCache MemberCache {
1751 return spec.MemberCache;
1755 void CheckMemberUsage (List<MemberCore> al, string member_type)
1760 foreach (MemberCore mc in al) {
1761 if ((mc.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE)
1764 if ((mc.ModFlags & Modifiers.PARTIAL) != 0)
1767 if (!mc.IsUsed && (mc.caching_flags & Flags.Excluded) == 0) {
1768 Report.Warning (169, 3, mc.Location, "The private {0} `{1}' is never used", member_type, mc.GetSignatureForError ());
1773 public virtual void VerifyMembers ()
1776 // Check for internal or private fields that were never assigned
1778 if (Report.WarningLevel >= 3) {
1779 if (Compiler.Settings.EnhancedWarnings) {
1780 CheckMemberUsage (properties, "property");
1781 CheckMemberUsage (methods, "method");
1782 CheckMemberUsage (constants, "constant");
1785 if (fields != null){
1786 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1787 foreach (FieldBase f in fields) {
1788 if ((f.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1789 if (is_type_exposed)
1796 if ((f.caching_flags & Flags.IsAssigned) == 0)
1797 Report.Warning (169, 3, f.Location, "The private field `{0}' is never used", f.GetSignatureForError ());
1799 Report.Warning (414, 3, f.Location, "The private field `{0}' is assigned but its value is never used",
1800 f.GetSignatureForError ());
1805 if ((f.caching_flags & Flags.IsAssigned) != 0)
1809 // Only report 649 on level 4
1811 if (Report.WarningLevel < 4)
1815 // Don't be pendatic over serializable attributes
1817 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1820 Constant c = New.Constantify (f.MemberType, f.Location);
1823 value = c.GetValueAsLiteral ();
1824 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1827 // Ignore this warning for struct value fields (they are always initialized)
1828 if (f.MemberType.IsStruct)
1835 value = " `" + value + "'";
1837 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1838 f.GetSignatureForError (), value);
1844 public override void Emit ()
1847 MemberSpec candidate;
1848 bool overrides = false;
1849 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1850 if (conflict_symbol == null && candidate == null) {
1851 if ((ModFlags & Modifiers.NEW) != 0)
1852 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1853 GetSignatureForError ());
1855 if ((ModFlags & Modifiers.NEW) == 0) {
1856 if (candidate == null)
1857 candidate = conflict_symbol;
1859 Report.SymbolRelatedToPreviousError (candidate);
1860 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1861 GetSignatureForError (), candidate.GetSignatureForError ());
1866 // Run constraints check on all possible generic types
1867 if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
1868 if (base_type != null && base_type_expr != null) {
1869 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1872 if (iface_exprs != null) {
1873 foreach (var iface_type in iface_exprs) {
1874 if (iface_type == null)
1877 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
1882 if (all_tp_builders != null) {
1883 int current_starts_index = CurrentTypeParametersStartIndex;
1884 for (int i = 0; i < all_tp_builders.Length; i++) {
1885 if (i < current_starts_index) {
1886 TypeParameters[i].EmitConstraints (all_tp_builders [i]);
1888 var tp = CurrentTypeParameters [i - current_starts_index];
1889 tp.CheckGenericConstraints (!IsObsolete);
1895 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1896 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
1899 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
1900 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
1906 // TODO: move to ClassOrStruct
1907 void EmitConstructors ()
1909 if (instance_constructors == null)
1912 if (spec.IsAttribute && IsExposedFromAssembly () && Compiler.Settings.VerifyClsCompliance && IsClsComplianceRequired ()) {
1913 bool has_compliant_args = false;
1915 foreach (Constructor c in instance_constructors) {
1919 catch (Exception e) {
1920 throw new InternalErrorException (c, e);
1923 if (has_compliant_args)
1926 has_compliant_args = c.HasCompliantArgs;
1928 if (!has_compliant_args)
1929 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
1931 foreach (Constructor c in instance_constructors) {
1935 catch (Exception e) {
1936 throw new InternalErrorException (c, e);
1943 /// Emits the code, this step is performed after all
1944 /// the types, enumerations, constructors
1946 public virtual void EmitType ()
1948 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1951 if (OptAttributes != null)
1952 OptAttributes.Emit ();
1956 EmitConstructors ();
1958 if (constants != null)
1959 foreach (Const con in constants)
1962 if (default_static_constructor != null)
1963 default_static_constructor.Emit ();
1965 if (operators != null)
1966 foreach (Operator o in operators)
1969 if (properties != null)
1970 foreach (Property p in properties)
1973 if (indexers != null) {
1974 foreach (Indexer indx in indexers)
1979 if (events != null){
1980 foreach (Event e in Events)
1984 if (methods != null) {
1985 for (int i = 0; i < methods.Count; ++i)
1986 ((MethodOrOperator) methods [i]).Emit ();
1990 foreach (FieldBase f in fields)
1993 if (types != null) {
1994 foreach (TypeContainer t in types)
1998 if (pending != null)
1999 pending.VerifyPendingMethods ();
2001 if (Report.Errors > 0)
2004 if (compiler_generated != null) {
2005 for (int i = 0; i < compiler_generated.Count; ++i)
2006 compiler_generated [i].EmitType ();
2010 public virtual void CloseType ()
2012 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2015 // Close base type container first to avoid TypeLoadException
2016 if (spec.BaseType != null) {
2017 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2018 if (btype != null) {
2021 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2027 caching_flags |= Flags.CloseTypeCreated;
2028 TypeBuilder.CreateType ();
2029 } catch (TypeLoadException){
2031 // This is fine, the code still created the type
2033 // Report.Warning (-20, "Exception while creating class: " + TypeBuilder.Name);
2034 // Console.WriteLine (e.Message);
2035 } catch (Exception e) {
2036 throw new InternalErrorException (this, e);
2040 foreach (TypeContainer tc in Types)
2044 if (compiler_generated != null)
2045 foreach (CompilerGeneratedClass c in compiler_generated)
2049 initialized_fields = null;
2050 initialized_static_fields = null;
2052 ordered_explicit_member_list = null;
2053 ordered_member_list = null;
2058 compiler_generated = null;
2059 default_constructor = null;
2060 default_static_constructor = null;
2062 OptAttributes = null;
2066 // Performs the validation on a Method's modifiers (properties have
2067 // the same properties).
2069 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2071 public bool MethodModifiersValid (MemberCore mc)
2073 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2074 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2076 var flags = mc.ModFlags;
2079 // At most one of static, virtual or override
2081 if ((flags & Modifiers.STATIC) != 0){
2082 if ((flags & vao) != 0){
2083 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2084 mc.GetSignatureForError ());
2089 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2090 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2091 mc.GetSignatureForError ());
2096 // If the declaration includes the abstract modifier, then the
2097 // declaration does not include static, virtual or extern
2099 if ((flags & Modifiers.ABSTRACT) != 0){
2100 if ((flags & Modifiers.EXTERN) != 0){
2102 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2106 if ((flags & Modifiers.SEALED) != 0) {
2107 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2111 if ((flags & Modifiers.VIRTUAL) != 0){
2112 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2116 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2117 Report.SymbolRelatedToPreviousError (this);
2118 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2119 mc.GetSignatureForError (), GetSignatureForError ());
2124 if ((flags & Modifiers.PRIVATE) != 0){
2125 if ((flags & vao) != 0){
2126 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2131 if ((flags & Modifiers.SEALED) != 0){
2132 if ((flags & Modifiers.OVERRIDE) == 0){
2133 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2141 public Constructor DefaultStaticConstructor {
2142 get { return default_static_constructor; }
2145 protected override bool VerifyClsCompliance ()
2147 if (!base.VerifyClsCompliance ())
2150 // Check this name against other containers
2151 NamespaceEntry.NS.VerifyClsCompliance ();
2153 // Check all container names for user classes
2154 if (Kind != MemberKind.Delegate)
2155 MemberCache.VerifyClsCompliance (Definition, Report);
2157 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2158 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2159 GetSignatureForError (), BaseType.GetSignatureForError ());
2165 /// Performs checks for an explicit interface implementation. First it
2166 /// checks whether the `interface_type' is a base inteface implementation.
2167 /// Then it checks whether `name' exists in the interface type.
2169 public bool VerifyImplements (InterfaceMemberBase mb)
2171 var ifaces = spec.Interfaces;
2172 if (ifaces != null) {
2173 foreach (TypeSpec t in ifaces){
2174 if (t == mb.InterfaceType)
2179 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2180 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2181 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2186 // Used for visiblity checks to tests whether this definition shares
2187 // base type baseType, it does member-definition search
2189 public bool IsBaseTypeDefinition (TypeSpec baseType)
2191 // RootContext check
2192 if (TypeBuilder == null)
2197 if (type.MemberDefinition == baseType.MemberDefinition)
2200 type = type.BaseType;
2201 } while (type != null);
2206 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2208 return Module.DeclaringAssembly == assembly;
2211 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2213 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2217 // Public function used to locate types.
2219 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2221 // Returns: Type or null if they type can not be found.
2223 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2225 FullNamedExpression e;
2226 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2232 TypeParameter[] tp = CurrentTypeParameters;
2234 TypeParameter tparam = TypeParameter.FindTypeParameter (tp, name);
2236 e = new TypeParameterExpr (tparam, Location.Null);
2241 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2243 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2244 e = new TypeExpression (t, Location.Null);
2245 else if (Parent != null) {
2246 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2248 int errors = Report.Errors;
2250 e = NamespaceEntry.LookupNamespaceOrType (name, arity, mode, loc);
2252 if (errors != Report.Errors)
2257 // TODO MemberCache: How to cache arity stuff ?
2258 if (arity == 0 && mode == LookupMode.Normal)
2264 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2266 // TODO: GenericMethod only
2267 if (PartialContainer == null)
2270 // Has any nested type
2271 // Does not work, because base type can have
2272 //if (PartialContainer.Types == null)
2275 var container = PartialContainer.CurrentType;
2277 // Is not Root container
2278 if (container == null)
2281 return MemberCache.FindNestedType (container, name, arity);
2284 public void Mark_HasEquals ()
2286 cached_method |= CachedMethods.Equals;
2289 public void Mark_HasGetHashCode ()
2291 cached_method |= CachedMethods.GetHashCode;
2295 /// Method container contains Equals method
2297 public bool HasEquals {
2299 return (cached_method & CachedMethods.Equals) != 0;
2304 /// Method container contains GetHashCode method
2306 public bool HasGetHashCode {
2308 return (cached_method & CachedMethods.GetHashCode) != 0;
2312 public bool HasStaticFieldInitializer {
2314 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2318 cached_method |= CachedMethods.HasStaticFieldInitializer;
2320 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2324 public override string DocCommentHeader {
2325 get { return "T:"; }
2329 public abstract class ClassOrStruct : TypeContainer
2331 SecurityType declarative_security;
2333 public ClassOrStruct (NamespaceContainer ns, DeclSpace parent,
2334 MemberName name, Attributes attrs, MemberKind kind)
2335 : base (ns, parent, name, attrs, kind)
2339 protected override bool AddToContainer (MemberCore symbol, string name)
2341 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2342 if (symbol is TypeParameter) {
2343 Report.Error (694, symbol.Location,
2344 "Type parameter `{0}' has same name as containing type, or method",
2345 symbol.GetSignatureForError ());
2349 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2350 if (imb == null || !imb.IsExplicitImpl) {
2351 Report.SymbolRelatedToPreviousError (this);
2352 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2353 symbol.GetSignatureForError ());
2358 return base.AddToContainer (symbol, name);
2361 public override void VerifyMembers ()
2363 base.VerifyMembers ();
2365 if ((events != null) && Report.WarningLevel >= 3) {
2366 foreach (Event e in events){
2367 // Note: The event can be assigned from same class only, so we can report
2368 // this warning for all accessibility modes
2369 if ((e.caching_flags & Flags.IsUsed) == 0)
2370 Report.Warning (67, 3, e.Location, "The event `{0}' is never used", e.GetSignatureForError ());
2374 if (types != null) {
2375 foreach (var t in types)
2380 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2382 if (a.IsValidSecurityAttribute ()) {
2383 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2387 if (a.Type == pa.StructLayout) {
2388 PartialContainer.HasStructLayout = true;
2389 if (a.IsExplicitLayoutKind ())
2390 PartialContainer.HasExplicitLayout = true;
2393 if (a.Type == pa.Dynamic) {
2394 a.Error_MisusedDynamicAttribute ();
2398 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2402 /// Defines the default constructors
2404 protected void DefineDefaultConstructor (bool is_static)
2406 // The default instance constructor is public
2407 // If the class is abstract, the default constructor is protected
2408 // The default static constructor is private
2412 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2414 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2417 Constructor c = new Constructor (this, MemberName.Name, mods,
2418 null, ParametersCompiled.EmptyReadOnlyParameters,
2419 new GeneratedBaseInitializer (Location),
2423 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location);
2426 protected override bool DoDefineMembers ()
2428 CheckProtectedModifier ();
2430 base.DoDefineMembers ();
2432 if (default_static_constructor != null)
2433 default_static_constructor.Define ();
2438 public override void Emit ()
2440 if (default_static_constructor == null && PartialContainer.HasStaticFieldInitializer) {
2441 DefineDefaultConstructor (true);
2442 default_static_constructor.Define ();
2447 if (declarative_security != null) {
2448 foreach (var de in declarative_security) {
2450 TypeBuilder.__AddDeclarativeSecurity (de);
2452 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2458 public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
2460 DeclSpace top_level = Parent;
2461 if (top_level != null) {
2462 var methods = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity);
2463 if (methods != null) {
2464 return new ExtensionMethodCandidates (methods, NamespaceEntry, NamespaceEntry.NS) {
2465 HasUninspectedMembers = true
2470 return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity);
2473 protected override TypeAttributes TypeAttr {
2475 if (default_static_constructor == null)
2476 return base.TypeAttr | TypeAttributes.BeforeFieldInit;
2478 return base.TypeAttr;
2484 // TODO: should be sealed
2485 public class Class : ClassOrStruct {
2486 const Modifiers AllowedModifiers =
2489 Modifiers.PROTECTED |
2490 Modifiers.INTERNAL |
2492 Modifiers.ABSTRACT |
2497 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2499 public Class (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod,
2501 : base (ns, parent, name, attrs, MemberKind.Class)
2503 var accmods = (Parent == null || Parent.Parent == null) ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2504 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2505 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2508 public override void Accept (StructuralVisitor visitor)
2510 visitor.Visit (this);
2513 public override void AddBasesForPart (DeclSpace part, List<FullNamedExpression> bases)
2515 if (part.Name == "System.Object")
2516 Report.Error (537, part.Location,
2517 "The class System.Object cannot have a base class or implement an interface.");
2518 base.AddBasesForPart (part, bases);
2521 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2523 if (a.Type == pa.AttributeUsage) {
2524 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2525 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2529 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2530 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2534 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2535 a.Error_MissingGuidAttribute ();
2539 if (a.Type == pa.Extension) {
2540 a.Error_MisusedExtensionAttribute ();
2544 if (a.Type.IsConditionallyExcluded (Compiler, Location))
2547 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2550 public override AttributeTargets AttributeTargets {
2552 return AttributeTargets.Class;
2556 protected override void DefineContainerMembers (System.Collections.IList list)
2562 base.DefineContainerMembers (list);
2566 foreach (MemberCore m in list) {
2567 if (m is Operator) {
2568 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2572 if (m is Destructor) {
2573 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2578 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2582 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is Enum || m is Delegate)
2585 if (m is Constructor) {
2586 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2590 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2593 base.DefineContainerMembers (list);
2596 protected override bool DoDefineMembers ()
2598 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2599 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2602 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2603 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2606 if (InstanceConstructors == null && !IsStatic)
2607 DefineDefaultConstructor (false);
2609 return base.DoDefineMembers ();
2612 public override void Emit ()
2616 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2617 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2619 if (base_type != null && base_type.HasDynamicElement) {
2620 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2624 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2626 var ifaces = base.ResolveBaseTypes (out base_class);
2628 if (base_class == null) {
2629 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2630 base_type = Compiler.BuiltinTypes.Object;
2632 if (base_type.IsGenericParameter){
2633 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2634 GetSignatureForError (), base_type.GetSignatureForError ());
2635 } else if (base_type.IsStatic) {
2636 Report.SymbolRelatedToPreviousError (base_type);
2637 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2638 GetSignatureForError (), base_type.GetSignatureForError ());
2639 } else if (base_type.IsSealed) {
2640 Report.SymbolRelatedToPreviousError (base_type);
2641 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2642 GetSignatureForError (), base_type.GetSignatureForError ());
2643 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2644 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2645 GetSignatureForError (), base_type.GetSignatureForError ());
2648 switch (base_type.BuiltinType) {
2649 case BuiltinTypeSpec.Type.Enum:
2650 case BuiltinTypeSpec.Type.ValueType:
2651 case BuiltinTypeSpec.Type.MulticastDelegate:
2652 case BuiltinTypeSpec.Type.Delegate:
2653 case BuiltinTypeSpec.Type.Array:
2654 if (!(spec is BuiltinTypeSpec)) {
2655 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2656 GetSignatureForError (), base_type.GetSignatureForError ());
2658 base_type = Compiler.BuiltinTypes.Object;
2663 if (!IsAccessibleAs (base_type)) {
2664 Report.SymbolRelatedToPreviousError (base_type);
2665 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2666 base_type.GetSignatureForError (), GetSignatureForError ());
2670 if (PartialContainer.IsStatic && ifaces != null) {
2671 foreach (var t in ifaces)
2672 Report.SymbolRelatedToPreviousError (t);
2673 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2679 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2680 /// Valid only for attribute classes.
2681 public override string[] ConditionalConditions ()
2683 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2686 caching_flags &= ~Flags.Excluded_Undetected;
2688 if (OptAttributes == null)
2691 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2695 string[] conditions = new string[attrs.Length];
2696 for (int i = 0; i < conditions.Length; ++i)
2697 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2699 caching_flags |= Flags.Excluded;
2704 // FIXME: How do we deal with the user specifying a different
2707 protected override TypeAttributes TypeAttr {
2709 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2711 ta |= StaticClassAttribute;
2717 public sealed class Struct : ClassOrStruct {
2719 bool is_unmanaged, has_unmanaged_check_done;
2723 // Modifiers allowed in a struct declaration
2725 const Modifiers AllowedModifiers =
2728 Modifiers.PROTECTED |
2729 Modifiers.INTERNAL |
2733 public Struct (NamespaceContainer ns, DeclSpace parent, MemberName name,
2734 Modifiers mod, Attributes attrs)
2735 : base (ns, parent, name, attrs, MemberKind.Struct)
2737 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2738 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2739 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2742 public override AttributeTargets AttributeTargets {
2744 return AttributeTargets.Struct;
2748 public override void Accept (StructuralVisitor visitor)
2750 visitor.Visit (this);
2753 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2755 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2758 // When struct constains fixed fixed and struct layout has explicitly
2759 // set CharSet, its value has to be propagated to compiler generated
2762 if (a.Type == pa.StructLayout && Fields != null) {
2763 var value = a.GetNamedValue ("CharSet");
2767 for (int i = 0; i < Fields.Count; ++i) {
2768 FixedField ff = Fields [i] as FixedField;
2772 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2777 bool CheckStructCycles (Struct s)
2779 if (s.Fields == null)
2786 foreach (FieldBase field in s.Fields) {
2787 TypeSpec ftype = field.Spec.MemberType;
2788 if (!ftype.IsStruct)
2791 if (ftype is BuiltinTypeSpec)
2794 foreach (var targ in ftype.TypeArguments) {
2795 if (!CheckFieldTypeCycle (targ)) {
2796 Report.Error (523, field.Location,
2797 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2798 field.GetSignatureForError (), ftype.GetSignatureForError ());
2804 // Static fields of exactly same type are allowed
2806 if (field.IsStatic && ftype == s.CurrentType)
2809 if (!CheckFieldTypeCycle (ftype)) {
2810 Report.Error (523, field.Location,
2811 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2812 field.GetSignatureForError (), ftype.GetSignatureForError ());
2817 s.InTransit = false;
2821 bool CheckFieldTypeCycle (TypeSpec ts)
2823 var fts = ts.MemberDefinition as Struct;
2827 return CheckStructCycles (fts);
2830 public override void Emit ()
2832 CheckStructCycles (this);
2837 public override bool IsUnmanagedType ()
2839 if (has_unmanaged_check_done)
2840 return is_unmanaged;
2842 if (requires_delayed_unmanagedtype_check)
2845 if (Parent != null && Parent.IsGeneric) {
2846 has_unmanaged_check_done = true;
2850 if (fields != null) {
2851 requires_delayed_unmanagedtype_check = true;
2853 foreach (FieldBase f in fields) {
2857 // It can happen when recursive unmanaged types are defined
2858 // struct S { S* s; }
2859 TypeSpec mt = f.MemberType;
2867 has_unmanaged_check_done = true;
2871 has_unmanaged_check_done = true;
2874 is_unmanaged = true;
2878 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2880 var ifaces = base.ResolveBaseTypes (out base_class);
2881 base_type = Compiler.BuiltinTypes.ValueType;
2885 protected override TypeAttributes TypeAttr {
2887 const TypeAttributes DefaultTypeAttributes =
2888 TypeAttributes.SequentialLayout |
2889 TypeAttributes.Sealed;
2891 return base.TypeAttr | DefaultTypeAttributes;
2895 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2897 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2898 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2899 field.GetSignatureForError ());
2902 base.RegisterFieldForInitialization (field, expression);
2910 public sealed class Interface : TypeContainer {
2913 /// Modifiers allowed in a class declaration
2915 const Modifiers AllowedModifiers =
2918 Modifiers.PROTECTED |
2919 Modifiers.INTERNAL |
2923 public Interface (NamespaceContainer ns, DeclSpace parent, MemberName name, Modifiers mod,
2925 : base (ns, parent, name, attrs, MemberKind.Interface)
2927 var accmods = parent.Parent == null ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2929 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2930 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2935 public override AttributeTargets AttributeTargets {
2937 return AttributeTargets.Interface;
2941 protected override TypeAttributes TypeAttr {
2943 const TypeAttributes DefaultTypeAttributes =
2944 TypeAttributes.AutoLayout |
2945 TypeAttributes.Abstract |
2946 TypeAttributes.Interface;
2948 return base.TypeAttr | DefaultTypeAttributes;
2954 public override void Accept (StructuralVisitor visitor)
2956 visitor.Visit (this);
2959 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2961 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2962 a.Error_MissingGuidAttribute ();
2966 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2969 protected override bool VerifyClsCompliance ()
2971 if (!base.VerifyClsCompliance ())
2974 if (iface_exprs != null) {
2975 foreach (var iface in iface_exprs) {
2976 if (iface.IsCLSCompliant ())
2979 Report.SymbolRelatedToPreviousError (iface);
2980 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2981 GetSignatureForError (), TypeManager.CSharpName (iface));
2989 public abstract class InterfaceMemberBase : MemberBase
2992 // Common modifiers allowed in a class declaration
2994 protected const Modifiers AllowedModifiersClass =
2997 Modifiers.PROTECTED |
2998 Modifiers.INTERNAL |
3003 Modifiers.OVERRIDE |
3004 Modifiers.ABSTRACT |
3009 // Common modifiers allowed in a struct declaration
3011 protected const Modifiers AllowedModifiersStruct =
3014 Modifiers.PROTECTED |
3015 Modifiers.INTERNAL |
3018 Modifiers.OVERRIDE |
3023 // Common modifiers allowed in a interface declaration
3025 protected const Modifiers AllowedModifiersInterface =
3030 // Whether this is an interface member.
3032 public bool IsInterface;
3035 // If true, this is an explicit interface implementation
3037 public bool IsExplicitImpl;
3039 protected bool is_external_implementation;
3042 // The interface type we are explicitly implementing
3044 public TypeSpec InterfaceType;
3047 // The method we're overriding if this is an override method.
3049 protected MethodSpec base_method;
3051 readonly Modifiers explicit_mod_flags;
3052 public MethodAttributes flags;
3054 public InterfaceMemberBase (DeclSpace parent, GenericMethod generic,
3055 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod,
3056 MemberName name, Attributes attrs)
3057 : base (parent, generic, type, mod, allowed_mod, Modifiers.PRIVATE,
3060 IsInterface = parent.PartialContainer.Kind == MemberKind.Interface;
3061 IsExplicitImpl = (MemberName.Left != null);
3062 explicit_mod_flags = mod;
3065 public abstract Variance ExpectedMemberTypeVariance { get; }
3067 protected override bool CheckBase ()
3069 if (!base.CheckBase ())
3072 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3073 CheckForDuplications ();
3078 // For System.Object only
3079 if (Parent.BaseType == null)
3082 MemberSpec candidate;
3083 bool overrides = false;
3084 var base_member = FindBaseMember (out candidate, ref overrides);
3086 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3087 if (base_member == null) {
3088 if (candidate == null) {
3089 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3090 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3091 "object.Finalize()");
3093 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3094 GetSignatureForError (), SimpleName.GetMemberType (this));
3097 Report.SymbolRelatedToPreviousError (candidate);
3099 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3100 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3101 else if (this is PropertyBase)
3102 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3103 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3105 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3106 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3113 // Handles ambiguous overrides
3115 if (candidate != null) {
3116 Report.SymbolRelatedToPreviousError (candidate);
3117 Report.SymbolRelatedToPreviousError (base_member);
3119 // Get member definition for error reporting
3120 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3121 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3123 Report.Error (462, Location,
3124 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3125 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3128 if (!CheckOverrideAgainstBase (base_member))
3131 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3133 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3134 Report.SymbolRelatedToPreviousError (base_member);
3135 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3136 GetSignatureForError (), base_member.GetSignatureForError ());
3139 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3140 Report.SymbolRelatedToPreviousError (base_member);
3141 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3142 GetSignatureForError (), base_member.GetSignatureForError ());
3146 base_method = base_member as MethodSpec;
3150 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3151 base_member = candidate;
3153 if (base_member == null) {
3154 if ((ModFlags & Modifiers.NEW) != 0) {
3155 if (base_member == null) {
3156 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3157 GetSignatureForError ());
3161 if ((ModFlags & Modifiers.NEW) == 0) {
3162 ModFlags |= Modifiers.NEW;
3163 if (!IsCompilerGenerated) {
3164 Report.SymbolRelatedToPreviousError (base_member);
3165 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3166 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",
3167 GetSignatureForError (), base_member.GetSignatureForError ());
3169 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3170 GetSignatureForError (), base_member.GetSignatureForError ());
3175 if (!IsInterface && base_member.IsAbstract && !overrides) {
3176 Report.SymbolRelatedToPreviousError (base_member);
3177 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3178 GetSignatureForError (), base_member.GetSignatureForError ());
3185 protected virtual bool CheckForDuplications ()
3187 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3191 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3192 // that have been defined.
3194 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3198 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3199 Report.SymbolRelatedToPreviousError (base_member);
3200 Report.Error (506, Location,
3201 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3202 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3206 // Now we check that the overriden method is not final
3207 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3208 Report.SymbolRelatedToPreviousError (base_member);
3209 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3210 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3214 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3215 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3216 Report.SymbolRelatedToPreviousError (base_member);
3217 if (this is PropertyBasedMember) {
3218 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3219 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3221 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3222 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3230 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3232 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3233 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3235 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3237 // It must be at least "protected"
3239 if ((thisp & Modifiers.PROTECTED) == 0) {
3244 // when overriding protected internal, the method can be declared
3245 // protected internal only within the same assembly or assembly
3246 // which has InternalsVisibleTo
3248 if ((thisp & Modifiers.INTERNAL) != 0) {
3249 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3253 // protected overriding protected internal inside same assembly
3254 // requires internal modifier as well
3256 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3263 return thisp == base_classp;
3266 public override bool Define ()
3269 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3270 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3272 flags = MethodAttributes.Public |
3273 MethodAttributes.Abstract |
3274 MethodAttributes.HideBySig |
3275 MethodAttributes.NewSlot |
3276 MethodAttributes.Virtual;
3278 Parent.PartialContainer.MethodModifiersValid (this);
3280 flags = ModifiersExtensions.MethodAttr (ModFlags);
3283 if (IsExplicitImpl) {
3284 InterfaceType = MemberName.Left.GetTypeExpression ().ResolveAsType (Parent);
3285 if (InterfaceType == null)
3288 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3289 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3290 GetSignatureForError ());
3293 if (!InterfaceType.IsInterface) {
3294 Report.SymbolRelatedToPreviousError (InterfaceType);
3295 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3296 TypeManager.CSharpName (InterfaceType));
3298 Parent.PartialContainer.VerifyImplements (this);
3301 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3304 return base.Define ();
3307 protected bool DefineParameters (ParametersCompiled parameters)
3309 if (!parameters.Resolve (this))
3313 for (int i = 0; i < parameters.Count; ++i) {
3314 Parameter p = parameters [i];
3316 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3317 p.Warning_UselessOptionalParameter (Report);
3319 if (p.CheckAccessibility (this))
3322 TypeSpec t = parameters.Types [i];
3323 Report.SymbolRelatedToPreviousError (t);
3324 if (this is Indexer)
3325 Report.Error (55, Location,
3326 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3327 TypeManager.CSharpName (t), GetSignatureForError ());
3328 else if (this is Operator)
3329 Report.Error (57, Location,
3330 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3331 TypeManager.CSharpName (t), GetSignatureForError ());
3333 Report.Error (51, Location,
3334 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3335 TypeManager.CSharpName (t), GetSignatureForError ());
3341 protected override void DoMemberTypeDependentChecks ()
3343 base.DoMemberTypeDependentChecks ();
3345 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3348 public override void Emit()
3350 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3351 // We are more strict than csc and report this as an error because SRE does not allow emit that
3352 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3353 if (this is Constructor) {
3354 Report.Warning (824, 1, Location,
3355 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3357 Report.Warning (626, 1, Location,
3358 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3359 GetSignatureForError ());
3366 public override bool EnableOverloadChecks (MemberCore overload)
3369 // Two members can differ in their explicit interface
3370 // type parameter only
3372 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3373 if (imb != null && imb.IsExplicitImpl) {
3374 if (IsExplicitImpl) {
3375 caching_flags |= Flags.MethodOverloadsExist;
3380 return IsExplicitImpl;
3383 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3385 var base_modifiers = base_member.Modifiers;
3387 // Remove internal modifier from types which are not internally accessible
3388 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3389 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3390 base_modifiers = Modifiers.PROTECTED;
3392 Report.SymbolRelatedToPreviousError (base_member);
3393 Report.Error (507, member.Location,
3394 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3395 member.GetSignatureForError (),
3396 ModifiersExtensions.AccessibilityName (base_modifiers),
3397 base_member.GetSignatureForError ());
3400 protected void Error_StaticReturnType ()
3402 Report.Error (722, Location,
3403 "`{0}': static types cannot be used as return types",
3404 MemberType.GetSignatureForError ());
3408 /// Gets base method and its return type
3410 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3412 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3416 // The "short" name of this property / indexer / event. This is the
3417 // name without the explicit interface.
3419 public string ShortName {
3420 get { return MemberName.Name; }
3421 set { SetMemberName (new MemberName (MemberName.Left, value, Location)); }
3425 // Returns full metadata method name
3427 public string GetFullName (MemberName name)
3429 return GetFullName (name.Name);
3432 public string GetFullName (string name)
3434 if (!IsExplicitImpl)
3438 // When dealing with explicit members a full interface type
3439 // name is added to member name to avoid possible name conflicts
3441 // We use CSharpName which gets us full name with benefit of
3442 // replacing predefined names which saves some space and name
3445 return TypeManager.CSharpName (InterfaceType) + "." + name;
3448 public override string GetSignatureForDocumentation ()
3451 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3453 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3456 protected override bool VerifyClsCompliance ()
3458 if (!base.VerifyClsCompliance ()) {
3462 if (GenericMethod != null)
3463 GenericMethod.VerifyClsCompliance ();
3468 public override bool IsUsed
3470 get { return IsExplicitImpl || base.IsUsed; }
3475 public abstract class MemberBase : MemberCore
3477 protected FullNamedExpression type_expr;
3478 protected TypeSpec member_type;
3480 public readonly DeclSpace ds;
3481 public readonly GenericMethod GenericMethod;
3483 protected MemberBase (DeclSpace parent, GenericMethod generic,
3484 FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod,
3485 MemberName name, Attributes attrs)
3486 : base (parent, name, attrs)
3488 this.ds = generic != null ? generic : (DeclSpace) parent;
3489 this.type_expr = type;
3490 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3491 GenericMethod = generic;
3492 if (GenericMethod != null)
3493 GenericMethod.ModFlags = ModFlags;
3498 public TypeSpec MemberType {
3504 public FullNamedExpression TypeExpression {
3513 // Main member define entry
3515 public override bool Define ()
3517 DoMemberTypeIndependentChecks ();
3520 // Returns false only when type resolution failed
3522 if (!ResolveMemberType ())
3525 DoMemberTypeDependentChecks ();
3530 // Any type_name independent checks
3532 protected virtual void DoMemberTypeIndependentChecks ()
3534 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3535 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3536 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3537 GetSignatureForError (), Parent.GetSignatureForError ());
3542 // Any type_name dependent checks
3544 protected virtual void DoMemberTypeDependentChecks ()
3546 // verify accessibility
3547 if (!IsAccessibleAs (MemberType)) {
3548 Report.SymbolRelatedToPreviousError (MemberType);
3549 if (this is Property)
3550 Report.Error (53, Location,
3551 "Inconsistent accessibility: property type `" +
3552 TypeManager.CSharpName (MemberType) + "' is less " +
3553 "accessible than property `" + GetSignatureForError () + "'");
3554 else if (this is Indexer)
3555 Report.Error (54, Location,
3556 "Inconsistent accessibility: indexer return type `" +
3557 TypeManager.CSharpName (MemberType) + "' is less " +
3558 "accessible than indexer `" + GetSignatureForError () + "'");
3559 else if (this is MethodCore) {
3560 if (this is Operator)
3561 Report.Error (56, Location,
3562 "Inconsistent accessibility: return type `" +
3563 TypeManager.CSharpName (MemberType) + "' is less " +
3564 "accessible than operator `" + GetSignatureForError () + "'");
3566 Report.Error (50, Location,
3567 "Inconsistent accessibility: return type `" +
3568 TypeManager.CSharpName (MemberType) + "' is less " +
3569 "accessible than method `" + GetSignatureForError () + "'");
3571 Report.Error (52, Location,
3572 "Inconsistent accessibility: field type `" +
3573 TypeManager.CSharpName (MemberType) + "' is less " +
3574 "accessible than field `" + GetSignatureForError () + "'");
3579 protected void IsTypePermitted ()
3581 if (MemberType.IsSpecialRuntimeType) {
3582 if (Parent is StateMachine) {
3583 Report.Error (4012, Location,
3584 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3585 MemberType.GetSignatureForError ());
3586 } else if (Parent is HoistedStoreyClass) {
3587 Report.Error (4013, Location,
3588 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3589 MemberType.GetSignatureForError ());
3591 Report.Error (610, Location,
3592 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3597 protected virtual bool CheckBase ()
3599 CheckProtectedModifier ();
3604 public override string GetSignatureForDocumentation ()
3606 return Parent.Name + "." + Name;
3609 protected virtual bool ResolveMemberType ()
3611 if (member_type != null)
3612 throw new InternalErrorException ("Multi-resolve");
3614 member_type = type_expr.ResolveAsType (this);
3615 return member_type != null;