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;
22 using System.Diagnostics;
23 using Mono.CompilerServices.SymbolWriter;
26 using XmlElement = System.Object;
30 using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
31 using IKVM.Reflection;
32 using IKVM.Reflection.Emit;
34 using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
35 using System.Reflection;
36 using System.Reflection.Emit;
42 // General types container, used as a base class for all constructs which can hold types
44 public abstract class TypeContainer : MemberCore
46 public readonly MemberKind Kind;
47 public readonly string Basename;
49 protected List<TypeContainer> containers;
51 TypeDefinition main_container;
53 protected Dictionary<string, MemberCore> defined_names;
55 protected bool is_defined;
57 public TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
58 : base (parent, name, attrs)
62 this.Basename = name.Basename;
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. User
98 public Attributes UnattachedAttributes {
102 public virtual void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 if (containers == null)
192 containers = new List<TypeContainer> ();
194 containers.Add (next_part);
197 public virtual void AddTypeContainer (TypeContainer tc)
201 var tparams = tc.MemberName.TypeParameters;
202 if (tparams != null && tc.PartialContainer != null) {
203 var td = (TypeDefinition) tc;
204 for (int i = 0; i < tparams.Count; ++i) {
206 if (tp.MemberName == null)
209 td.AddNameToContainer (tp, tp.Name);
214 public virtual void CloseContainer ()
216 if (containers != null) {
217 foreach (TypeContainer tc in containers) {
218 tc.CloseContainer ();
223 public virtual void CreateMetadataName (StringBuilder sb)
225 if (Parent != null && Parent.MemberName != null)
226 Parent.CreateMetadataName (sb);
228 MemberName.CreateMetadataName (sb);
231 public virtual bool CreateContainer ()
233 if (containers != null) {
234 foreach (TypeContainer tc in containers) {
235 tc.CreateContainer ();
242 public override bool Define ()
244 if (containers != null) {
245 foreach (TypeContainer tc in containers) {
250 // Release cache used by parser only
251 if (Module.Evaluator == null) {
252 defined_names = null;
254 defined_names.Clear ();
260 public virtual void PrepareEmit ()
262 if (containers != null) {
263 foreach (var t in containers) {
266 } catch (Exception e) {
267 if (MemberName == MemberName.Null)
270 throw new InternalErrorException (t, e);
276 public virtual bool DefineContainer ()
283 DoDefineContainer ();
285 if (containers != null) {
286 foreach (TypeContainer tc in containers) {
288 tc.DefineContainer ();
289 } catch (Exception e) {
290 if (MemberName == MemberName.Null)
293 throw new InternalErrorException (tc, e);
301 public virtual void ExpandBaseInterfaces ()
303 if (containers != null) {
304 foreach (TypeContainer tc in containers) {
305 tc.ExpandBaseInterfaces ();
310 protected virtual void DefineNamespace ()
312 if (containers != null) {
313 foreach (var tc in containers) {
315 tc.DefineNamespace ();
316 } catch (Exception e) {
317 throw new InternalErrorException (tc, e);
323 protected virtual void DoDefineContainer ()
327 public virtual void EmitContainer ()
329 if (containers != null) {
330 for (int i = 0; i < containers.Count; ++i)
331 containers[i].EmitContainer ();
335 protected void Error_MissingPartialModifier (MemberCore type)
337 Report.Error (260, type.Location,
338 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
339 type.GetSignatureForError ());
342 public override string GetSignatureForDocumentation ()
344 if (Parent != null && Parent.MemberName != null)
345 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
347 return MemberName.GetSignatureForDocumentation ();
350 public override string GetSignatureForError ()
352 if (Parent != null && Parent.MemberName != null)
353 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
355 return MemberName.GetSignatureForError ();
358 public string GetSignatureForMetadata ()
361 if (Parent is TypeDefinition) {
362 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
365 var sb = new StringBuilder ();
366 CreateMetadataName (sb);
367 return sb.ToString ();
369 throw new NotImplementedException ();
373 public virtual void RemoveContainer (TypeContainer cont)
375 if (containers != null)
376 containers.Remove (cont);
378 var tc = Parent == Module ? Module : this;
379 tc.defined_names.Remove (cont.Basename);
382 public virtual void VerifyMembers ()
384 if (containers != null) {
385 foreach (TypeContainer tc in containers)
390 public override void WriteDebugSymbol (MonoSymbolFile file)
392 if (containers != null) {
393 foreach (TypeContainer tc in containers) {
394 tc.WriteDebugSymbol (file);
400 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
403 // Different context is needed when resolving type container base
404 // types. Type names come from the parent scope but type parameter
405 // names from the container scope.
407 public struct BaseContext : IMemberContext
411 public BaseContext (TypeContainer tc)
416 #region IMemberContext Members
418 public CompilerContext Compiler {
419 get { return tc.Compiler; }
422 public TypeSpec CurrentType {
423 get { return tc.Parent.CurrentType; }
426 public TypeParameters CurrentTypeParameters {
427 get { return tc.PartialContainer.CurrentTypeParameters; }
430 public MemberCore CurrentMemberDefinition {
434 public bool IsObsolete {
435 get { return tc.IsObsolete; }
438 public bool IsUnsafe {
439 get { return tc.IsUnsafe; }
442 public bool IsStatic {
443 get { return tc.IsStatic; }
446 public ModuleContainer Module {
447 get { return tc.Module; }
450 public string GetSignatureForError ()
452 return tc.GetSignatureForError ();
455 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
460 public FullNamedExpression LookupNamespaceAlias (string name)
462 return tc.Parent.LookupNamespaceAlias (name);
465 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
468 var tp = CurrentTypeParameters;
470 TypeParameter t = tp.Find (name);
472 return new TypeParameterExpr (t, loc);
476 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
486 GetHashCode = 1 << 1,
487 HasStaticFieldInitializer = 1 << 2
490 readonly List<MemberCore> members;
492 // Holds a list of fields that have initializers
493 protected List<FieldInitializer> initialized_fields;
495 // Holds a list of static fields that have initializers
496 protected List<FieldInitializer> initialized_static_fields;
498 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
500 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
503 // Points to the first non-static field added to the container.
505 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
506 // and the first one's as good as any.
508 protected FieldBase first_nonstatic_field;
511 // This one is computed after we can distinguish interfaces
512 // from classes from the arraylist `type_bases'
514 protected TypeSpec base_type;
515 FullNamedExpression base_type_expr; // TODO: It's temporary variable
516 protected TypeSpec[] iface_exprs;
518 protected List<FullNamedExpression> type_bases;
520 TypeDefinition InTransit;
522 public TypeBuilder TypeBuilder;
523 GenericTypeParameterBuilder[] all_tp_builders;
525 // All recursive type parameters put together sharing same
526 // TypeParameter instances
528 TypeParameters all_type_parameters;
530 public const string DefaultIndexerName = "Item";
532 bool has_normal_indexers;
534 protected bool requires_delayed_unmanagedtype_check;
536 bool members_defined;
537 bool members_defined_ok;
538 protected bool has_static_constructor;
540 private CachedMethods cached_method;
542 protected TypeSpec spec;
543 TypeSpec current_type;
545 public int DynamicSitesCounter;
546 public int AnonymousMethodsCounter;
547 public int MethodGroupsCounter;
549 static readonly string[] attribute_targets = new string[] { "type" };
552 /// The pending methods that need to be implemented
553 // (interfaces or abstract methods)
555 PendingImplementation pending;
557 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
558 : base (parent, name, attrs, kind)
560 PartialContainer = this;
561 members = new List<MemberCore> ();
566 public List<FullNamedExpression> BaseTypeExpressions {
572 public override TypeSpec CurrentType {
574 if (current_type == null) {
575 if (IsGenericOrParentIsGeneric) {
577 // Switch to inflated version as it's used by all expressions
579 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
580 current_type = spec.MakeGenericType (this, targs);
590 public override TypeParameters CurrentTypeParameters {
592 return PartialContainer.MemberName.TypeParameters;
596 int CurrentTypeParametersStartIndex {
598 int total = all_tp_builders.Length;
599 if (CurrentTypeParameters != null) {
600 return total - CurrentTypeParameters.Count;
606 public virtual AssemblyDefinition DeclaringAssembly {
608 return Module.DeclaringAssembly;
612 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
614 return Module.DeclaringAssembly;
618 public TypeSpec Definition {
624 public bool HasMembersDefined {
626 return members_defined;
630 public bool HasInstanceConstructor {
632 return (caching_flags & Flags.HasInstanceConstructor) != 0;
635 caching_flags |= Flags.HasInstanceConstructor;
639 // Indicated whether container has StructLayout attribute set Explicit
640 public bool HasExplicitLayout {
641 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
642 set { caching_flags |= Flags.HasExplicitLayout; }
645 public bool HasOperators {
647 return (caching_flags & Flags.HasUserOperators) != 0;
650 caching_flags |= Flags.HasUserOperators;
654 public bool HasStructLayout {
655 get { return (caching_flags & Flags.HasStructLayout) != 0; }
656 set { caching_flags |= Flags.HasStructLayout; }
659 public TypeSpec[] Interfaces {
665 public bool IsGenericOrParentIsGeneric {
667 return all_type_parameters != null;
671 public bool IsTopLevel {
673 return !(Parent is TypeDefinition);
677 public bool IsPartial {
679 return (ModFlags & Modifiers.PARTIAL) != 0;
683 bool ITypeDefinition.IsTypeForwarder {
690 // Returns true for secondary partial containers
694 return PartialContainer != this;
698 public MemberCache MemberCache {
700 return spec.MemberCache;
704 public List<MemberCore> Members {
710 string ITypeDefinition.Namespace {
713 while (p.Kind != MemberKind.Namespace)
716 return p.MemberName == null ? null : p.GetSignatureForError ();
720 public TypeParameters TypeParametersAll {
722 return all_type_parameters;
726 public override string[] ValidAttributeTargets {
728 return attribute_targets;
734 public override void Accept (StructuralVisitor visitor)
736 visitor.Visit (this);
739 public void AddMember (MemberCore symbol)
741 if (symbol.MemberName.ExplicitInterface != null) {
742 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
743 Report.Error (541, symbol.Location,
744 "`{0}': explicit interface declaration can only be declared in a class or struct",
745 symbol.GetSignatureForError ());
749 AddNameToContainer (symbol, symbol.MemberName.Basename);
750 members.Add (symbol);
753 public override void AddTypeContainer (TypeContainer tc)
755 AddNameToContainer (tc, tc.Basename);
757 if (containers == null)
758 containers = new List<TypeContainer> ();
761 base.AddTypeContainer (tc);
764 public override void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
768 if (containers == null)
769 containers = new List<TypeContainer> ();
771 base.AddCompilerGeneratedClass (c);
775 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
777 public virtual void AddNameToContainer (MemberCore symbol, string name)
779 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
783 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
784 PartialContainer.defined_names.Add (name, symbol);
788 if (symbol.EnableOverloadChecks (mc))
791 InterfaceMemberBase im = mc as InterfaceMemberBase;
792 if (im != null && im.IsExplicitImpl)
795 Report.SymbolRelatedToPreviousError (mc);
796 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
797 Error_MissingPartialModifier (symbol);
801 if (symbol is TypeParameter) {
802 Report.Error (692, symbol.Location,
803 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
805 Report.Error (102, symbol.Location,
806 "The type `{0}' already contains a definition for `{1}'",
807 GetSignatureForError (), name);
813 public void AddConstructor (Constructor c)
815 AddConstructor (c, false);
818 public void AddConstructor (Constructor c, bool isDefault)
820 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
822 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
824 if (is_static && c.ParameterInfo.IsEmpty) {
825 PartialContainer.has_static_constructor = true;
827 PartialContainer.HasInstanceConstructor = true;
833 public bool AddField (FieldBase field)
837 if ((field.ModFlags & Modifiers.STATIC) != 0)
840 var first_field = PartialContainer.first_nonstatic_field;
841 if (first_field == null) {
842 PartialContainer.first_nonstatic_field = field;
846 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
847 Report.SymbolRelatedToPreviousError (first_field.Parent);
848 Report.Warning (282, 3, field.Location,
849 "struct instance field `{0}' found in different declaration from instance field `{1}'",
850 field.GetSignatureForError (), first_field.GetSignatureForError ());
856 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
858 public void AddIndexer (Indexer i)
863 public void AddOperator (Operator op)
865 PartialContainer.HasOperators = true;
869 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
871 if (has_normal_indexers && a.Type == pa.DefaultMember) {
872 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
876 if (a.Type == pa.Required) {
877 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
881 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
884 public override AttributeTargets AttributeTargets {
886 throw new NotSupportedException ();
890 public TypeSpec BaseType {
892 return spec.BaseType;
896 protected virtual TypeAttributes TypeAttr {
898 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
902 public int TypeParametersCount {
904 return MemberName.Arity;
908 TypeParameterSpec[] ITypeDefinition.TypeParameters {
910 return PartialContainer.CurrentTypeParameters.Types;
914 public string GetAttributeDefaultMember ()
916 return indexer_name ?? DefaultIndexerName;
919 public bool IsComImport {
921 if (OptAttributes == null)
924 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
928 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
931 PartialContainer.RegisterFieldForInitialization (field, expression);
933 if ((field.ModFlags & Modifiers.STATIC) != 0){
934 if (initialized_static_fields == null) {
935 HasStaticFieldInitializer = true;
936 initialized_static_fields = new List<FieldInitializer> (4);
939 initialized_static_fields.Add (expression);
941 if (initialized_fields == null)
942 initialized_fields = new List<FieldInitializer> (4);
944 initialized_fields.Add (expression);
948 public void ResolveFieldInitializers (BlockContext ec)
950 Debug.Assert (!IsPartialPart);
953 if (initialized_static_fields == null)
956 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
958 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
959 for (i = 0; i < initialized_static_fields.Count; ++i) {
960 FieldInitializer fi = initialized_static_fields [i];
961 ExpressionStatement s = fi.ResolveStatement (ec);
963 s = EmptyExpressionStatement.Instance;
964 } else if (!fi.IsSideEffectFree) {
965 has_complex_initializer |= true;
971 for (i = 0; i < initialized_static_fields.Count; ++i) {
972 FieldInitializer fi = initialized_static_fields [i];
974 // Need special check to not optimize code like this
975 // static int a = b = 5;
978 if (!has_complex_initializer && fi.IsDefaultInitializer)
981 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
987 if (initialized_fields == null)
990 for (int i = 0; i < initialized_fields.Count; ++i) {
991 FieldInitializer fi = initialized_fields [i];
992 ExpressionStatement s = fi.ResolveStatement (ec);
997 // Field is re-initialized to its default value => removed
999 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
1002 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1006 public override string DocComment {
1018 public PendingImplementation PendingImplementations {
1019 get { return pending; }
1022 internal override void GenerateDocComment (DocumentationBuilder builder)
1027 base.GenerateDocComment (builder);
1029 foreach (var member in members)
1030 member.GenerateDocComment (builder);
1033 public TypeSpec GetAttributeCoClass ()
1035 if (OptAttributes == null)
1038 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1042 return a.GetCoClassAttributeValue ();
1045 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1048 if (OptAttributes != null) {
1049 a = OptAttributes.Search (pa);
1055 return a.GetAttributeUsageAttribute ();
1058 public virtual CompilationSourceFile GetCompilationSourceFile ()
1060 TypeContainer ns = Parent;
1062 var sf = ns as CompilationSourceFile;
1070 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1076 /// This function computes the Base class and also the
1077 /// list of interfaces that the class or struct @c implements.
1079 /// The return value is an array (might be null) of
1080 /// interfaces implemented (as Types).
1082 /// The @base_class argument is set to the base object or null
1083 /// if this is `System.Object'.
1085 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1088 if (type_bases == null)
1091 int count = type_bases.Count;
1092 TypeSpec[] ifaces = null;
1093 var base_context = new BaseContext (this);
1094 for (int i = 0, j = 0; i < count; i++){
1095 FullNamedExpression fne = type_bases [i];
1097 var fne_resolved = fne.ResolveAsType (base_context);
1098 if (fne_resolved == null)
1101 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1102 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1103 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1104 GetSignatureForError ());
1109 base_type = fne_resolved;
1115 ifaces = new TypeSpec [count - i];
1117 if (fne_resolved.IsInterface) {
1118 for (int ii = 0; ii < j; ++ii) {
1119 if (fne_resolved == ifaces [ii]) {
1120 Report.Error (528, Location, "`{0}' is already listed in interface list",
1121 fne_resolved.GetSignatureForError ());
1126 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1127 Report.Error (61, fne.Location,
1128 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1129 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1132 Report.SymbolRelatedToPreviousError (fne_resolved);
1133 if (Kind != MemberKind.Class) {
1134 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1135 } else if (base_class != null)
1136 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1137 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1139 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1140 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1144 ifaces [j++] = fne_resolved;
1151 // Checks that some operators come in pairs:
1157 // They are matched based on the return type and the argument types
1159 void CheckPairedOperators ()
1161 bool has_equality_or_inequality = false;
1162 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1164 for (int i = 0; i < members.Count; ++i) {
1165 var o_a = members[i] as Operator;
1169 var o_type = o_a.OperatorType;
1170 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1171 has_equality_or_inequality = true;
1173 if (found_matched.Contains (o_type))
1176 var matching_type = o_a.GetMatchingOperator ();
1177 if (matching_type == Operator.OpType.TOP) {
1181 bool pair_found = false;
1182 for (int ii = i + 1; ii < members.Count; ++ii) {
1183 var o_b = members[ii] as Operator;
1184 if (o_b == null || o_b.OperatorType != matching_type)
1187 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1190 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1193 found_matched.Add (matching_type);
1199 Report.Error (216, o_a.Location,
1200 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1201 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1205 if (has_equality_or_inequality) {
1207 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1208 GetSignatureForError ());
1210 if (!HasGetHashCode)
1211 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1212 GetSignatureForError ());
1216 public override void CreateMetadataName (StringBuilder sb)
1218 if (Parent.MemberName != null) {
1219 Parent.CreateMetadataName (sb);
1221 if (sb.Length != 0) {
1226 sb.Append (MemberName.Basename);
1229 bool CreateTypeBuilder ()
1232 // Sets .size to 1 for structs with no instance fields
1234 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1236 var parent_def = Parent as TypeDefinition;
1237 if (parent_def == null) {
1238 var sb = new StringBuilder ();
1239 CreateMetadataName (sb);
1240 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1242 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1245 if (DeclaringAssembly.Importer != null)
1246 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1248 spec.SetMetaInfo (TypeBuilder);
1249 spec.MemberCache = new MemberCache (this);
1251 TypeParameters parentAllTypeParameters = null;
1252 if (parent_def != null) {
1253 spec.DeclaringType = Parent.CurrentType;
1254 parent_def.MemberCache.AddMember (spec);
1255 parentAllTypeParameters = parent_def.all_type_parameters;
1258 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1259 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1261 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1263 if (CurrentTypeParameters != null)
1264 CurrentTypeParameters.Define (all_tp_builders, spec, CurrentTypeParametersStartIndex, this);
1270 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1273 int parent_offset = 0;
1274 if (parentAllTypeParameters != null) {
1275 if (CurrentTypeParameters == null) {
1276 all_type_parameters = parentAllTypeParameters;
1277 return parentAllTypeParameters.GetAllNames ();
1280 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1281 all_type_parameters = new TypeParameters (names.Length);
1282 all_type_parameters.Add (parentAllTypeParameters);
1284 parent_offset = all_type_parameters.Count;
1285 for (int i = 0; i < parent_offset; ++i)
1286 names[i] = all_type_parameters[i].MemberName.Name;
1289 names = new string[CurrentTypeParameters.Count];
1292 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1293 if (all_type_parameters != null)
1294 all_type_parameters.Add (MemberName.TypeParameters[i]);
1296 var name = CurrentTypeParameters[i].MemberName.Name;
1297 names[parent_offset + i] = name;
1298 for (int ii = 0; ii < parent_offset + i; ++ii) {
1299 if (names[ii] != name)
1302 var tp = CurrentTypeParameters[i];
1303 var conflict = all_type_parameters[ii];
1305 tp.WarningParentNameConflict (conflict);
1309 if (all_type_parameters == null)
1310 all_type_parameters = CurrentTypeParameters;
1316 public SourceMethodBuilder CreateMethodSymbolEntry ()
1318 if (Module.DeclaringAssembly.SymbolWriter == null)
1321 var source_file = GetCompilationSourceFile ();
1322 if (source_file == null)
1325 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1329 // Creates a proxy base method call inside this container for hoisted base member calls
1331 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1333 Method proxy_method;
1336 // One proxy per base method is enough
1338 if (hoisted_base_call_proxies == null) {
1339 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1340 proxy_method = null;
1342 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1345 if (proxy_method == null) {
1346 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1348 MemberName member_name;
1349 TypeArguments targs = null;
1350 TypeSpec return_type = method.ReturnType;
1351 var local_param_types = method.Parameters.Types;
1353 if (method.IsGeneric) {
1355 // Copy all base generic method type parameters info
1357 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1358 var tparams = new TypeParameters ();
1360 targs = new TypeArguments ();
1361 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1362 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1363 var tp = hoisted_tparams[i];
1364 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1365 tparams.Add (local_tp);
1367 targs.Add (new SimpleName (tp.Name, Location));
1368 targs.Arguments[i] = local_tp.Type;
1371 member_name = new MemberName (name, tparams, Location);
1374 // Mutate any method type parameters from original
1375 // to newly created hoisted version
1377 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1378 return_type = mutator.Mutate (return_type);
1379 local_param_types = mutator.Mutate (local_param_types);
1381 member_name = new MemberName (name);
1384 var base_parameters = new Parameter[method.Parameters.Count];
1385 for (int i = 0; i < base_parameters.Length; ++i) {
1386 var base_param = method.Parameters.FixedParameters[i];
1387 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1388 base_param.Name, base_param.ModFlags, null, Location);
1389 base_parameters[i].Resolve (this, i);
1392 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1393 if (method.Parameters.HasArglist) {
1394 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1395 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1398 // Compiler generated proxy
1399 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1400 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1401 member_name, cloned_params, null);
1403 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1404 IsCompilerGenerated = true
1407 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1408 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1410 mg.SetTypeArguments (rc, targs);
1412 // Get all the method parameters and pass them as arguments
1413 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1414 Statement statement;
1415 if (method.ReturnType.Kind == MemberKind.Void)
1416 statement = new StatementExpression (real_base_call);
1418 statement = new Return (real_base_call, Location);
1420 block.AddStatement (statement);
1421 proxy_method.Block = block;
1423 members.Add (proxy_method);
1424 proxy_method.Define ();
1426 hoisted_base_call_proxies.Add (method, proxy_method);
1429 return proxy_method.Spec;
1432 protected bool DefineBaseTypes ()
1434 iface_exprs = ResolveBaseTypes (out base_type_expr);
1437 if (IsPartialPart) {
1438 set_base_type = false;
1440 if (base_type_expr != null) {
1441 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1442 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1443 Report.Error (263, Location,
1444 "Partial declarations of `{0}' must not specify different base classes",
1445 GetSignatureForError ());
1447 PartialContainer.base_type_expr = base_type_expr;
1448 PartialContainer.base_type = base_type;
1449 set_base_type = true;
1453 if (iface_exprs != null) {
1454 if (PartialContainer.iface_exprs == null)
1455 PartialContainer.iface_exprs = iface_exprs;
1457 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1458 foreach (var iface_partial in iface_exprs) {
1459 if (ifaces.Contains (iface_partial))
1462 ifaces.Add (iface_partial);
1465 PartialContainer.iface_exprs = ifaces.ToArray ();
1469 PartialContainer.members.AddRange (members);
1470 if (containers != null) {
1471 if (PartialContainer.containers == null)
1472 PartialContainer.containers = new List<TypeContainer> ();
1474 PartialContainer.containers.AddRange (containers);
1477 members_defined = members_defined_ok = true;
1478 caching_flags |= Flags.CloseTypeCreated;
1480 set_base_type = true;
1483 var cycle = CheckRecursiveDefinition (this);
1484 if (cycle != null) {
1485 Report.SymbolRelatedToPreviousError (cycle);
1486 if (this is Interface) {
1487 Report.Error (529, Location,
1488 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1489 GetSignatureForError (), cycle.GetSignatureForError ());
1492 PartialContainer.iface_exprs = null;
1494 Report.Error (146, Location,
1495 "Circular base class dependency involving `{0}' and `{1}'",
1496 GetSignatureForError (), cycle.GetSignatureForError ());
1499 PartialContainer.base_type = null;
1503 if (iface_exprs != null) {
1504 foreach (var iface_type in iface_exprs) {
1505 // Prevents a crash, the interface might not have been resolved: 442144
1506 if (iface_type == null)
1509 if (!spec.AddInterfaceDefined (iface_type))
1512 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1516 if (Kind == MemberKind.Interface) {
1517 spec.BaseType = Compiler.BuiltinTypes.Object;
1521 if (set_base_type) {
1522 if (base_type != null) {
1523 spec.BaseType = base_type;
1525 // Set base type after type creation
1526 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1528 TypeBuilder.SetParent (null);
1535 public override void ExpandBaseInterfaces ()
1538 DoExpandBaseInterfaces ();
1540 base.ExpandBaseInterfaces ();
1543 public void DoExpandBaseInterfaces ()
1545 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1548 caching_flags |= Flags.InterfacesExpanded;
1551 // Expand base interfaces. It cannot be done earlier because all partial
1552 // interface parts need to be defined before the type they are used from
1554 if (iface_exprs != null) {
1555 foreach (var iface in iface_exprs) {
1559 var td = iface.MemberDefinition as TypeDefinition;
1561 td.DoExpandBaseInterfaces ();
1563 if (iface.Interfaces == null)
1566 foreach (var biface in iface.Interfaces) {
1567 if (spec.AddInterfaceDefined (biface)) {
1568 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1575 // Include all base type interfaces too, see ImportTypeBase for details
1577 if (base_type != null) {
1578 var td = base_type.MemberDefinition as TypeDefinition;
1580 td.DoExpandBaseInterfaces ();
1583 // Simply use base interfaces only, they are all expanded which makes
1584 // it easy to handle generic type argument propagation with single
1587 // interface IA<T> : IB<T>
1588 // interface IB<U> : IC<U>
1591 if (base_type.Interfaces != null) {
1592 foreach (var iface in base_type.Interfaces) {
1593 spec.AddInterfaceDefined (iface);
1599 public override void PrepareEmit ()
1601 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1604 foreach (var member in members) {
1605 var pm = member as IParametersMember;
1608 var p = pm.Parameters;
1612 ((ParametersCompiled) p).ResolveDefaultValues (member);
1615 var c = member as Const;
1620 base.PrepareEmit ();
1624 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1626 public override bool CreateContainer ()
1628 if (TypeBuilder != null)
1634 if (IsPartialPart) {
1635 spec = PartialContainer.spec;
1636 TypeBuilder = PartialContainer.TypeBuilder;
1637 all_tp_builders = PartialContainer.all_tp_builders;
1638 all_type_parameters = PartialContainer.all_type_parameters;
1640 if (!CreateTypeBuilder ()) {
1646 return base.CreateContainer ();
1649 protected override void DoDefineContainer ()
1653 DoResolveTypeParameters ();
1657 // Replaces normal spec with predefined one when compiling corlib
1658 // and this type container defines predefined type
1660 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1662 // When compiling build-in types we start with two
1663 // version of same type. One is of BuiltinTypeSpec and
1664 // second one is ordinary TypeSpec. The unification
1665 // happens at later stage when we know which type
1666 // really matches the builtin type signature. However
1667 // that means TypeSpec create during CreateType of this
1668 // type has to be replaced with builtin one
1670 spec.SetMetaInfo (TypeBuilder);
1671 spec.MemberCache = this.spec.MemberCache;
1672 spec.DeclaringType = this.spec.DeclaringType;
1675 current_type = null;
1678 void UpdateTypeParameterConstraints (TypeDefinition part)
1680 for (int i = 0; i < CurrentTypeParameters.Count; i++) {
1681 if (CurrentTypeParameters[i].AddPartialConstraints (part, part.MemberName.TypeParameters[i]))
1684 Report.SymbolRelatedToPreviousError (Location, "");
1685 Report.Error (265, part.Location,
1686 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1687 GetSignatureForError (), CurrentTypeParameters[i].GetSignatureForError ());
1691 public override void RemoveContainer (TypeContainer cont)
1693 base.RemoveContainer (cont);
1694 Members.Remove (cont);
1695 Cache.Remove (cont.Basename);
1698 protected virtual bool DoResolveTypeParameters ()
1700 var tparams = CurrentTypeParameters;
1701 if (tparams == null)
1704 var base_context = new BaseContext (this);
1705 for (int i = 0; i < tparams.Count; ++i) {
1706 var tp = tparams[i];
1708 if (!tp.ResolveConstraints (base_context)) {
1714 if (IsPartialPart) {
1715 PartialContainer.UpdateTypeParameterConstraints (this);
1721 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1723 if (InTransit != null)
1728 if (base_type != null) {
1729 var ptc = base_type.MemberDefinition as TypeDefinition;
1730 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1734 if (iface_exprs != null) {
1735 foreach (var iface in iface_exprs) {
1736 // the interface might not have been resolved, prevents a crash, see #442144
1739 var ptc = iface.MemberDefinition as Interface;
1740 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1745 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1753 /// Populates our TypeBuilder with fields and methods
1755 public sealed override bool Define ()
1757 if (members_defined)
1758 return members_defined_ok;
1760 members_defined_ok = DoDefineMembers ();
1761 members_defined = true;
1765 return members_defined_ok;
1768 protected virtual bool DoDefineMembers ()
1770 Debug.Assert (!IsPartialPart);
1772 if (iface_exprs != null) {
1773 foreach (var iface_type in iface_exprs) {
1774 if (iface_type == null)
1777 // Ensure the base is always setup
1778 var compiled_iface = iface_type.MemberDefinition as Interface;
1779 if (compiled_iface != null)
1780 compiled_iface.Define ();
1782 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1783 if (oa != null && !IsObsolete)
1784 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1786 if (iface_type.Arity > 0) {
1787 // TODO: passing `this' is wrong, should be base type iface instead
1788 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1790 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1791 Report.Error (1966, Location,
1792 "`{0}': cannot implement a dynamic interface `{1}'",
1793 GetSignatureForError (), iface_type.GetSignatureForError ());
1798 if (iface_type.IsGenericOrParentIsGeneric) {
1799 foreach (var prev_iface in iface_exprs) {
1800 if (prev_iface == iface_type || prev_iface == null)
1803 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1806 Report.Error (695, Location,
1807 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1808 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1813 if (Kind == MemberKind.Interface) {
1814 foreach (var iface in spec.Interfaces) {
1815 MemberCache.AddInterface (iface);
1820 if (base_type != null) {
1822 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1824 if (base_type_expr != null) {
1825 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1826 if (obsolete_attr != null && !IsObsolete)
1827 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1829 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1830 Report.Error (698, base_type_expr.Location,
1831 "A generic type cannot derive from `{0}' because it is an attribute class",
1832 base_type.GetSignatureForError ());
1836 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1837 if (baseContainer != null) {
1838 baseContainer.Define ();
1841 // It can trigger define of this type (for generic types only)
1843 if (HasMembersDefined)
1848 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1849 pending = PendingImplementation.GetPendingImplementations (this);
1852 var count = members.Count;
1853 for (int i = 0; i < count; ++i) {
1854 var mc = members[i] as InterfaceMemberBase;
1855 if (mc == null || !mc.IsExplicitImpl)
1860 } catch (Exception e) {
1861 throw new InternalErrorException (mc, e);
1865 for (int i = 0; i < count; ++i) {
1866 var mc = members[i] as InterfaceMemberBase;
1867 if (mc != null && mc.IsExplicitImpl)
1870 if (members[i] is TypeContainer)
1874 members[i].Define ();
1875 } catch (Exception e) {
1876 throw new InternalErrorException (members[i], e);
1881 CheckPairedOperators ();
1884 if (requires_delayed_unmanagedtype_check) {
1885 requires_delayed_unmanagedtype_check = false;
1886 foreach (var member in members) {
1887 var f = member as Field;
1888 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1889 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1893 ComputeIndexerName();
1895 if (HasEquals && !HasGetHashCode) {
1896 Report.Warning (659, 3, Location,
1897 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1900 if (Kind == MemberKind.Interface && iface_exprs != null) {
1901 MemberCache.RemoveHiddenMembers (spec);
1907 void ComputeIndexerName ()
1909 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1910 if (indexers == null)
1913 string class_indexer_name = null;
1916 // Check normal indexers for consistent name, explicit interface implementation
1917 // indexers are ignored
1919 foreach (var indexer in indexers) {
1921 // FindMembers can return unfiltered full hierarchy names
1923 if (indexer.DeclaringType != spec)
1926 has_normal_indexers = true;
1928 if (class_indexer_name == null) {
1929 indexer_name = class_indexer_name = indexer.Name;
1933 if (indexer.Name != class_indexer_name)
1934 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1935 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1939 void EmitIndexerName ()
1941 if (!has_normal_indexers)
1944 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1948 var encoder = new AttributeEncoder ();
1949 encoder.Encode (GetAttributeDefaultMember ());
1950 encoder.EncodeEmptyNamedArguments ();
1952 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1955 public override void VerifyMembers ()
1958 // Check for internal or private fields that were never assigned
1960 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1961 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1962 foreach (var member in members) {
1963 if (member is Event) {
1965 // An event can be assigned from same class only, so we can report
1966 // this warning for all accessibility modes
1969 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1974 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1975 if (is_type_exposed)
1978 member.SetIsUsed ();
1981 var f = member as Field;
1985 if (!member.IsUsed) {
1986 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1987 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1989 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1990 member.GetSignatureForError ());
1995 if ((f.caching_flags & Flags.IsAssigned) != 0)
1999 // Only report 649 on level 4
2001 if (Compiler.Settings.WarningLevel < 4)
2005 // Don't be pedantic when type requires specific layout
2007 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2010 Constant c = New.Constantify (f.MemberType, f.Location);
2013 value = c.GetValueAsLiteral ();
2014 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2021 value = " `" + value + "'";
2023 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2024 f.GetSignatureForError (), value);
2028 base.VerifyMembers ();
2031 public override void Emit ()
2033 if (OptAttributes != null)
2034 OptAttributes.Emit ();
2036 if (!IsCompilerGenerated) {
2038 MemberSpec candidate;
2039 bool overrides = false;
2040 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2041 if (conflict_symbol == null && candidate == null) {
2042 if ((ModFlags & Modifiers.NEW) != 0)
2043 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2044 GetSignatureForError ());
2046 if ((ModFlags & Modifiers.NEW) == 0) {
2047 if (candidate == null)
2048 candidate = conflict_symbol;
2050 Report.SymbolRelatedToPreviousError (candidate);
2051 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2052 GetSignatureForError (), candidate.GetSignatureForError ());
2057 // Run constraints check on all possible generic types
2058 if (base_type != null && base_type_expr != null) {
2059 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2062 if (iface_exprs != null) {
2063 foreach (var iface_type in iface_exprs) {
2064 if (iface_type == null)
2067 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2072 if (all_tp_builders != null) {
2073 int current_starts_index = CurrentTypeParametersStartIndex;
2074 for (int i = 0; i < all_tp_builders.Length; i++) {
2075 if (i < current_starts_index) {
2076 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2078 var tp = CurrentTypeParameters [i - current_starts_index];
2079 tp.CheckGenericConstraints (!IsObsolete);
2085 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2086 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2089 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2090 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2095 for (int i = 0; i < members.Count; i++)
2099 CheckAttributeClsCompliance ();
2101 if (pending != null)
2102 pending.VerifyPendingMethods ();
2106 void CheckAttributeClsCompliance ()
2108 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2111 foreach (var m in members) {
2112 var c = m as Constructor;
2116 if (c.HasCompliantArgs)
2120 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2123 public sealed override void EmitContainer ()
2125 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2131 public override void CloseContainer ()
2133 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2136 // Close base type container first to avoid TypeLoadException
2137 if (spec.BaseType != null) {
2138 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2139 if (btype != null) {
2140 btype.CloseContainer ();
2142 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2148 caching_flags |= Flags.CloseTypeCreated;
2149 TypeBuilder.CreateType ();
2150 } catch (TypeLoadException) {
2152 // This is fine, the code still created the type
2154 } catch (Exception e) {
2155 throw new InternalErrorException (this, e);
2158 base.CloseContainer ();
2161 initialized_fields = null;
2162 initialized_static_fields = null;
2164 OptAttributes = null;
2168 // Performs the validation on a Method's modifiers (properties have
2169 // the same properties).
2171 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2173 public bool MethodModifiersValid (MemberCore mc)
2175 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2176 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2178 var flags = mc.ModFlags;
2181 // At most one of static, virtual or override
2183 if ((flags & Modifiers.STATIC) != 0){
2184 if ((flags & vao) != 0){
2185 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2186 mc.GetSignatureForError ());
2191 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2192 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2193 mc.GetSignatureForError ());
2198 // If the declaration includes the abstract modifier, then the
2199 // declaration does not include static, virtual or extern
2201 if ((flags & Modifiers.ABSTRACT) != 0){
2202 if ((flags & Modifiers.EXTERN) != 0){
2204 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2208 if ((flags & Modifiers.SEALED) != 0) {
2209 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2213 if ((flags & Modifiers.VIRTUAL) != 0){
2214 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2218 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2219 Report.SymbolRelatedToPreviousError (this);
2220 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2221 mc.GetSignatureForError (), GetSignatureForError ());
2226 if ((flags & Modifiers.PRIVATE) != 0){
2227 if ((flags & vao) != 0){
2228 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2233 if ((flags & Modifiers.SEALED) != 0){
2234 if ((flags & Modifiers.OVERRIDE) == 0){
2235 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2243 protected override bool VerifyClsCompliance ()
2245 if (!base.VerifyClsCompliance ())
2248 // Check all container names for user classes
2249 if (Kind != MemberKind.Delegate)
2250 MemberCache.VerifyClsCompliance (Definition, Report);
2252 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2253 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2254 GetSignatureForError (), BaseType.GetSignatureForError ());
2260 /// Performs checks for an explicit interface implementation. First it
2261 /// checks whether the `interface_type' is a base inteface implementation.
2262 /// Then it checks whether `name' exists in the interface type.
2264 public bool VerifyImplements (InterfaceMemberBase mb)
2266 var ifaces = spec.Interfaces;
2267 if (ifaces != null) {
2268 foreach (TypeSpec t in ifaces){
2269 if (t == mb.InterfaceType)
2274 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2275 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2276 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2281 // Used for visiblity checks to tests whether this definition shares
2282 // base type baseType, it does member-definition search
2284 public bool IsBaseTypeDefinition (TypeSpec baseType)
2286 // RootContext check
2287 if (TypeBuilder == null)
2292 if (type.MemberDefinition == baseType.MemberDefinition)
2295 type = type.BaseType;
2296 } while (type != null);
2301 public override bool IsClsComplianceRequired ()
2304 return PartialContainer.IsClsComplianceRequired ();
2306 return base.IsClsComplianceRequired ();
2309 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2311 return Module.DeclaringAssembly == assembly;
2314 public virtual bool IsUnmanagedType ()
2319 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2321 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2325 // Public function used to locate types.
2327 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2329 // Returns: Type or null if they type can not be found.
2331 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2333 FullNamedExpression e;
2334 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2340 var tp = CurrentTypeParameters;
2342 TypeParameter tparam = tp.Find (name);
2344 e = new TypeParameterExpr (tparam, Location.Null);
2349 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2351 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2352 e = new TypeExpression (t, Location.Null);
2354 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2358 // TODO MemberCache: How to cache arity stuff ?
2359 if (arity == 0 && mode == LookupMode.Normal)
2365 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2367 // Has any nested type
2368 // Does not work, because base type can have
2369 //if (PartialContainer.Types == null)
2372 var container = PartialContainer.CurrentType;
2373 return MemberCache.FindNestedType (container, name, arity);
2376 public void Mark_HasEquals ()
2378 cached_method |= CachedMethods.Equals;
2381 public void Mark_HasGetHashCode ()
2383 cached_method |= CachedMethods.GetHashCode;
2386 public override void WriteDebugSymbol (MonoSymbolFile file)
2391 foreach (var m in members) {
2392 m.WriteDebugSymbol (file);
2397 /// Method container contains Equals method
2399 public bool HasEquals {
2401 return (cached_method & CachedMethods.Equals) != 0;
2406 /// Method container contains GetHashCode method
2408 public bool HasGetHashCode {
2410 return (cached_method & CachedMethods.GetHashCode) != 0;
2414 public bool HasStaticFieldInitializer {
2416 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2420 cached_method |= CachedMethods.HasStaticFieldInitializer;
2422 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2426 public override string DocCommentHeader {
2427 get { return "T:"; }
2431 public abstract class ClassOrStruct : TypeDefinition
2433 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2435 SecurityType declarative_security;
2437 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2438 : base (parent, name, attrs, kind)
2442 protected override TypeAttributes TypeAttr {
2444 TypeAttributes ta = base.TypeAttr;
2445 if (!has_static_constructor)
2446 ta |= TypeAttributes.BeforeFieldInit;
2448 if (Kind == MemberKind.Class) {
2449 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2451 ta |= StaticClassAttribute;
2453 ta |= TypeAttributes.SequentialLayout;
2460 public override void AddNameToContainer (MemberCore symbol, string name)
2462 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2463 if (symbol is TypeParameter) {
2464 Report.Error (694, symbol.Location,
2465 "Type parameter `{0}' has same name as containing type, or method",
2466 symbol.GetSignatureForError ());
2470 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2471 if (imb == null || !imb.IsExplicitImpl) {
2472 Report.SymbolRelatedToPreviousError (this);
2473 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2474 symbol.GetSignatureForError ());
2479 base.AddNameToContainer (symbol, name);
2482 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2484 if (a.IsValidSecurityAttribute ()) {
2485 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2489 if (a.Type == pa.StructLayout) {
2490 PartialContainer.HasStructLayout = true;
2491 if (a.IsExplicitLayoutKind ())
2492 PartialContainer.HasExplicitLayout = true;
2495 if (a.Type == pa.Dynamic) {
2496 a.Error_MisusedDynamicAttribute ();
2500 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2504 /// Defines the default constructors
2506 protected Constructor DefineDefaultConstructor (bool is_static)
2508 // The default instance constructor is public
2509 // If the class is abstract, the default constructor is protected
2510 // The default static constructor is private
2514 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2516 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2519 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2520 c.Initializer = new GeneratedBaseInitializer (Location);
2522 AddConstructor (c, true);
2523 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2524 IsCompilerGenerated = true
2530 protected override bool DoDefineMembers ()
2532 CheckProtectedModifier ();
2534 base.DoDefineMembers ();
2539 public override void Emit ()
2541 if (!has_static_constructor && HasStaticFieldInitializer) {
2542 var c = DefineDefaultConstructor (true);
2548 if (declarative_security != null) {
2549 foreach (var de in declarative_security) {
2551 TypeBuilder.__AddDeclarativeSecurity (de);
2553 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2561 public sealed class Class : ClassOrStruct
2563 const Modifiers AllowedModifiers =
2566 Modifiers.PROTECTED |
2567 Modifiers.INTERNAL |
2569 Modifiers.ABSTRACT |
2574 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2575 : base (parent, name, attrs, MemberKind.Class)
2577 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2578 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2579 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2582 public override void Accept (StructuralVisitor visitor)
2584 visitor.Visit (this);
2587 public override void AddBasesForPart (List<FullNamedExpression> bases)
2589 var pmn = MemberName;
2590 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2591 Report.Error (537, Location,
2592 "The class System.Object cannot have a base class or implement an interface.");
2594 base.AddBasesForPart (bases);
2597 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2599 if (a.Type == pa.AttributeUsage) {
2600 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2601 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2605 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2606 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2610 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2611 a.Error_MissingGuidAttribute ();
2615 if (a.Type == pa.Extension) {
2616 a.Error_MisusedExtensionAttribute ();
2620 if (a.Type.IsConditionallyExcluded (this, Location))
2623 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2626 public override AttributeTargets AttributeTargets {
2628 return AttributeTargets.Class;
2632 protected override bool DoDefineMembers ()
2634 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2635 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2638 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2639 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2643 foreach (var m in Members) {
2644 if (m is Operator) {
2645 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2649 if (m is Destructor) {
2650 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2655 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2659 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2662 if (m is Constructor) {
2663 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2667 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2670 if (!PartialContainer.HasInstanceConstructor)
2671 DefineDefaultConstructor (false);
2674 return base.DoDefineMembers ();
2677 public override void Emit ()
2681 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2682 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2684 if (base_type != null && base_type.HasDynamicElement) {
2685 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2689 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2691 var ifaces = base.ResolveBaseTypes (out base_class);
2693 if (base_class == null) {
2694 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2695 base_type = Compiler.BuiltinTypes.Object;
2697 if (base_type.IsGenericParameter){
2698 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2699 GetSignatureForError (), base_type.GetSignatureForError ());
2700 } else if (base_type.IsStatic) {
2701 Report.SymbolRelatedToPreviousError (base_type);
2702 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2703 GetSignatureForError (), base_type.GetSignatureForError ());
2704 } else if (base_type.IsSealed) {
2705 Report.SymbolRelatedToPreviousError (base_type);
2706 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2707 GetSignatureForError (), base_type.GetSignatureForError ());
2708 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2709 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2710 GetSignatureForError (), base_type.GetSignatureForError ());
2713 switch (base_type.BuiltinType) {
2714 case BuiltinTypeSpec.Type.Enum:
2715 case BuiltinTypeSpec.Type.ValueType:
2716 case BuiltinTypeSpec.Type.MulticastDelegate:
2717 case BuiltinTypeSpec.Type.Delegate:
2718 case BuiltinTypeSpec.Type.Array:
2719 if (!(spec is BuiltinTypeSpec)) {
2720 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2721 GetSignatureForError (), base_type.GetSignatureForError ());
2723 base_type = Compiler.BuiltinTypes.Object;
2728 if (!IsAccessibleAs (base_type)) {
2729 Report.SymbolRelatedToPreviousError (base_type);
2730 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2731 base_type.GetSignatureForError (), GetSignatureForError ());
2735 if (PartialContainer.IsStatic && ifaces != null) {
2736 foreach (var t in ifaces)
2737 Report.SymbolRelatedToPreviousError (t);
2738 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2744 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2745 /// Valid only for attribute classes.
2746 public override string[] ConditionalConditions ()
2748 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2751 caching_flags &= ~Flags.Excluded_Undetected;
2753 if (OptAttributes == null)
2756 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2760 string[] conditions = new string[attrs.Length];
2761 for (int i = 0; i < conditions.Length; ++i)
2762 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2764 caching_flags |= Flags.Excluded;
2769 public sealed class Struct : ClassOrStruct
2771 bool is_unmanaged, has_unmanaged_check_done;
2775 // Modifiers allowed in a struct declaration
2777 const Modifiers AllowedModifiers =
2780 Modifiers.PROTECTED |
2781 Modifiers.INTERNAL |
2785 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2786 : base (parent, name, attrs, MemberKind.Struct)
2788 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2789 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2790 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2793 public override AttributeTargets AttributeTargets {
2795 return AttributeTargets.Struct;
2799 public override void Accept (StructuralVisitor visitor)
2801 visitor.Visit (this);
2804 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2806 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2809 // When struct constains fixed fixed and struct layout has explicitly
2810 // set CharSet, its value has to be propagated to compiler generated
2813 if (a.Type == pa.StructLayout) {
2814 var value = a.GetNamedValue ("CharSet");
2818 for (int i = 0; i < Members.Count; ++i) {
2819 FixedField ff = Members [i] as FixedField;
2823 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2828 bool CheckStructCycles ()
2834 foreach (var member in Members) {
2835 var field = member as Field;
2839 TypeSpec ftype = field.Spec.MemberType;
2840 if (!ftype.IsStruct)
2843 if (ftype is BuiltinTypeSpec)
2846 foreach (var targ in ftype.TypeArguments) {
2847 if (!CheckFieldTypeCycle (targ)) {
2848 Report.Error (523, field.Location,
2849 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2850 field.GetSignatureForError (), ftype.GetSignatureForError ());
2856 // Static fields of exactly same type are allowed
2858 if (field.IsStatic && ftype == CurrentType)
2861 if (!CheckFieldTypeCycle (ftype)) {
2862 Report.Error (523, field.Location,
2863 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2864 field.GetSignatureForError (), ftype.GetSignatureForError ());
2873 static bool CheckFieldTypeCycle (TypeSpec ts)
2875 var fts = ts.MemberDefinition as Struct;
2879 return fts.CheckStructCycles ();
2882 public override void Emit ()
2884 CheckStructCycles ();
2889 public override bool IsUnmanagedType ()
2891 if (has_unmanaged_check_done)
2892 return is_unmanaged;
2894 if (requires_delayed_unmanagedtype_check)
2897 var parent_def = Parent.PartialContainer;
2898 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2899 has_unmanaged_check_done = true;
2903 if (first_nonstatic_field != null) {
2904 requires_delayed_unmanagedtype_check = true;
2906 foreach (var member in Members) {
2907 var f = member as Field;
2914 // It can happen when recursive unmanaged types are defined
2915 // struct S { S* s; }
2916 TypeSpec mt = f.MemberType;
2924 has_unmanaged_check_done = true;
2928 has_unmanaged_check_done = true;
2931 is_unmanaged = true;
2935 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2937 var ifaces = base.ResolveBaseTypes (out base_class);
2938 base_type = Compiler.BuiltinTypes.ValueType;
2942 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2944 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2945 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2946 field.GetSignatureForError ());
2949 base.RegisterFieldForInitialization (field, expression);
2957 public sealed class Interface : TypeDefinition {
2960 /// Modifiers allowed in a class declaration
2962 const Modifiers AllowedModifiers =
2965 Modifiers.PROTECTED |
2966 Modifiers.INTERNAL |
2970 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2971 : base (parent, name, attrs, MemberKind.Interface)
2973 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2975 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2976 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2981 public override AttributeTargets AttributeTargets {
2983 return AttributeTargets.Interface;
2987 protected override TypeAttributes TypeAttr {
2989 const TypeAttributes DefaultTypeAttributes =
2990 TypeAttributes.AutoLayout |
2991 TypeAttributes.Abstract |
2992 TypeAttributes.Interface;
2994 return base.TypeAttr | DefaultTypeAttributes;
3000 public override void Accept (StructuralVisitor visitor)
3002 visitor.Visit (this);
3005 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3007 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3008 a.Error_MissingGuidAttribute ();
3012 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3015 protected override bool VerifyClsCompliance ()
3017 if (!base.VerifyClsCompliance ())
3020 if (iface_exprs != null) {
3021 foreach (var iface in iface_exprs) {
3022 if (iface.IsCLSCompliant ())
3025 Report.SymbolRelatedToPreviousError (iface);
3026 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3027 GetSignatureForError (), TypeManager.CSharpName (iface));
3035 public abstract class InterfaceMemberBase : MemberBase
3038 // Common modifiers allowed in a class declaration
3040 protected const Modifiers AllowedModifiersClass =
3043 Modifiers.PROTECTED |
3044 Modifiers.INTERNAL |
3049 Modifiers.OVERRIDE |
3050 Modifiers.ABSTRACT |
3055 // Common modifiers allowed in a struct declaration
3057 protected const Modifiers AllowedModifiersStruct =
3060 Modifiers.PROTECTED |
3061 Modifiers.INTERNAL |
3064 Modifiers.OVERRIDE |
3069 // Common modifiers allowed in a interface declaration
3071 protected const Modifiers AllowedModifiersInterface =
3076 // Whether this is an interface member.
3078 public bool IsInterface;
3081 // If true, this is an explicit interface implementation
3083 public readonly bool IsExplicitImpl;
3085 protected bool is_external_implementation;
3088 // The interface type we are explicitly implementing
3090 public TypeSpec InterfaceType;
3093 // The method we're overriding if this is an override method.
3095 protected MethodSpec base_method;
3097 readonly Modifiers explicit_mod_flags;
3098 public MethodAttributes flags;
3100 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3101 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3103 IsInterface = parent.Kind == MemberKind.Interface;
3104 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3105 explicit_mod_flags = mod;
3108 public abstract Variance ExpectedMemberTypeVariance { get; }
3110 protected override bool CheckBase ()
3112 if (!base.CheckBase ())
3115 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3116 CheckForDuplications ();
3121 // For System.Object only
3122 if (Parent.BaseType == null)
3125 MemberSpec candidate;
3126 bool overrides = false;
3127 var base_member = FindBaseMember (out candidate, ref overrides);
3129 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3130 if (base_member == null) {
3131 if (candidate == null) {
3132 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3133 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3134 "object.Finalize()");
3136 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3137 GetSignatureForError (), SimpleName.GetMemberType (this));
3140 Report.SymbolRelatedToPreviousError (candidate);
3142 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3143 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3144 else if (this is PropertyBase)
3145 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3146 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3148 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3149 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3156 // Handles ambiguous overrides
3158 if (candidate != null) {
3159 Report.SymbolRelatedToPreviousError (candidate);
3160 Report.SymbolRelatedToPreviousError (base_member);
3162 // Get member definition for error reporting
3163 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3164 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3166 Report.Error (462, Location,
3167 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3168 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3171 if (!CheckOverrideAgainstBase (base_member))
3174 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3176 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3177 Report.SymbolRelatedToPreviousError (base_member);
3178 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3179 GetSignatureForError (), base_member.GetSignatureForError ());
3182 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3183 Report.SymbolRelatedToPreviousError (base_member);
3184 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3185 GetSignatureForError (), base_member.GetSignatureForError ());
3189 base_method = base_member as MethodSpec;
3193 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3194 base_member = candidate;
3196 if (base_member == null) {
3197 if ((ModFlags & Modifiers.NEW) != 0) {
3198 if (base_member == null) {
3199 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3200 GetSignatureForError ());
3204 if ((ModFlags & Modifiers.NEW) == 0) {
3205 ModFlags |= Modifiers.NEW;
3206 if (!IsCompilerGenerated) {
3207 Report.SymbolRelatedToPreviousError (base_member);
3208 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3209 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",
3210 GetSignatureForError (), base_member.GetSignatureForError ());
3212 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3213 GetSignatureForError (), base_member.GetSignatureForError ());
3218 if (!IsInterface && base_member.IsAbstract && !overrides) {
3219 Report.SymbolRelatedToPreviousError (base_member);
3220 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3221 GetSignatureForError (), base_member.GetSignatureForError ());
3228 protected virtual bool CheckForDuplications ()
3230 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3234 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3235 // that have been defined.
3237 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3241 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3242 Report.SymbolRelatedToPreviousError (base_member);
3243 Report.Error (506, Location,
3244 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3245 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3249 // Now we check that the overriden method is not final
3250 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3251 Report.SymbolRelatedToPreviousError (base_member);
3252 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3253 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3257 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3258 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3259 Report.SymbolRelatedToPreviousError (base_member);
3260 if (this is PropertyBasedMember) {
3261 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3262 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3264 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3265 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3273 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3275 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3276 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3278 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3280 // It must be at least "protected"
3282 if ((thisp & Modifiers.PROTECTED) == 0) {
3287 // when overriding protected internal, the method can be declared
3288 // protected internal only within the same assembly or assembly
3289 // which has InternalsVisibleTo
3291 if ((thisp & Modifiers.INTERNAL) != 0) {
3292 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3296 // protected overriding protected internal inside same assembly
3297 // requires internal modifier as well
3299 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3306 return thisp == base_classp;
3309 public override bool Define ()
3312 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3313 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3315 flags = MethodAttributes.Public |
3316 MethodAttributes.Abstract |
3317 MethodAttributes.HideBySig |
3318 MethodAttributes.NewSlot |
3319 MethodAttributes.Virtual;
3321 Parent.PartialContainer.MethodModifiersValid (this);
3323 flags = ModifiersExtensions.MethodAttr (ModFlags);
3326 if (IsExplicitImpl) {
3327 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3328 if (InterfaceType == null)
3331 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3332 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3333 GetSignatureForError ());
3336 if (!InterfaceType.IsInterface) {
3337 Report.SymbolRelatedToPreviousError (InterfaceType);
3338 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3339 TypeManager.CSharpName (InterfaceType));
3341 Parent.PartialContainer.VerifyImplements (this);
3344 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3347 return base.Define ();
3350 protected bool DefineParameters (ParametersCompiled parameters)
3352 if (!parameters.Resolve (this))
3356 for (int i = 0; i < parameters.Count; ++i) {
3357 Parameter p = parameters [i];
3359 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3360 p.Warning_UselessOptionalParameter (Report);
3362 if (p.CheckAccessibility (this))
3365 TypeSpec t = parameters.Types [i];
3366 Report.SymbolRelatedToPreviousError (t);
3367 if (this is Indexer)
3368 Report.Error (55, Location,
3369 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3370 TypeManager.CSharpName (t), GetSignatureForError ());
3371 else if (this is Operator)
3372 Report.Error (57, Location,
3373 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3374 TypeManager.CSharpName (t), GetSignatureForError ());
3376 Report.Error (51, Location,
3377 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3378 TypeManager.CSharpName (t), GetSignatureForError ());
3384 protected override void DoMemberTypeDependentChecks ()
3386 base.DoMemberTypeDependentChecks ();
3388 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3391 public override void Emit()
3393 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3394 // We are more strict than csc and report this as an error because SRE does not allow emit that
3395 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3396 if (this is Constructor) {
3397 Report.Warning (824, 1, Location,
3398 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3400 Report.Warning (626, 1, Location,
3401 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3402 GetSignatureForError ());
3409 public override bool EnableOverloadChecks (MemberCore overload)
3412 // Two members can differ in their explicit interface
3413 // type parameter only
3415 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3416 if (imb != null && imb.IsExplicitImpl) {
3417 if (IsExplicitImpl) {
3418 caching_flags |= Flags.MethodOverloadsExist;
3423 return IsExplicitImpl;
3426 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3428 var base_modifiers = base_member.Modifiers;
3430 // Remove internal modifier from types which are not internally accessible
3431 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3432 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3433 base_modifiers = Modifiers.PROTECTED;
3435 Report.SymbolRelatedToPreviousError (base_member);
3436 Report.Error (507, member.Location,
3437 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3438 member.GetSignatureForError (),
3439 ModifiersExtensions.AccessibilityName (base_modifiers),
3440 base_member.GetSignatureForError ());
3443 protected void Error_StaticReturnType ()
3445 Report.Error (722, Location,
3446 "`{0}': static types cannot be used as return types",
3447 MemberType.GetSignatureForError ());
3451 /// Gets base method and its return type
3453 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3455 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3459 // The "short" name of this property / indexer / event. This is the
3460 // name without the explicit interface.
3462 public string ShortName {
3463 get { return MemberName.Name; }
3467 // Returns full metadata method name
3469 public string GetFullName (MemberName name)
3471 return GetFullName (name.Name);
3474 public string GetFullName (string name)
3476 if (!IsExplicitImpl)
3480 // When dealing with explicit members a full interface type
3481 // name is added to member name to avoid possible name conflicts
3483 // We use CSharpName which gets us full name with benefit of
3484 // replacing predefined names which saves some space and name
3487 return TypeManager.CSharpName (InterfaceType) + "." + name;
3490 public override string GetSignatureForDocumentation ()
3493 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3495 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3498 public override bool IsUsed
3500 get { return IsExplicitImpl || base.IsUsed; }
3503 public override void SetConstraints (List<Constraints> constraints_list)
3505 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3506 Report.Error (460, Location,
3507 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3508 GetSignatureForError ());
3511 base.SetConstraints (constraints_list);
3515 public abstract class MemberBase : MemberCore
3517 protected FullNamedExpression type_expr;
3518 protected TypeSpec member_type;
3519 public new TypeDefinition Parent;
3521 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3522 : base (parent, name, attrs)
3524 this.Parent = parent;
3525 this.type_expr = type;
3526 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3531 public TypeSpec MemberType {
3537 public FullNamedExpression TypeExpression {
3546 // Main member define entry
3548 public override bool Define ()
3550 DoMemberTypeIndependentChecks ();
3553 // Returns false only when type resolution failed
3555 if (!ResolveMemberType ())
3558 DoMemberTypeDependentChecks ();
3563 // Any type_name independent checks
3565 protected virtual void DoMemberTypeIndependentChecks ()
3567 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3568 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3569 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3570 GetSignatureForError (), Parent.GetSignatureForError ());
3575 // Any type_name dependent checks
3577 protected virtual void DoMemberTypeDependentChecks ()
3579 // verify accessibility
3580 if (!IsAccessibleAs (MemberType)) {
3581 Report.SymbolRelatedToPreviousError (MemberType);
3582 if (this is Property)
3583 Report.Error (53, Location,
3584 "Inconsistent accessibility: property type `" +
3585 TypeManager.CSharpName (MemberType) + "' is less " +
3586 "accessible than property `" + GetSignatureForError () + "'");
3587 else if (this is Indexer)
3588 Report.Error (54, Location,
3589 "Inconsistent accessibility: indexer return type `" +
3590 TypeManager.CSharpName (MemberType) + "' is less " +
3591 "accessible than indexer `" + GetSignatureForError () + "'");
3592 else if (this is MethodCore) {
3593 if (this is Operator)
3594 Report.Error (56, Location,
3595 "Inconsistent accessibility: return type `" +
3596 TypeManager.CSharpName (MemberType) + "' is less " +
3597 "accessible than operator `" + GetSignatureForError () + "'");
3599 Report.Error (50, Location,
3600 "Inconsistent accessibility: return type `" +
3601 TypeManager.CSharpName (MemberType) + "' is less " +
3602 "accessible than method `" + GetSignatureForError () + "'");
3604 Report.Error (52, Location,
3605 "Inconsistent accessibility: field type `" +
3606 TypeManager.CSharpName (MemberType) + "' is less " +
3607 "accessible than field `" + GetSignatureForError () + "'");
3612 protected void IsTypePermitted ()
3614 if (MemberType.IsSpecialRuntimeType) {
3615 if (Parent is StateMachine) {
3616 Report.Error (4012, Location,
3617 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3618 MemberType.GetSignatureForError ());
3619 } else if (Parent is HoistedStoreyClass) {
3620 Report.Error (4013, Location,
3621 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3622 MemberType.GetSignatureForError ());
3624 Report.Error (610, Location,
3625 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3630 protected virtual bool CheckBase ()
3632 CheckProtectedModifier ();
3637 public override string GetSignatureForDocumentation ()
3639 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3642 protected virtual bool ResolveMemberType ()
3644 if (member_type != null)
3645 throw new InternalErrorException ("Multi-resolve");
3647 member_type = type_expr.ResolveAsType (this);
3648 return member_type != null;