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;
21 using System.Diagnostics;
22 using Mono.CompilerServices.SymbolWriter;
25 using XmlElement = System.Object;
29 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
30 using IKVM.Reflection;
31 using IKVM.Reflection.Emit;
33 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
34 using System.Reflection;
35 using System.Reflection.Emit;
41 // General types container, used as a base class for all constructs which can hold types
43 public abstract class TypeContainer : MemberCore
45 public readonly MemberKind Kind;
46 public readonly string Basename;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
57 : base (parent, name, attrs)
61 this.Basename = name.Basename;
63 defined_names = new Dictionary<string, MemberCore> ();
66 public override TypeSpec CurrentType {
72 public Dictionary<string, MemberCore> DefinedNames {
78 public TypeDefinition PartialContainer {
80 return main_container;
83 main_container = value;
87 public IList<TypeContainer> Containers {
94 // Any unattached attributes during parsing get added here. User
97 public Attributes UnattachedAttributes {
101 public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
106 public virtual void AddPartial (TypeDefinition next_part)
109 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
111 AddPartial (next_part, mc as TypeDefinition);
114 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
116 next_part.ModFlags |= Modifiers.PARTIAL;
118 if (existing == null) {
119 AddTypeContainer (next_part);
123 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
124 if (existing.Kind != next_part.Kind) {
125 AddTypeContainer (next_part);
127 Report.SymbolRelatedToPreviousError (next_part);
128 Error_MissingPartialModifier (existing);
134 if (existing.Kind != next_part.Kind) {
135 Report.SymbolRelatedToPreviousError (existing);
136 Report.Error (261, next_part.Location,
137 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
138 next_part.GetSignatureForError ());
141 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
142 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
143 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
144 Report.SymbolRelatedToPreviousError (existing);
145 Report.Error (262, next_part.Location,
146 "Partial declarations of `{0}' have conflicting accessibility modifiers",
147 next_part.GetSignatureForError ());
150 var tc_names = existing.CurrentTypeParameters;
151 if (tc_names != null) {
152 for (int i = 0; i < tc_names.Count; ++i) {
153 var tp = next_part.MemberName.TypeParameters[i];
154 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
155 Report.SymbolRelatedToPreviousError (existing.Location, "");
156 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
157 next_part.GetSignatureForError ());
161 if (tc_names[i].Variance != tp.Variance) {
162 Report.SymbolRelatedToPreviousError (existing.Location, "");
163 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
164 next_part.GetSignatureForError ());
170 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
171 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
172 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
173 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
174 existing.ModFlags |= next_part.ModFlags;
176 existing.ModFlags |= next_part.ModFlags;
179 existing.Definition.Modifiers = existing.ModFlags;
181 if (next_part.attributes != null) {
182 if (existing.attributes == null)
183 existing.attributes = next_part.attributes;
185 existing.attributes.AddAttributes (next_part.attributes.Attrs);
188 next_part.PartialContainer = existing;
190 if (containers == null)
191 containers = new List<TypeContainer> ();
193 containers.Add (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 public virtual void CloseContainer ()
215 if (containers != null) {
216 foreach (TypeContainer tc in containers) {
217 tc.CloseContainer ();
222 public virtual void CreateMetadataName (StringBuilder sb)
224 if (Parent != null && Parent.MemberName != null)
225 Parent.CreateMetadataName (sb);
227 MemberName.CreateMetadataName (sb);
230 public virtual bool CreateContainer ()
232 if (containers != null) {
233 foreach (TypeContainer tc in containers) {
234 tc.CreateContainer ();
241 public override bool Define ()
243 if (containers != null) {
244 foreach (TypeContainer tc in containers) {
249 // Release cache used by parser only
250 if (Module.Evaluator == null) {
251 defined_names = null;
253 defined_names.Clear ();
259 public virtual void PrepareEmit ()
261 if (containers != null) {
262 foreach (var t in containers) {
265 } catch (Exception e) {
266 if (MemberName == MemberName.Null)
269 throw new InternalErrorException (t, e);
275 public virtual bool DefineContainer ()
282 DoDefineContainer ();
284 if (containers != null) {
285 foreach (TypeContainer tc in containers) {
287 tc.DefineContainer ();
288 } catch (Exception e) {
289 if (MemberName == MemberName.Null)
292 throw new InternalErrorException (tc, e);
300 public virtual void ExpandBaseInterfaces ()
302 if (containers != null) {
303 foreach (TypeContainer tc in containers) {
304 tc.ExpandBaseInterfaces ();
309 protected virtual void DefineNamespace ()
311 if (containers != null) {
312 foreach (var tc in containers) {
314 tc.DefineNamespace ();
315 } catch (Exception e) {
316 throw new InternalErrorException (tc, e);
322 protected virtual void DoDefineContainer ()
326 public virtual void EmitContainer ()
328 if (containers != null) {
329 for (int i = 0; i < containers.Count; ++i)
330 containers[i].EmitContainer ();
334 protected void Error_MissingPartialModifier (MemberCore type)
336 Report.Error (260, type.Location,
337 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
338 type.GetSignatureForError ());
341 public override string GetSignatureForDocumentation ()
343 if (Parent != null && Parent.MemberName != null)
344 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
346 return MemberName.GetSignatureForDocumentation ();
349 public override string GetSignatureForError ()
351 if (Parent != null && Parent.MemberName != null)
352 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
354 return MemberName.GetSignatureForError ();
357 public string GetSignatureForMetadata ()
359 if (Parent is TypeDefinition) {
360 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
363 var sb = new StringBuilder ();
364 CreateMetadataName (sb);
365 return sb.ToString ();
368 public virtual void RemoveContainer (TypeContainer cont)
370 if (containers != null)
371 containers.Remove (cont);
373 var tc = Parent == Module ? Module : this;
374 tc.defined_names.Remove (cont.Basename);
377 public virtual void VerifyMembers ()
379 if (containers != null) {
380 foreach (TypeContainer tc in containers)
385 public override void WriteDebugSymbol (MonoSymbolFile file)
387 if (containers != null) {
388 foreach (TypeContainer tc in containers) {
389 tc.WriteDebugSymbol (file);
395 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
398 // Different context is needed when resolving type container base
399 // types. Type names come from the parent scope but type parameter
400 // names from the container scope.
402 public struct BaseContext : IMemberContext
406 public BaseContext (TypeContainer tc)
411 #region IMemberContext Members
413 public CompilerContext Compiler {
414 get { return tc.Compiler; }
417 public TypeSpec CurrentType {
418 get { return tc.Parent.CurrentType; }
421 public TypeParameters CurrentTypeParameters {
422 get { return tc.PartialContainer.CurrentTypeParameters; }
425 public MemberCore CurrentMemberDefinition {
429 public bool IsObsolete {
430 get { return tc.IsObsolete; }
433 public bool IsUnsafe {
434 get { return tc.IsUnsafe; }
437 public bool IsStatic {
438 get { return tc.IsStatic; }
441 public ModuleContainer Module {
442 get { return tc.Module; }
445 public string GetSignatureForError ()
447 return tc.GetSignatureForError ();
450 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
455 public FullNamedExpression LookupNamespaceAlias (string name)
457 return tc.Parent.LookupNamespaceAlias (name);
460 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
463 var tp = CurrentTypeParameters;
465 TypeParameter t = tp.Find (name);
467 return new TypeParameterExpr (t, loc);
471 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
481 GetHashCode = 1 << 1,
482 HasStaticFieldInitializer = 1 << 2
485 readonly List<MemberCore> members;
487 // Holds a list of fields that have initializers
488 protected List<FieldInitializer> initialized_fields;
490 // Holds a list of static fields that have initializers
491 protected List<FieldInitializer> initialized_static_fields;
493 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
495 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
498 // Points to the first non-static field added to the container.
500 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
501 // and the first one's as good as any.
503 protected FieldBase first_nonstatic_field;
506 // This one is computed after we can distinguish interfaces
507 // from classes from the arraylist `type_bases'
509 protected TypeSpec base_type;
510 FullNamedExpression base_type_expr; // TODO: It's temporary variable
511 protected TypeSpec[] iface_exprs;
513 protected List<FullNamedExpression> type_bases;
515 TypeDefinition InTransit;
517 public TypeBuilder TypeBuilder;
518 GenericTypeParameterBuilder[] all_tp_builders;
520 // All recursive type parameters put together sharing same
521 // TypeParameter instances
523 TypeParameters all_type_parameters;
525 public const string DefaultIndexerName = "Item";
527 bool has_normal_indexers;
529 protected bool requires_delayed_unmanagedtype_check;
531 bool members_defined;
532 bool members_defined_ok;
533 protected bool has_static_constructor;
535 private CachedMethods cached_method;
537 protected TypeSpec spec;
538 TypeSpec current_type;
540 public int DynamicSitesCounter;
541 public int AnonymousMethodsCounter;
542 public int MethodGroupsCounter;
544 static readonly string[] attribute_targets = new string[] { "type" };
547 /// The pending methods that need to be implemented
548 // (interfaces or abstract methods)
550 PendingImplementation pending;
552 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
553 : base (parent, name, attrs, kind)
555 PartialContainer = this;
556 members = new List<MemberCore> ();
561 public List<FullNamedExpression> BaseTypeExpressions {
567 public override TypeSpec CurrentType {
569 if (current_type == null) {
570 if (IsGenericOrParentIsGeneric) {
572 // Switch to inflated version as it's used by all expressions
574 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
575 current_type = spec.MakeGenericType (this, targs);
585 public override TypeParameters CurrentTypeParameters {
587 return PartialContainer.MemberName.TypeParameters;
591 int CurrentTypeParametersStartIndex {
593 int total = all_tp_builders.Length;
594 if (CurrentTypeParameters != null) {
595 return total - CurrentTypeParameters.Count;
601 public virtual AssemblyDefinition DeclaringAssembly {
603 return Module.DeclaringAssembly;
607 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
609 return Module.DeclaringAssembly;
613 public TypeSpec Definition {
619 public bool HasMembersDefined {
621 return members_defined;
625 public bool HasInstanceConstructor {
627 return (caching_flags & Flags.HasInstanceConstructor) != 0;
630 caching_flags |= Flags.HasInstanceConstructor;
634 // Indicated whether container has StructLayout attribute set Explicit
635 public bool HasExplicitLayout {
636 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
637 set { caching_flags |= Flags.HasExplicitLayout; }
640 public bool HasOperators {
642 return (caching_flags & Flags.HasUserOperators) != 0;
645 caching_flags |= Flags.HasUserOperators;
649 public bool HasStructLayout {
650 get { return (caching_flags & Flags.HasStructLayout) != 0; }
651 set { caching_flags |= Flags.HasStructLayout; }
654 public TypeSpec[] Interfaces {
660 public bool IsGenericOrParentIsGeneric {
662 return all_type_parameters != null;
666 public bool IsTopLevel {
668 return !(Parent is TypeDefinition);
672 public bool IsPartial {
674 return (ModFlags & Modifiers.PARTIAL) != 0;
678 bool ITypeDefinition.IsTypeForwarder {
685 // Returns true for secondary partial containers
689 return PartialContainer != this;
693 public MemberCache MemberCache {
695 return spec.MemberCache;
699 public List<MemberCore> Members {
705 string ITypeDefinition.Namespace {
708 while (p.Kind != MemberKind.Namespace)
711 return p.MemberName == null ? null : p.GetSignatureForError ();
715 public TypeParameters TypeParametersAll {
717 return all_type_parameters;
721 public override string[] ValidAttributeTargets {
723 return attribute_targets;
729 public override void Accept (StructuralVisitor visitor)
731 visitor.Visit (this);
734 public void AddMember (MemberCore symbol)
736 if (symbol.MemberName.ExplicitInterface != null) {
737 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
738 Report.Error (541, symbol.Location,
739 "`{0}': explicit interface declaration can only be declared in a class or struct",
740 symbol.GetSignatureForError ());
744 AddNameToContainer (symbol, symbol.MemberName.Basename);
745 members.Add (symbol);
748 public override void AddTypeContainer (TypeContainer tc)
750 AddNameToContainer (tc, tc.Basename);
752 if (containers == null)
753 containers = new List<TypeContainer> ();
756 base.AddTypeContainer (tc);
759 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
763 if (containers == null)
764 containers = new List<TypeContainer> ();
766 base.AddCompilerGeneratedClass (c);
770 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
772 public virtual void AddNameToContainer (MemberCore symbol, string name)
774 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
778 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
779 PartialContainer.defined_names.Add (name, symbol);
783 if (symbol.EnableOverloadChecks (mc))
786 InterfaceMemberBase im = mc as InterfaceMemberBase;
787 if (im != null && im.IsExplicitImpl)
790 Report.SymbolRelatedToPreviousError (mc);
791 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
792 Error_MissingPartialModifier (symbol);
796 if (symbol is TypeParameter) {
797 Report.Error (692, symbol.Location,
798 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
800 Report.Error (102, symbol.Location,
801 "The type `{0}' already contains a definition for `{1}'",
802 GetSignatureForError (), name);
808 public void AddConstructor (Constructor c)
810 AddConstructor (c, false);
813 public void AddConstructor (Constructor c, bool isDefault)
815 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
817 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
819 if (is_static && c.ParameterInfo.IsEmpty) {
820 PartialContainer.has_static_constructor = true;
822 PartialContainer.HasInstanceConstructor = true;
828 public bool AddField (FieldBase field)
832 if ((field.ModFlags & Modifiers.STATIC) != 0)
835 var first_field = PartialContainer.first_nonstatic_field;
836 if (first_field == null) {
837 PartialContainer.first_nonstatic_field = field;
841 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
842 Report.SymbolRelatedToPreviousError (first_field.Parent);
843 Report.Warning (282, 3, field.Location,
844 "struct instance field `{0}' found in different declaration from instance field `{1}'",
845 field.GetSignatureForError (), first_field.GetSignatureForError ());
851 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
853 public void AddIndexer (Indexer i)
858 public void AddOperator (Operator op)
860 PartialContainer.HasOperators = true;
864 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
866 if (has_normal_indexers && a.Type == pa.DefaultMember) {
867 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
871 if (a.Type == pa.Required) {
872 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
876 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
879 public override AttributeTargets AttributeTargets {
881 throw new NotSupportedException ();
885 public TypeSpec BaseType {
887 return spec.BaseType;
891 protected virtual TypeAttributes TypeAttr {
893 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
897 public int TypeParametersCount {
899 return MemberName.Arity;
903 TypeParameterSpec[] ITypeDefinition.TypeParameters {
905 return PartialContainer.CurrentTypeParameters.Types;
909 public string GetAttributeDefaultMember ()
911 return indexer_name ?? DefaultIndexerName;
914 public bool IsComImport {
916 if (OptAttributes == null)
919 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
923 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
926 PartialContainer.RegisterFieldForInitialization (field, expression);
928 if ((field.ModFlags & Modifiers.STATIC) != 0){
929 if (initialized_static_fields == null) {
930 HasStaticFieldInitializer = true;
931 initialized_static_fields = new List<FieldInitializer> (4);
934 initialized_static_fields.Add (expression);
936 if (initialized_fields == null)
937 initialized_fields = new List<FieldInitializer> (4);
939 initialized_fields.Add (expression);
943 public void ResolveFieldInitializers (BlockContext ec)
945 Debug.Assert (!IsPartialPart);
948 if (initialized_static_fields == null)
951 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
953 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
954 for (i = 0; i < initialized_static_fields.Count; ++i) {
955 FieldInitializer fi = initialized_static_fields [i];
956 ExpressionStatement s = fi.ResolveStatement (ec);
958 s = EmptyExpressionStatement.Instance;
959 } else if (!fi.IsSideEffectFree) {
960 has_complex_initializer |= true;
966 for (i = 0; i < initialized_static_fields.Count; ++i) {
967 FieldInitializer fi = initialized_static_fields [i];
969 // Need special check to not optimize code like this
970 // static int a = b = 5;
973 if (!has_complex_initializer && fi.IsDefaultInitializer)
976 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
982 if (initialized_fields == null)
985 for (int i = 0; i < initialized_fields.Count; ++i) {
986 FieldInitializer fi = initialized_fields [i];
987 ExpressionStatement s = fi.ResolveStatement (ec);
992 // Field is re-initialized to its default value => removed
994 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
997 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1001 public override string DocComment {
1013 public PendingImplementation PendingImplementations {
1014 get { return pending; }
1017 internal override void GenerateDocComment (DocumentationBuilder builder)
1022 base.GenerateDocComment (builder);
1024 foreach (var member in members)
1025 member.GenerateDocComment (builder);
1028 public TypeSpec GetAttributeCoClass ()
1030 if (OptAttributes == null)
1033 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1037 return a.GetCoClassAttributeValue ();
1040 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1043 if (OptAttributes != null) {
1044 a = OptAttributes.Search (pa);
1050 return a.GetAttributeUsageAttribute ();
1053 public virtual CompilationSourceFile GetCompilationSourceFile ()
1055 TypeContainer ns = Parent;
1057 var sf = ns as CompilationSourceFile;
1065 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1067 type_bases = baseTypes;
1071 /// This function computes the Base class and also the
1072 /// list of interfaces that the class or struct @c implements.
1074 /// The return value is an array (might be null) of
1075 /// interfaces implemented (as Types).
1077 /// The @base_class argument is set to the base object or null
1078 /// if this is `System.Object'.
1080 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1083 if (type_bases == null)
1086 int count = type_bases.Count;
1087 TypeSpec[] ifaces = null;
1088 var base_context = new BaseContext (this);
1089 for (int i = 0, j = 0; i < count; i++){
1090 FullNamedExpression fne = type_bases [i];
1092 var fne_resolved = fne.ResolveAsType (base_context);
1093 if (fne_resolved == null)
1096 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1097 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1098 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1099 GetSignatureForError ());
1104 base_type = fne_resolved;
1110 ifaces = new TypeSpec [count - i];
1112 if (fne_resolved.IsInterface) {
1113 for (int ii = 0; ii < j; ++ii) {
1114 if (fne_resolved == ifaces [ii]) {
1115 Report.Error (528, Location, "`{0}' is already listed in interface list",
1116 fne_resolved.GetSignatureForError ());
1121 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1122 Report.Error (61, fne.Location,
1123 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1124 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1127 Report.SymbolRelatedToPreviousError (fne_resolved);
1128 if (Kind != MemberKind.Class) {
1129 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1130 } else if (base_class != null)
1131 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1132 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1134 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1135 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1139 ifaces [j++] = fne_resolved;
1146 // Checks that some operators come in pairs:
1152 // They are matched based on the return type and the argument types
1154 void CheckPairedOperators ()
1156 bool has_equality_or_inequality = false;
1157 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1159 for (int i = 0; i < members.Count; ++i) {
1160 var o_a = members[i] as Operator;
1164 var o_type = o_a.OperatorType;
1165 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1166 has_equality_or_inequality = true;
1168 if (found_matched.Contains (o_type))
1171 var matching_type = o_a.GetMatchingOperator ();
1172 if (matching_type == Operator.OpType.TOP) {
1176 bool pair_found = false;
1177 for (int ii = 0; ii < members.Count; ++ii) {
1178 var o_b = members[ii] as Operator;
1179 if (o_b == null || o_b.OperatorType != matching_type)
1182 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1185 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1188 found_matched.Add (matching_type);
1194 Report.Error (216, o_a.Location,
1195 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1196 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1200 if (has_equality_or_inequality) {
1202 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1203 GetSignatureForError ());
1205 if (!HasGetHashCode)
1206 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1207 GetSignatureForError ());
1211 public override void CreateMetadataName (StringBuilder sb)
1213 if (Parent.MemberName != null) {
1214 Parent.CreateMetadataName (sb);
1216 if (sb.Length != 0) {
1221 sb.Append (MemberName.Basename);
1224 bool CreateTypeBuilder ()
1227 // Sets .size to 1 for structs with no instance fields
1229 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1231 var parent_def = Parent as TypeDefinition;
1232 if (parent_def == null) {
1233 var sb = new StringBuilder ();
1234 CreateMetadataName (sb);
1235 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1237 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1240 if (DeclaringAssembly.Importer != null)
1241 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1243 spec.SetMetaInfo (TypeBuilder);
1244 spec.MemberCache = new MemberCache (this);
1246 TypeParameters parentAllTypeParameters = null;
1247 if (parent_def != null) {
1248 spec.DeclaringType = Parent.CurrentType;
1249 parent_def.MemberCache.AddMember (spec);
1250 parentAllTypeParameters = parent_def.all_type_parameters;
1253 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1254 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1256 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1258 if (CurrentTypeParameters != null) {
1259 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1260 CurrentTypeParameters.Define (all_tp_builders);
1267 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1270 int parent_offset = 0;
1271 if (parentAllTypeParameters != null) {
1272 if (CurrentTypeParameters == null) {
1273 all_type_parameters = parentAllTypeParameters;
1274 return parentAllTypeParameters.GetAllNames ();
1277 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1278 all_type_parameters = new TypeParameters (names.Length);
1279 all_type_parameters.Add (parentAllTypeParameters);
1281 parent_offset = all_type_parameters.Count;
1282 for (int i = 0; i < parent_offset; ++i)
1283 names[i] = all_type_parameters[i].MemberName.Name;
1286 names = new string[CurrentTypeParameters.Count];
1289 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1290 if (all_type_parameters != null)
1291 all_type_parameters.Add (MemberName.TypeParameters[i]);
1293 var name = CurrentTypeParameters[i].MemberName.Name;
1294 names[parent_offset + i] = name;
1295 for (int ii = 0; ii < parent_offset + i; ++ii) {
1296 if (names[ii] != name)
1299 var tp = CurrentTypeParameters[i];
1300 var conflict = all_type_parameters[ii];
1302 tp.WarningParentNameConflict (conflict);
1306 if (all_type_parameters == null)
1307 all_type_parameters = CurrentTypeParameters;
1313 public SourceMethodBuilder CreateMethodSymbolEntry ()
1315 if (Module.DeclaringAssembly.SymbolWriter == null)
1318 var source_file = GetCompilationSourceFile ();
1319 if (source_file == null)
1322 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1326 // Creates a proxy base method call inside this container for hoisted base member calls
1328 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1330 Method proxy_method;
1333 // One proxy per base method is enough
1335 if (hoisted_base_call_proxies == null) {
1336 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1337 proxy_method = null;
1339 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1342 if (proxy_method == null) {
1343 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1345 MemberName member_name;
1346 TypeArguments targs = null;
1347 TypeSpec return_type = method.ReturnType;
1348 var local_param_types = method.Parameters.Types;
1350 if (method.IsGeneric) {
1352 // Copy all base generic method type parameters info
1354 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1355 var tparams = new TypeParameters ();
1357 targs = new TypeArguments ();
1358 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1359 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1360 var tp = hoisted_tparams[i];
1361 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1362 tparams.Add (local_tp);
1364 targs.Add (new SimpleName (tp.Name, Location));
1365 targs.Arguments[i] = local_tp.Type;
1368 member_name = new MemberName (name, tparams, Location);
1371 // Mutate any method type parameters from original
1372 // to newly created hoisted version
1374 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1375 return_type = mutator.Mutate (return_type);
1376 local_param_types = mutator.Mutate (local_param_types);
1378 member_name = new MemberName (name);
1381 var base_parameters = new Parameter[method.Parameters.Count];
1382 for (int i = 0; i < base_parameters.Length; ++i) {
1383 var base_param = method.Parameters.FixedParameters[i];
1384 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1385 base_param.Name, base_param.ModFlags, null, Location);
1386 base_parameters[i].Resolve (this, i);
1389 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1390 if (method.Parameters.HasArglist) {
1391 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1392 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1395 // Compiler generated proxy
1396 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1397 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1398 member_name, cloned_params, null);
1400 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1401 IsCompilerGenerated = true
1404 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1405 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1407 mg.SetTypeArguments (rc, targs);
1409 // Get all the method parameters and pass them as arguments
1410 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1411 Statement statement;
1412 if (method.ReturnType.Kind == MemberKind.Void)
1413 statement = new StatementExpression (real_base_call);
1415 statement = new Return (real_base_call, Location);
1417 block.AddStatement (statement);
1418 proxy_method.Block = block;
1420 members.Add (proxy_method);
1421 proxy_method.Define ();
1422 proxy_method.PrepareEmit ();
1424 hoisted_base_call_proxies.Add (method, proxy_method);
1427 return proxy_method.Spec;
1430 protected bool DefineBaseTypes ()
1432 iface_exprs = ResolveBaseTypes (out base_type_expr);
1435 if (IsPartialPart) {
1436 set_base_type = false;
1438 if (base_type_expr != null) {
1439 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1440 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1441 Report.Error (263, Location,
1442 "Partial declarations of `{0}' must not specify different base classes",
1443 GetSignatureForError ());
1445 PartialContainer.base_type_expr = base_type_expr;
1446 PartialContainer.base_type = base_type;
1447 set_base_type = true;
1451 if (iface_exprs != null) {
1452 if (PartialContainer.iface_exprs == null)
1453 PartialContainer.iface_exprs = iface_exprs;
1455 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1456 foreach (var iface_partial in iface_exprs) {
1457 if (ifaces.Contains (iface_partial))
1460 ifaces.Add (iface_partial);
1463 PartialContainer.iface_exprs = ifaces.ToArray ();
1467 PartialContainer.members.AddRange (members);
1468 if (containers != null) {
1469 if (PartialContainer.containers == null)
1470 PartialContainer.containers = new List<TypeContainer> ();
1472 PartialContainer.containers.AddRange (containers);
1475 members_defined = members_defined_ok = true;
1476 caching_flags |= Flags.CloseTypeCreated;
1478 set_base_type = true;
1481 var cycle = CheckRecursiveDefinition (this);
1482 if (cycle != null) {
1483 Report.SymbolRelatedToPreviousError (cycle);
1484 if (this is Interface) {
1485 Report.Error (529, Location,
1486 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1487 GetSignatureForError (), cycle.GetSignatureForError ());
1490 PartialContainer.iface_exprs = null;
1492 Report.Error (146, Location,
1493 "Circular base class dependency involving `{0}' and `{1}'",
1494 GetSignatureForError (), cycle.GetSignatureForError ());
1497 PartialContainer.base_type = null;
1501 if (iface_exprs != null) {
1502 foreach (var iface_type in iface_exprs) {
1503 // Prevents a crash, the interface might not have been resolved: 442144
1504 if (iface_type == null)
1507 if (!spec.AddInterfaceDefined (iface_type))
1510 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1514 if (Kind == MemberKind.Interface) {
1515 spec.BaseType = Compiler.BuiltinTypes.Object;
1519 if (set_base_type) {
1520 if (base_type != null) {
1521 spec.BaseType = base_type;
1523 // Set base type after type creation
1524 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1526 TypeBuilder.SetParent (null);
1533 public override void ExpandBaseInterfaces ()
1536 DoExpandBaseInterfaces ();
1538 base.ExpandBaseInterfaces ();
1541 public void DoExpandBaseInterfaces ()
1543 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1546 caching_flags |= Flags.InterfacesExpanded;
1549 // Expand base interfaces. It cannot be done earlier because all partial
1550 // interface parts need to be defined before the type they are used from
1552 if (iface_exprs != null) {
1553 foreach (var iface in iface_exprs) {
1557 var td = iface.MemberDefinition as TypeDefinition;
1559 td.DoExpandBaseInterfaces ();
1561 if (iface.Interfaces == null)
1564 foreach (var biface in iface.Interfaces) {
1565 if (spec.AddInterfaceDefined (biface)) {
1566 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1573 // Include all base type interfaces too, see ImportTypeBase for details
1575 if (base_type != null) {
1576 var td = base_type.MemberDefinition as TypeDefinition;
1578 td.DoExpandBaseInterfaces ();
1581 // Simply use base interfaces only, they are all expanded which makes
1582 // it easy to handle generic type argument propagation with single
1585 // interface IA<T> : IB<T>
1586 // interface IB<U> : IC<U>
1589 if (base_type.Interfaces != null) {
1590 foreach (var iface in base_type.Interfaces) {
1591 spec.AddInterfaceDefined (iface);
1597 public override void PrepareEmit ()
1599 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1602 foreach (var member in members) {
1603 var pm = member as IParametersMember;
1605 var mc = member as MethodOrOperator;
1610 var p = pm.Parameters;
1614 ((ParametersCompiled) p).ResolveDefaultValues (member);
1617 var c = member as Const;
1622 base.PrepareEmit ();
1626 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1628 public override bool CreateContainer ()
1630 if (TypeBuilder != null)
1636 if (IsPartialPart) {
1637 spec = PartialContainer.spec;
1638 TypeBuilder = PartialContainer.TypeBuilder;
1639 all_tp_builders = PartialContainer.all_tp_builders;
1640 all_type_parameters = PartialContainer.all_type_parameters;
1642 if (!CreateTypeBuilder ()) {
1648 return base.CreateContainer ();
1651 protected override void DoDefineContainer ()
1655 DoResolveTypeParameters ();
1659 // Replaces normal spec with predefined one when compiling corlib
1660 // and this type container defines predefined type
1662 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1664 // When compiling build-in types we start with two
1665 // version of same type. One is of BuiltinTypeSpec and
1666 // second one is ordinary TypeSpec. The unification
1667 // happens at later stage when we know which type
1668 // really matches the builtin type signature. However
1669 // that means TypeSpec create during CreateType of this
1670 // type has to be replaced with builtin one
1672 spec.SetMetaInfo (TypeBuilder);
1673 spec.MemberCache = this.spec.MemberCache;
1674 spec.DeclaringType = this.spec.DeclaringType;
1677 current_type = null;
1680 public override void RemoveContainer (TypeContainer cont)
1682 base.RemoveContainer (cont);
1683 Members.Remove (cont);
1684 Cache.Remove (cont.Basename);
1687 protected virtual bool DoResolveTypeParameters ()
1689 var tparams = CurrentTypeParameters;
1690 if (tparams == null)
1693 var base_context = new BaseContext (this);
1694 for (int i = 0; i < tparams.Count; ++i) {
1695 var tp = tparams[i];
1697 if (!tp.ResolveConstraints (base_context)) {
1703 if (IsPartialPart) {
1704 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1710 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1712 if (InTransit != null)
1717 if (base_type != null) {
1718 var ptc = base_type.MemberDefinition as TypeDefinition;
1719 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1723 if (iface_exprs != null) {
1724 foreach (var iface in iface_exprs) {
1725 // the interface might not have been resolved, prevents a crash, see #442144
1728 var ptc = iface.MemberDefinition as Interface;
1729 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1734 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1742 /// Populates our TypeBuilder with fields and methods
1744 public sealed override bool Define ()
1746 if (members_defined)
1747 return members_defined_ok;
1749 members_defined_ok = DoDefineMembers ();
1750 members_defined = true;
1754 return members_defined_ok;
1757 protected virtual bool DoDefineMembers ()
1759 Debug.Assert (!IsPartialPart);
1761 if (iface_exprs != null) {
1762 foreach (var iface_type in iface_exprs) {
1763 if (iface_type == null)
1766 // Ensure the base is always setup
1767 var compiled_iface = iface_type.MemberDefinition as Interface;
1768 if (compiled_iface != null)
1769 compiled_iface.Define ();
1771 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1772 if (oa != null && !IsObsolete)
1773 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1775 if (iface_type.Arity > 0) {
1776 // TODO: passing `this' is wrong, should be base type iface instead
1777 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1779 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1780 Report.Error (1966, Location,
1781 "`{0}': cannot implement a dynamic interface `{1}'",
1782 GetSignatureForError (), iface_type.GetSignatureForError ());
1787 if (iface_type.IsGenericOrParentIsGeneric) {
1788 foreach (var prev_iface in iface_exprs) {
1789 if (prev_iface == iface_type || prev_iface == null)
1792 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1795 Report.Error (695, Location,
1796 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1797 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1802 if (Kind == MemberKind.Interface) {
1803 foreach (var iface in spec.Interfaces) {
1804 MemberCache.AddInterface (iface);
1809 if (base_type != null) {
1811 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1813 if (base_type_expr != null) {
1814 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1815 if (obsolete_attr != null && !IsObsolete)
1816 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1818 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1819 Report.Error (698, base_type_expr.Location,
1820 "A generic type cannot derive from `{0}' because it is an attribute class",
1821 base_type.GetSignatureForError ());
1825 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1826 if (baseContainer != null) {
1827 baseContainer.Define ();
1830 // It can trigger define of this type (for generic types only)
1832 if (HasMembersDefined)
1837 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1838 pending = PendingImplementation.GetPendingImplementations (this);
1841 var count = members.Count;
1842 for (int i = 0; i < count; ++i) {
1843 var mc = members[i] as InterfaceMemberBase;
1844 if (mc == null || !mc.IsExplicitImpl)
1849 } catch (Exception e) {
1850 throw new InternalErrorException (mc, e);
1854 for (int i = 0; i < count; ++i) {
1855 var mc = members[i] as InterfaceMemberBase;
1856 if (mc != null && mc.IsExplicitImpl)
1859 if (members[i] is TypeContainer)
1863 members[i].Define ();
1864 } catch (Exception e) {
1865 throw new InternalErrorException (members[i], e);
1870 CheckPairedOperators ();
1873 if (requires_delayed_unmanagedtype_check) {
1874 requires_delayed_unmanagedtype_check = false;
1875 foreach (var member in members) {
1876 var f = member as Field;
1877 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1878 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1882 ComputeIndexerName();
1884 if (HasEquals && !HasGetHashCode) {
1885 Report.Warning (659, 3, Location,
1886 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1889 if (Kind == MemberKind.Interface && iface_exprs != null) {
1890 MemberCache.RemoveHiddenMembers (spec);
1896 void ComputeIndexerName ()
1898 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1899 if (indexers == null)
1902 string class_indexer_name = null;
1905 // Check normal indexers for consistent name, explicit interface implementation
1906 // indexers are ignored
1908 foreach (var indexer in indexers) {
1910 // FindMembers can return unfiltered full hierarchy names
1912 if (indexer.DeclaringType != spec)
1915 has_normal_indexers = true;
1917 if (class_indexer_name == null) {
1918 indexer_name = class_indexer_name = indexer.Name;
1922 if (indexer.Name != class_indexer_name)
1923 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1924 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1928 void EmitIndexerName ()
1930 if (!has_normal_indexers)
1933 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1937 var encoder = new AttributeEncoder ();
1938 encoder.Encode (GetAttributeDefaultMember ());
1939 encoder.EncodeEmptyNamedArguments ();
1941 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1944 public override void VerifyMembers ()
1947 // Check for internal or private fields that were never assigned
1949 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1950 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1951 foreach (var member in members) {
1952 if (member is Event) {
1954 // An event can be assigned from same class only, so we can report
1955 // this warning for all accessibility modes
1958 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1963 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1964 if (is_type_exposed)
1967 member.SetIsUsed ();
1970 var f = member as Field;
1974 if (!member.IsUsed) {
1975 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1976 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1978 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1979 member.GetSignatureForError ());
1984 if ((f.caching_flags & Flags.IsAssigned) != 0)
1988 // Only report 649 on level 4
1990 if (Compiler.Settings.WarningLevel < 4)
1994 // Don't be pedantic when type requires specific layout
1996 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1999 Constant c = New.Constantify (f.MemberType, f.Location);
2002 value = c.GetValueAsLiteral ();
2003 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2010 value = " `" + value + "'";
2012 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2013 f.GetSignatureForError (), value);
2017 base.VerifyMembers ();
2020 public override void Emit ()
2022 if (OptAttributes != null)
2023 OptAttributes.Emit ();
2025 if (!IsCompilerGenerated) {
2027 MemberSpec candidate;
2028 bool overrides = false;
2029 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2030 if (conflict_symbol == null && candidate == null) {
2031 if ((ModFlags & Modifiers.NEW) != 0)
2032 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2033 GetSignatureForError ());
2035 if ((ModFlags & Modifiers.NEW) == 0) {
2036 if (candidate == null)
2037 candidate = conflict_symbol;
2039 Report.SymbolRelatedToPreviousError (candidate);
2040 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2041 GetSignatureForError (), candidate.GetSignatureForError ());
2046 // Run constraints check on all possible generic types
2047 if (base_type != null && base_type_expr != null) {
2048 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2051 if (iface_exprs != null) {
2052 foreach (var iface_type in iface_exprs) {
2053 if (iface_type == null)
2056 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2061 if (all_tp_builders != null) {
2062 int current_starts_index = CurrentTypeParametersStartIndex;
2063 for (int i = 0; i < all_tp_builders.Length; i++) {
2064 if (i < current_starts_index) {
2065 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2067 var tp = CurrentTypeParameters [i - current_starts_index];
2068 tp.CheckGenericConstraints (!IsObsolete);
2074 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2075 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2078 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2079 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2084 for (int i = 0; i < members.Count; i++)
2088 CheckAttributeClsCompliance ();
2090 if (pending != null)
2091 pending.VerifyPendingMethods ();
2095 void CheckAttributeClsCompliance ()
2097 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2100 foreach (var m in members) {
2101 var c = m as Constructor;
2105 if (c.HasCompliantArgs)
2109 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2112 public sealed override void EmitContainer ()
2114 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2120 public override void CloseContainer ()
2122 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2125 // Close base type container first to avoid TypeLoadException
2126 if (spec.BaseType != null) {
2127 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2128 if (btype != null) {
2129 btype.CloseContainer ();
2131 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2137 caching_flags |= Flags.CloseTypeCreated;
2138 TypeBuilder.CreateType ();
2139 } catch (TypeLoadException) {
2141 // This is fine, the code still created the type
2143 } catch (Exception e) {
2144 throw new InternalErrorException (this, e);
2147 base.CloseContainer ();
2150 initialized_fields = null;
2151 initialized_static_fields = null;
2153 OptAttributes = null;
2157 // Performs the validation on a Method's modifiers (properties have
2158 // the same properties).
2160 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2162 public bool MethodModifiersValid (MemberCore mc)
2164 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2165 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2167 var flags = mc.ModFlags;
2170 // At most one of static, virtual or override
2172 if ((flags & Modifiers.STATIC) != 0){
2173 if ((flags & vao) != 0){
2174 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2175 mc.GetSignatureForError ());
2180 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2181 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2182 mc.GetSignatureForError ());
2187 // If the declaration includes the abstract modifier, then the
2188 // declaration does not include static, virtual or extern
2190 if ((flags & Modifiers.ABSTRACT) != 0){
2191 if ((flags & Modifiers.EXTERN) != 0){
2193 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2197 if ((flags & Modifiers.SEALED) != 0) {
2198 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2202 if ((flags & Modifiers.VIRTUAL) != 0){
2203 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2207 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2208 Report.SymbolRelatedToPreviousError (this);
2209 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2210 mc.GetSignatureForError (), GetSignatureForError ());
2215 if ((flags & Modifiers.PRIVATE) != 0){
2216 if ((flags & vao) != 0){
2217 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2222 if ((flags & Modifiers.SEALED) != 0){
2223 if ((flags & Modifiers.OVERRIDE) == 0){
2224 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2232 protected override bool VerifyClsCompliance ()
2234 if (!base.VerifyClsCompliance ())
2237 // Check all container names for user classes
2238 if (Kind != MemberKind.Delegate)
2239 MemberCache.VerifyClsCompliance (Definition, Report);
2241 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2242 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2243 GetSignatureForError (), BaseType.GetSignatureForError ());
2249 /// Performs checks for an explicit interface implementation. First it
2250 /// checks whether the `interface_type' is a base inteface implementation.
2251 /// Then it checks whether `name' exists in the interface type.
2253 public bool VerifyImplements (InterfaceMemberBase mb)
2255 var ifaces = spec.Interfaces;
2256 if (ifaces != null) {
2257 foreach (TypeSpec t in ifaces){
2258 if (t == mb.InterfaceType)
2263 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2264 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2265 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2270 // Used for visiblity checks to tests whether this definition shares
2271 // base type baseType, it does member-definition search
2273 public bool IsBaseTypeDefinition (TypeSpec baseType)
2275 // RootContext check
2276 if (TypeBuilder == null)
2281 if (type.MemberDefinition == baseType.MemberDefinition)
2284 type = type.BaseType;
2285 } while (type != null);
2290 public override bool IsClsComplianceRequired ()
2293 return PartialContainer.IsClsComplianceRequired ();
2295 return base.IsClsComplianceRequired ();
2298 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2300 return Module.DeclaringAssembly == assembly;
2303 public virtual bool IsUnmanagedType ()
2308 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2310 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2314 // Public function used to locate types.
2316 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2318 // Returns: Type or null if they type can not be found.
2320 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2322 FullNamedExpression e;
2323 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2329 var tp = CurrentTypeParameters;
2331 TypeParameter tparam = tp.Find (name);
2333 e = new TypeParameterExpr (tparam, Location.Null);
2338 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2340 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2341 e = new TypeExpression (t, Location.Null);
2343 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2347 // TODO MemberCache: How to cache arity stuff ?
2348 if (arity == 0 && mode == LookupMode.Normal)
2354 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2356 // Has any nested type
2357 // Does not work, because base type can have
2358 //if (PartialContainer.Types == null)
2361 var container = PartialContainer.CurrentType;
2362 return MemberCache.FindNestedType (container, name, arity);
2365 public void Mark_HasEquals ()
2367 cached_method |= CachedMethods.Equals;
2370 public void Mark_HasGetHashCode ()
2372 cached_method |= CachedMethods.GetHashCode;
2375 public override void WriteDebugSymbol (MonoSymbolFile file)
2380 foreach (var m in members) {
2381 m.WriteDebugSymbol (file);
2386 /// Method container contains Equals method
2388 public bool HasEquals {
2390 return (cached_method & CachedMethods.Equals) != 0;
2395 /// Method container contains GetHashCode method
2397 public bool HasGetHashCode {
2399 return (cached_method & CachedMethods.GetHashCode) != 0;
2403 public bool HasStaticFieldInitializer {
2405 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2409 cached_method |= CachedMethods.HasStaticFieldInitializer;
2411 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2415 public override string DocCommentHeader {
2416 get { return "T:"; }
2420 public abstract class ClassOrStruct : TypeDefinition
2422 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2424 SecurityType declarative_security;
2426 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2427 : base (parent, name, attrs, kind)
2431 protected override TypeAttributes TypeAttr {
2433 TypeAttributes ta = base.TypeAttr;
2434 if (!has_static_constructor)
2435 ta |= TypeAttributes.BeforeFieldInit;
2437 if (Kind == MemberKind.Class) {
2438 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2440 ta |= StaticClassAttribute;
2442 ta |= TypeAttributes.SequentialLayout;
2449 public override void AddNameToContainer (MemberCore symbol, string name)
2451 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2452 if (symbol is TypeParameter) {
2453 Report.Error (694, symbol.Location,
2454 "Type parameter `{0}' has same name as containing type, or method",
2455 symbol.GetSignatureForError ());
2459 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2460 if (imb == null || !imb.IsExplicitImpl) {
2461 Report.SymbolRelatedToPreviousError (this);
2462 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2463 symbol.GetSignatureForError ());
2468 base.AddNameToContainer (symbol, name);
2471 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2473 if (a.IsValidSecurityAttribute ()) {
2474 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2478 if (a.Type == pa.StructLayout) {
2479 PartialContainer.HasStructLayout = true;
2480 if (a.IsExplicitLayoutKind ())
2481 PartialContainer.HasExplicitLayout = true;
2484 if (a.Type == pa.Dynamic) {
2485 a.Error_MisusedDynamicAttribute ();
2489 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2493 /// Defines the default constructors
2495 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2497 // The default instance constructor is public
2498 // If the class is abstract, the default constructor is protected
2499 // The default static constructor is private
2503 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2505 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2508 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2509 c.Initializer = new GeneratedBaseInitializer (Location);
2511 AddConstructor (c, true);
2512 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2513 IsCompilerGenerated = true
2519 protected override bool DoDefineMembers ()
2521 CheckProtectedModifier ();
2523 base.DoDefineMembers ();
2528 public override void Emit ()
2530 if (!has_static_constructor && HasStaticFieldInitializer) {
2531 var c = DefineDefaultConstructor (true);
2537 if (declarative_security != null) {
2538 foreach (var de in declarative_security) {
2540 TypeBuilder.__AddDeclarativeSecurity (de);
2542 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2550 public sealed class Class : ClassOrStruct
2552 const Modifiers AllowedModifiers =
2555 Modifiers.PROTECTED |
2556 Modifiers.INTERNAL |
2558 Modifiers.ABSTRACT |
2563 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2564 : base (parent, name, attrs, MemberKind.Class)
2566 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2567 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2568 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2571 public override void Accept (StructuralVisitor visitor)
2573 visitor.Visit (this);
2576 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2578 var pmn = MemberName;
2579 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2580 Report.Error (537, Location,
2581 "The class System.Object cannot have a base class or implement an interface.");
2583 base.SetBaseTypes (baseTypes);
2586 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2588 if (a.Type == pa.AttributeUsage) {
2589 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2590 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2594 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2595 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2599 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2600 a.Error_MissingGuidAttribute ();
2604 if (a.Type == pa.Extension) {
2605 a.Error_MisusedExtensionAttribute ();
2609 if (a.Type.IsConditionallyExcluded (this, Location))
2612 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2615 public override AttributeTargets AttributeTargets {
2617 return AttributeTargets.Class;
2621 protected override bool DoDefineMembers ()
2623 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2624 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2627 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2628 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2632 foreach (var m in Members) {
2633 if (m is Operator) {
2634 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2638 if (m is Destructor) {
2639 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2644 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2648 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2651 if (m is Constructor) {
2652 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2656 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2659 if (!PartialContainer.HasInstanceConstructor)
2660 DefineDefaultConstructor (false);
2663 return base.DoDefineMembers ();
2666 public override void Emit ()
2670 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2671 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2673 if (base_type != null && base_type.HasDynamicElement) {
2674 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2678 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2680 var ifaces = base.ResolveBaseTypes (out base_class);
2682 if (base_class == null) {
2683 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2684 base_type = Compiler.BuiltinTypes.Object;
2686 if (base_type.IsGenericParameter){
2687 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2688 GetSignatureForError (), base_type.GetSignatureForError ());
2689 } else if (base_type.IsStatic) {
2690 Report.SymbolRelatedToPreviousError (base_type);
2691 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2692 GetSignatureForError (), base_type.GetSignatureForError ());
2693 } else if (base_type.IsSealed) {
2694 Report.SymbolRelatedToPreviousError (base_type);
2695 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2696 GetSignatureForError (), base_type.GetSignatureForError ());
2697 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2698 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2699 GetSignatureForError (), base_type.GetSignatureForError ());
2702 switch (base_type.BuiltinType) {
2703 case BuiltinTypeSpec.Type.Enum:
2704 case BuiltinTypeSpec.Type.ValueType:
2705 case BuiltinTypeSpec.Type.MulticastDelegate:
2706 case BuiltinTypeSpec.Type.Delegate:
2707 case BuiltinTypeSpec.Type.Array:
2708 if (!(spec is BuiltinTypeSpec)) {
2709 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2710 GetSignatureForError (), base_type.GetSignatureForError ());
2712 base_type = Compiler.BuiltinTypes.Object;
2717 if (!IsAccessibleAs (base_type)) {
2718 Report.SymbolRelatedToPreviousError (base_type);
2719 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2720 base_type.GetSignatureForError (), GetSignatureForError ());
2724 if (PartialContainer.IsStatic && ifaces != null) {
2725 foreach (var t in ifaces)
2726 Report.SymbolRelatedToPreviousError (t);
2727 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2733 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2734 /// Valid only for attribute classes.
2735 public override string[] ConditionalConditions ()
2737 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2740 caching_flags &= ~Flags.Excluded_Undetected;
2742 if (OptAttributes == null)
2745 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2749 string[] conditions = new string[attrs.Length];
2750 for (int i = 0; i < conditions.Length; ++i)
2751 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2753 caching_flags |= Flags.Excluded;
2758 public sealed class Struct : ClassOrStruct
2760 bool is_unmanaged, has_unmanaged_check_done;
2764 // Modifiers allowed in a struct declaration
2766 const Modifiers AllowedModifiers =
2769 Modifiers.PROTECTED |
2770 Modifiers.INTERNAL |
2774 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2775 : base (parent, name, attrs, MemberKind.Struct)
2777 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2778 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2779 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2782 public override AttributeTargets AttributeTargets {
2784 return AttributeTargets.Struct;
2788 public override void Accept (StructuralVisitor visitor)
2790 visitor.Visit (this);
2793 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2795 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2798 // When struct constains fixed fixed and struct layout has explicitly
2799 // set CharSet, its value has to be propagated to compiler generated
2802 if (a.Type == pa.StructLayout) {
2803 var value = a.GetNamedValue ("CharSet");
2807 for (int i = 0; i < Members.Count; ++i) {
2808 FixedField ff = Members [i] as FixedField;
2812 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2817 bool CheckStructCycles ()
2823 foreach (var member in Members) {
2824 var field = member as Field;
2828 TypeSpec ftype = field.Spec.MemberType;
2829 if (!ftype.IsStruct)
2832 if (ftype is BuiltinTypeSpec)
2835 foreach (var targ in ftype.TypeArguments) {
2836 if (!CheckFieldTypeCycle (targ)) {
2837 Report.Error (523, field.Location,
2838 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2839 field.GetSignatureForError (), ftype.GetSignatureForError ());
2845 // Static fields of exactly same type are allowed
2847 if (field.IsStatic && ftype == CurrentType)
2850 if (!CheckFieldTypeCycle (ftype)) {
2851 Report.Error (523, field.Location,
2852 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2853 field.GetSignatureForError (), ftype.GetSignatureForError ());
2862 static bool CheckFieldTypeCycle (TypeSpec ts)
2864 var fts = ts.MemberDefinition as Struct;
2868 return fts.CheckStructCycles ();
2871 public override void Emit ()
2873 CheckStructCycles ();
2878 public override bool IsUnmanagedType ()
2880 if (has_unmanaged_check_done)
2881 return is_unmanaged;
2883 if (requires_delayed_unmanagedtype_check)
2886 var parent_def = Parent.PartialContainer;
2887 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2888 has_unmanaged_check_done = true;
2892 if (first_nonstatic_field != null) {
2893 requires_delayed_unmanagedtype_check = true;
2895 foreach (var member in Members) {
2896 var f = member as Field;
2903 // It can happen when recursive unmanaged types are defined
2904 // struct S { S* s; }
2905 TypeSpec mt = f.MemberType;
2913 has_unmanaged_check_done = true;
2917 has_unmanaged_check_done = true;
2920 is_unmanaged = true;
2924 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2926 var ifaces = base.ResolveBaseTypes (out base_class);
2927 base_type = Compiler.BuiltinTypes.ValueType;
2931 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2933 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2934 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2935 field.GetSignatureForError ());
2938 base.RegisterFieldForInitialization (field, expression);
2946 public sealed class Interface : TypeDefinition {
2949 /// Modifiers allowed in a class declaration
2951 const Modifiers AllowedModifiers =
2954 Modifiers.PROTECTED |
2955 Modifiers.INTERNAL |
2959 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2960 : base (parent, name, attrs, MemberKind.Interface)
2962 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2964 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2965 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2970 public override AttributeTargets AttributeTargets {
2972 return AttributeTargets.Interface;
2976 protected override TypeAttributes TypeAttr {
2978 const TypeAttributes DefaultTypeAttributes =
2979 TypeAttributes.AutoLayout |
2980 TypeAttributes.Abstract |
2981 TypeAttributes.Interface;
2983 return base.TypeAttr | DefaultTypeAttributes;
2989 public override void Accept (StructuralVisitor visitor)
2991 visitor.Visit (this);
2994 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2996 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2997 a.Error_MissingGuidAttribute ();
3001 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3004 protected override bool VerifyClsCompliance ()
3006 if (!base.VerifyClsCompliance ())
3009 if (iface_exprs != null) {
3010 foreach (var iface in iface_exprs) {
3011 if (iface.IsCLSCompliant ())
3014 Report.SymbolRelatedToPreviousError (iface);
3015 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3016 GetSignatureForError (), iface.GetSignatureForError ());
3024 public abstract class InterfaceMemberBase : MemberBase
3027 // Common modifiers allowed in a class declaration
3029 protected const Modifiers AllowedModifiersClass =
3032 Modifiers.PROTECTED |
3033 Modifiers.INTERNAL |
3038 Modifiers.OVERRIDE |
3039 Modifiers.ABSTRACT |
3044 // Common modifiers allowed in a struct declaration
3046 protected const Modifiers AllowedModifiersStruct =
3049 Modifiers.PROTECTED |
3050 Modifiers.INTERNAL |
3053 Modifiers.OVERRIDE |
3058 // Common modifiers allowed in a interface declaration
3060 protected const Modifiers AllowedModifiersInterface =
3065 // Whether this is an interface member.
3067 public bool IsInterface;
3070 // If true, this is an explicit interface implementation
3072 public readonly bool IsExplicitImpl;
3074 protected bool is_external_implementation;
3077 // The interface type we are explicitly implementing
3079 public TypeSpec InterfaceType;
3082 // The method we're overriding if this is an override method.
3084 protected MethodSpec base_method;
3086 readonly Modifiers explicit_mod_flags;
3087 public MethodAttributes flags;
3089 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3090 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3092 IsInterface = parent.Kind == MemberKind.Interface;
3093 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3094 explicit_mod_flags = mod;
3097 public abstract Variance ExpectedMemberTypeVariance { get; }
3099 protected override bool CheckBase ()
3101 if (!base.CheckBase ())
3104 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3105 CheckForDuplications ();
3110 // For System.Object only
3111 if (Parent.BaseType == null)
3114 MemberSpec candidate;
3115 bool overrides = false;
3116 var base_member = FindBaseMember (out candidate, ref overrides);
3118 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3119 if (base_member == null) {
3120 if (candidate == null) {
3121 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3122 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3123 "object.Finalize()");
3125 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3126 GetSignatureForError (), SimpleName.GetMemberType (this));
3129 Report.SymbolRelatedToPreviousError (candidate);
3131 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3132 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3133 else if (this is PropertyBase)
3134 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3135 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3137 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3138 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3145 // Handles ambiguous overrides
3147 if (candidate != null) {
3148 Report.SymbolRelatedToPreviousError (candidate);
3149 Report.SymbolRelatedToPreviousError (base_member);
3151 // Get member definition for error reporting
3152 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3153 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3155 Report.Error (462, Location,
3156 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3157 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3160 if (!CheckOverrideAgainstBase (base_member))
3163 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3165 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3166 Report.SymbolRelatedToPreviousError (base_member);
3167 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3168 GetSignatureForError (), base_member.GetSignatureForError ());
3171 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3172 Report.SymbolRelatedToPreviousError (base_member);
3173 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3174 GetSignatureForError (), base_member.GetSignatureForError ());
3178 base_method = base_member as MethodSpec;
3182 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3183 base_member = candidate;
3185 if (base_member == null) {
3186 if ((ModFlags & Modifiers.NEW) != 0) {
3187 if (base_member == null) {
3188 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3189 GetSignatureForError ());
3193 if ((ModFlags & Modifiers.NEW) == 0) {
3194 ModFlags |= Modifiers.NEW;
3195 if (!IsCompilerGenerated) {
3196 Report.SymbolRelatedToPreviousError (base_member);
3197 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3198 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",
3199 GetSignatureForError (), base_member.GetSignatureForError ());
3201 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3202 GetSignatureForError (), base_member.GetSignatureForError ());
3207 if (!IsInterface && base_member.IsAbstract && !overrides) {
3208 Report.SymbolRelatedToPreviousError (base_member);
3209 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3210 GetSignatureForError (), base_member.GetSignatureForError ());
3217 protected virtual bool CheckForDuplications ()
3219 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3223 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3224 // that have been defined.
3226 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3230 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3231 Report.SymbolRelatedToPreviousError (base_member);
3232 Report.Error (506, Location,
3233 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3234 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3238 // Now we check that the overriden method is not final
3239 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3240 Report.SymbolRelatedToPreviousError (base_member);
3241 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3242 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3246 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3247 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3248 Report.SymbolRelatedToPreviousError (base_member);
3249 if (this is PropertyBasedMember) {
3250 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3251 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3253 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3254 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3262 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3264 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3265 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3267 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3269 // It must be at least "protected"
3271 if ((thisp & Modifiers.PROTECTED) == 0) {
3276 // when overriding protected internal, the method can be declared
3277 // protected internal only within the same assembly or assembly
3278 // which has InternalsVisibleTo
3280 if ((thisp & Modifiers.INTERNAL) != 0) {
3281 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3285 // protected overriding protected internal inside same assembly
3286 // requires internal modifier as well
3288 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3295 return thisp == base_classp;
3298 public override bool Define ()
3301 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3302 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3304 flags = MethodAttributes.Public |
3305 MethodAttributes.Abstract |
3306 MethodAttributes.HideBySig |
3307 MethodAttributes.NewSlot |
3308 MethodAttributes.Virtual;
3310 Parent.PartialContainer.MethodModifiersValid (this);
3312 flags = ModifiersExtensions.MethodAttr (ModFlags);
3315 if (IsExplicitImpl) {
3316 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3317 if (InterfaceType == null)
3320 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3321 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3322 GetSignatureForError ());
3325 if (!InterfaceType.IsInterface) {
3326 Report.SymbolRelatedToPreviousError (InterfaceType);
3327 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3328 InterfaceType.GetSignatureForError ());
3330 Parent.PartialContainer.VerifyImplements (this);
3333 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3336 return base.Define ();
3339 protected bool DefineParameters (ParametersCompiled parameters)
3341 if (!parameters.Resolve (this))
3345 for (int i = 0; i < parameters.Count; ++i) {
3346 Parameter p = parameters [i];
3348 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3349 p.Warning_UselessOptionalParameter (Report);
3351 if (p.CheckAccessibility (this))
3354 TypeSpec t = parameters.Types [i];
3355 Report.SymbolRelatedToPreviousError (t);
3356 if (this is Indexer)
3357 Report.Error (55, Location,
3358 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3359 t.GetSignatureForError (), GetSignatureForError ());
3360 else if (this is Operator)
3361 Report.Error (57, Location,
3362 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3363 t.GetSignatureForError (), GetSignatureForError ());
3365 Report.Error (51, Location,
3366 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3367 t.GetSignatureForError (), GetSignatureForError ());
3373 protected override void DoMemberTypeDependentChecks ()
3375 base.DoMemberTypeDependentChecks ();
3377 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3380 public override void Emit()
3382 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3383 // We are more strict than csc and report this as an error because SRE does not allow emit that
3384 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3385 if (this is Constructor) {
3386 Report.Warning (824, 1, Location,
3387 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3389 Report.Warning (626, 1, Location,
3390 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3391 GetSignatureForError ());
3398 public override bool EnableOverloadChecks (MemberCore overload)
3401 // Two members can differ in their explicit interface
3402 // type parameter only
3404 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3405 if (imb != null && imb.IsExplicitImpl) {
3406 if (IsExplicitImpl) {
3407 caching_flags |= Flags.MethodOverloadsExist;
3412 return IsExplicitImpl;
3415 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3417 var base_modifiers = base_member.Modifiers;
3419 // Remove internal modifier from types which are not internally accessible
3420 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3421 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3422 base_modifiers = Modifiers.PROTECTED;
3424 Report.SymbolRelatedToPreviousError (base_member);
3425 Report.Error (507, member.Location,
3426 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3427 member.GetSignatureForError (),
3428 ModifiersExtensions.AccessibilityName (base_modifiers),
3429 base_member.GetSignatureForError ());
3432 protected void Error_StaticReturnType ()
3434 Report.Error (722, Location,
3435 "`{0}': static types cannot be used as return types",
3436 MemberType.GetSignatureForError ());
3440 /// Gets base method and its return type
3442 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3444 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3448 // The "short" name of this property / indexer / event. This is the
3449 // name without the explicit interface.
3451 public string ShortName {
3452 get { return MemberName.Name; }
3456 // Returns full metadata method name
3458 public string GetFullName (MemberName name)
3460 return GetFullName (name.Name);
3463 public string GetFullName (string name)
3465 if (!IsExplicitImpl)
3469 // When dealing with explicit members a full interface type
3470 // name is added to member name to avoid possible name conflicts
3472 // We use CSharpName which gets us full name with benefit of
3473 // replacing predefined names which saves some space and name
3476 return InterfaceType.GetSignatureForError () + "." + name;
3479 public override string GetSignatureForDocumentation ()
3482 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3484 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3487 public override bool IsUsed
3489 get { return IsExplicitImpl || base.IsUsed; }
3492 public override void SetConstraints (List<Constraints> constraints_list)
3494 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3495 Report.Error (460, Location,
3496 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3497 GetSignatureForError ());
3500 base.SetConstraints (constraints_list);
3504 public abstract class MemberBase : MemberCore
3506 protected FullNamedExpression type_expr;
3507 protected TypeSpec member_type;
3508 public new TypeDefinition Parent;
3510 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3511 : base (parent, name, attrs)
3513 this.Parent = parent;
3514 this.type_expr = type;
3516 if (name != MemberName.Null)
3517 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3522 public TypeSpec MemberType {
3528 public FullNamedExpression TypeExpression {
3537 // Main member define entry
3539 public override bool Define ()
3541 DoMemberTypeIndependentChecks ();
3544 // Returns false only when type resolution failed
3546 if (!ResolveMemberType ())
3549 DoMemberTypeDependentChecks ();
3554 // Any type_name independent checks
3556 protected virtual void DoMemberTypeIndependentChecks ()
3558 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3559 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3560 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3561 GetSignatureForError (), Parent.GetSignatureForError ());
3566 // Any type_name dependent checks
3568 protected virtual void DoMemberTypeDependentChecks ()
3570 // verify accessibility
3571 if (!IsAccessibleAs (MemberType)) {
3572 Report.SymbolRelatedToPreviousError (MemberType);
3573 if (this is Property)
3574 Report.Error (53, Location,
3575 "Inconsistent accessibility: property type `" +
3576 MemberType.GetSignatureForError () + "' is less " +
3577 "accessible than property `" + GetSignatureForError () + "'");
3578 else if (this is Indexer)
3579 Report.Error (54, Location,
3580 "Inconsistent accessibility: indexer return type `" +
3581 MemberType.GetSignatureForError () + "' is less " +
3582 "accessible than indexer `" + GetSignatureForError () + "'");
3583 else if (this is MethodCore) {
3584 if (this is Operator)
3585 Report.Error (56, Location,
3586 "Inconsistent accessibility: return type `" +
3587 MemberType.GetSignatureForError () + "' is less " +
3588 "accessible than operator `" + GetSignatureForError () + "'");
3590 Report.Error (50, Location,
3591 "Inconsistent accessibility: return type `" +
3592 MemberType.GetSignatureForError () + "' is less " +
3593 "accessible than method `" + GetSignatureForError () + "'");
3595 Report.Error (52, Location,
3596 "Inconsistent accessibility: field type `" +
3597 MemberType.GetSignatureForError () + "' is less " +
3598 "accessible than field `" + GetSignatureForError () + "'");
3603 protected void IsTypePermitted ()
3605 if (MemberType.IsSpecialRuntimeType) {
3606 if (Parent is StateMachine) {
3607 Report.Error (4012, Location,
3608 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3609 MemberType.GetSignatureForError ());
3610 } else if (Parent is HoistedStoreyClass) {
3611 Report.Error (4013, Location,
3612 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3613 MemberType.GetSignatureForError ());
3615 Report.Error (610, Location,
3616 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3621 protected virtual bool CheckBase ()
3623 CheckProtectedModifier ();
3628 public override string GetSignatureForDocumentation ()
3630 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3633 protected virtual bool ResolveMemberType ()
3635 if (member_type != null)
3636 throw new InternalErrorException ("Multi-resolve");
3638 member_type = type_expr.ResolveAsType (this);
3639 return member_type != null;