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 TypeDefinition PartialContainer {
75 return main_container;
78 main_container = value;
82 public IList<TypeContainer> Containers {
90 // Any unattached attributes during parsing get added here.
92 public Attributes UnattachedAttributes {
97 public virtual void AddCompilerGeneratedClass (CompilerGeneratedClass c)
102 public virtual void AddPartial (TypeDefinition next_part)
105 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
107 AddPartial (next_part, mc as TypeDefinition);
110 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
112 next_part.ModFlags |= Modifiers.PARTIAL;
114 if (existing == null) {
115 AddTypeContainer (next_part);
119 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
120 if (existing.Kind != next_part.Kind) {
121 AddTypeContainer (next_part);
123 Report.SymbolRelatedToPreviousError (next_part);
124 Error_MissingPartialModifier (existing);
130 if (existing.Kind != next_part.Kind) {
131 Report.SymbolRelatedToPreviousError (existing);
132 Report.Error (261, next_part.Location,
133 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
134 next_part.GetSignatureForError ());
137 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
138 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0 &&
139 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) == 0)) {
140 Report.SymbolRelatedToPreviousError (existing);
141 Report.Error (262, next_part.Location,
142 "Partial declarations of `{0}' have conflicting accessibility modifiers",
143 next_part.GetSignatureForError ());
146 var tc_names = existing.CurrentTypeParameters;
147 if (tc_names != null) {
148 for (int i = 0; i < tc_names.Count; ++i) {
149 var tp = next_part.MemberName.TypeParameters[i];
150 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
151 Report.SymbolRelatedToPreviousError (existing.Location, "");
152 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
153 next_part.GetSignatureForError ());
157 if (tc_names[i].Variance != tp.Variance) {
158 Report.SymbolRelatedToPreviousError (existing.Location, "");
159 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
160 next_part.GetSignatureForError ());
166 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
167 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
168 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFER) != 0) {
169 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFER | Modifiers.AccessibilityMask);
170 existing.ModFlags |= next_part.ModFlags;
172 existing.ModFlags |= next_part.ModFlags;
175 existing.Definition.Modifiers = existing.ModFlags;
177 if (next_part.attributes != null) {
178 if (existing.attributes == null)
179 existing.attributes = next_part.attributes;
181 existing.attributes.AddAttributes (next_part.attributes.Attrs);
184 next_part.PartialContainer = existing;
186 if (containers == null)
187 containers = new List<TypeContainer> ();
189 containers.Add (next_part);
192 public virtual void AddTypeContainer (TypeContainer tc)
196 var tparams = tc.MemberName.TypeParameters;
197 if (tparams != null && tc.PartialContainer != null) {
198 var td = (TypeDefinition) tc;
199 for (int i = 0; i < tparams.Count; ++i) {
201 if (tp.MemberName == null)
204 td.AddNameToContainer (tp, tp.Name);
209 public virtual void CloseContainer ()
211 if (containers != null) {
212 foreach (TypeContainer tc in containers) {
213 tc.CloseContainer ();
218 public virtual void CreateMetadataName (StringBuilder sb)
220 if (Parent != null && Parent.MemberName != null)
221 Parent.CreateMetadataName (sb);
223 MemberName.CreateMetadataName (sb);
226 public virtual bool CreateContainer ()
228 if (containers != null) {
229 foreach (TypeContainer tc in containers) {
230 tc.CreateContainer ();
237 public override bool Define ()
239 if (containers != null) {
240 foreach (TypeContainer tc in containers) {
245 // Release cache used by parser only
246 if (Module.Evaluator == null) {
247 defined_names = null;
249 defined_names.Clear ();
255 public virtual void PrepareEmit ()
257 if (containers != null) {
258 foreach (var t in containers) {
264 public virtual bool DefineContainer ()
271 DoDefineContainer ();
273 if (containers != null) {
274 foreach (TypeContainer tc in containers) {
276 tc.DefineContainer ();
277 } catch (Exception e) {
278 if (MemberName == MemberName.Null)
281 throw new InternalErrorException (tc, e);
289 protected virtual void DefineNamespace ()
291 if (containers != null) {
292 foreach (var tc in containers) {
294 tc.DefineNamespace ();
295 } catch (Exception e) {
296 throw new InternalErrorException (tc, e);
302 protected virtual void DoDefineContainer ()
306 public virtual void EmitContainer ()
308 if (containers != null) {
309 for (int i = 0; i < containers.Count; ++i)
310 containers[i].EmitContainer ();
314 protected void Error_MissingPartialModifier (MemberCore type)
316 Report.Error (260, type.Location,
317 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
318 type.GetSignatureForError ());
321 public override string GetSignatureForDocumentation ()
323 if (Parent != null && Parent.MemberName != null)
324 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
326 return MemberName.GetSignatureForDocumentation ();
329 public override string GetSignatureForError ()
331 if (Parent != null && Parent.MemberName != null)
332 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
334 return MemberName.GetSignatureForError ();
337 public virtual void RemoveContainer (TypeContainer cont)
339 if (containers != null)
340 containers.Remove (cont);
342 defined_names.Remove (cont.Basename);
345 public virtual void VerifyMembers ()
347 if (containers != null) {
348 foreach (TypeContainer tc in containers)
353 public override void WriteDebugSymbol (MonoSymbolFile file)
355 if (containers != null) {
356 foreach (TypeContainer tc in containers) {
357 tc.WriteDebugSymbol (file);
363 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
366 // Different context is needed when resolving type container base
367 // types. Type names come from the parent scope but type parameter
368 // names from the container scope.
370 public struct BaseContext : IMemberContext
374 public BaseContext (TypeContainer tc)
379 #region IMemberContext Members
381 public CompilerContext Compiler {
382 get { return tc.Compiler; }
385 public TypeSpec CurrentType {
386 get { return tc.Parent.CurrentType; }
389 public TypeParameters CurrentTypeParameters {
390 get { return tc.PartialContainer.CurrentTypeParameters; }
393 public MemberCore CurrentMemberDefinition {
397 public bool IsObsolete {
398 get { return tc.IsObsolete; }
401 public bool IsUnsafe {
402 get { return tc.IsUnsafe; }
405 public bool IsStatic {
406 get { return tc.IsStatic; }
409 public ModuleContainer Module {
410 get { return tc.Module; }
413 public string GetSignatureForError ()
415 return tc.GetSignatureForError ();
418 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
423 public FullNamedExpression LookupNamespaceAlias (string name)
425 return tc.Parent.LookupNamespaceAlias (name);
428 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
431 var tp = CurrentTypeParameters;
433 TypeParameter t = tp.Find (name);
435 return new TypeParameterExpr (t, loc);
439 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
449 GetHashCode = 1 << 1,
450 HasStaticFieldInitializer = 1 << 2
453 readonly List<MemberCore> members;
455 // Holds a list of fields that have initializers
456 protected List<FieldInitializer> initialized_fields;
458 // Holds a list of static fields that have initializers
459 protected List<FieldInitializer> initialized_static_fields;
461 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
463 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
466 // Points to the first non-static field added to the container.
468 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
469 // and the first one's as good as any.
471 protected FieldBase first_nonstatic_field;
474 // This one is computed after we can distinguish interfaces
475 // from classes from the arraylist `type_bases'
477 protected TypeSpec base_type;
478 FullNamedExpression base_type_expr; // TODO: It's temporary variable
479 protected TypeSpec[] iface_exprs;
481 protected List<FullNamedExpression> type_bases;
483 TypeDefinition InTransit;
485 public TypeBuilder TypeBuilder;
486 GenericTypeParameterBuilder[] all_tp_builders;
488 // All recursive type parameters put together sharing same
489 // TypeParameter instances
491 TypeParameters all_type_parameters;
493 public const string DefaultIndexerName = "Item";
495 bool has_normal_indexers;
497 protected bool requires_delayed_unmanagedtype_check;
499 bool members_defined;
500 bool members_defined_ok;
501 protected bool has_static_constructor;
503 private CachedMethods cached_method;
505 protected TypeSpec spec;
506 TypeSpec current_type;
508 public int DynamicSitesCounter;
509 public int AnonymousMethodsCounter;
511 static readonly string[] attribute_targets = new string[] { "type" };
514 /// The pending methods that need to be implemented
515 // (interfaces or abstract methods)
517 PendingImplementation pending;
519 public TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
520 : base (parent, name, attrs, kind)
522 PartialContainer = this;
523 members = new List<MemberCore> ();
528 public List<FullNamedExpression> BaseTypeExpressions {
534 public override TypeSpec CurrentType {
536 if (current_type == null) {
537 if (IsGenericOrParentIsGeneric) {
539 // Switch to inflated version as it's used by all expressions
541 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
542 current_type = spec.MakeGenericType (this, targs);
552 public override TypeParameters CurrentTypeParameters {
554 return PartialContainer.MemberName.TypeParameters;
558 int CurrentTypeParametersStartIndex {
560 int total = all_tp_builders.Length;
561 if (CurrentTypeParameters != null) {
562 return total - CurrentTypeParameters.Count;
568 public virtual AssemblyDefinition DeclaringAssembly {
570 return Module.DeclaringAssembly;
574 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
576 return Module.DeclaringAssembly;
580 public TypeSpec Definition {
586 public bool HasMembersDefined {
588 return members_defined;
592 public bool HasInstanceConstructor {
594 return (caching_flags & Flags.HasInstanceConstructor) != 0;
597 caching_flags |= Flags.HasInstanceConstructor;
601 // Indicated whether container has StructLayout attribute set Explicit
602 public bool HasExplicitLayout {
603 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
604 set { caching_flags |= Flags.HasExplicitLayout; }
607 public bool HasOperators {
609 return (caching_flags & Flags.HasUserOperators) != 0;
612 caching_flags |= Flags.HasUserOperators;
616 public bool HasStructLayout {
617 get { return (caching_flags & Flags.HasStructLayout) != 0; }
618 set { caching_flags |= Flags.HasStructLayout; }
621 public TypeSpec[] Interfaces {
627 public bool IsGenericOrParentIsGeneric {
629 return all_type_parameters != null;
633 public bool IsTopLevel {
635 return !(Parent is TypeDefinition);
639 public bool IsPartial {
641 return (ModFlags & Modifiers.PARTIAL) != 0;
646 // Returns true for secondary partial containers
650 return PartialContainer != this;
654 public MemberCache MemberCache {
656 return spec.MemberCache;
660 public List<MemberCore> Members {
666 string ITypeDefinition.Namespace {
669 while (p.Kind != MemberKind.Namespace)
672 return p.MemberName == null ? null : p.GetSignatureForError ();
676 public TypeParameters TypeParametersAll {
678 return all_type_parameters;
682 public override string[] ValidAttributeTargets {
684 return attribute_targets;
690 public override void Accept (StructuralVisitor visitor)
692 visitor.Visit (this);
695 public void AddMember (MemberCore symbol)
697 if (symbol.MemberName.ExplicitInterface != null) {
698 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
699 Report.Error (541, symbol.Location,
700 "`{0}': explicit interface declaration can only be declared in a class or struct",
701 symbol.GetSignatureForError ());
705 AddNameToContainer (symbol, symbol.MemberName.Basename);
706 members.Add (symbol);
709 public override void AddTypeContainer (TypeContainer tc)
711 AddNameToContainer (tc, tc.Basename);
713 if (containers == null)
714 containers = new List<TypeContainer> ();
717 base.AddTypeContainer (tc);
720 public override void AddCompilerGeneratedClass (CompilerGeneratedClass c)
724 if (containers == null)
725 containers = new List<TypeContainer> ();
727 base.AddCompilerGeneratedClass (c);
731 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
733 public virtual void AddNameToContainer (MemberCore symbol, string name)
735 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
739 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
740 PartialContainer.defined_names.Add (name, symbol);
744 if (symbol.EnableOverloadChecks (mc))
747 InterfaceMemberBase im = mc as InterfaceMemberBase;
748 if (im != null && im.IsExplicitImpl)
751 Report.SymbolRelatedToPreviousError (mc);
752 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
753 Error_MissingPartialModifier (symbol);
757 if (symbol is TypeParameter) {
758 Report.Error (692, symbol.Location,
759 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
761 Report.Error (102, symbol.Location,
762 "The type `{0}' already contains a definition for `{1}'",
763 GetSignatureForError (), name);
769 public void AddConstructor (Constructor c)
771 AddConstructor (c, false);
774 public void AddConstructor (Constructor c, bool isDefault)
776 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
778 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
780 if (is_static && c.ParameterInfo.IsEmpty) {
781 PartialContainer.has_static_constructor = true;
783 PartialContainer.HasInstanceConstructor = true;
789 public bool AddField (FieldBase field)
793 if ((field.ModFlags & Modifiers.STATIC) != 0)
796 var first_field = PartialContainer.first_nonstatic_field;
797 if (first_field == null) {
798 PartialContainer.first_nonstatic_field = field;
802 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
803 Report.SymbolRelatedToPreviousError (first_field.Parent);
804 Report.Warning (282, 3, field.Location,
805 "struct instance field `{0}' found in different declaration from instance field `{1}'",
806 field.GetSignatureForError (), first_field.GetSignatureForError ());
812 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
814 public void AddIndexer (Indexer i)
819 public void AddOperator (Operator op)
821 PartialContainer.HasOperators = true;
825 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
827 if (has_normal_indexers && a.Type == pa.DefaultMember) {
828 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
832 if (a.Type == pa.Required) {
833 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
837 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
840 public override AttributeTargets AttributeTargets {
842 throw new NotSupportedException ();
846 public TypeSpec BaseType {
848 return spec.BaseType;
852 protected virtual TypeAttributes TypeAttr {
854 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
858 public int TypeParametersCount {
860 return MemberName.Arity;
864 TypeParameterSpec[] ITypeDefinition.TypeParameters {
866 return PartialContainer.CurrentTypeParameters.Types;
870 public string GetAttributeDefaultMember ()
872 return indexer_name ?? DefaultIndexerName;
875 public bool IsComImport {
877 if (OptAttributes == null)
880 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
884 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
887 PartialContainer.RegisterFieldForInitialization (field, expression);
889 if ((field.ModFlags & Modifiers.STATIC) != 0){
890 if (initialized_static_fields == null) {
891 HasStaticFieldInitializer = true;
892 initialized_static_fields = new List<FieldInitializer> (4);
895 initialized_static_fields.Add (expression);
897 if (initialized_fields == null)
898 initialized_fields = new List<FieldInitializer> (4);
900 initialized_fields.Add (expression);
904 public void ResolveFieldInitializers (BlockContext ec)
906 Debug.Assert (!IsPartialPart);
909 if (initialized_static_fields == null)
912 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
914 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
915 for (i = 0; i < initialized_static_fields.Count; ++i) {
916 FieldInitializer fi = initialized_static_fields [i];
917 ExpressionStatement s = fi.ResolveStatement (ec);
919 s = EmptyExpressionStatement.Instance;
920 } else if (!fi.IsSideEffectFree) {
921 has_complex_initializer |= true;
927 for (i = 0; i < initialized_static_fields.Count; ++i) {
928 FieldInitializer fi = initialized_static_fields [i];
930 // Need special check to not optimize code like this
931 // static int a = b = 5;
934 if (!has_complex_initializer && fi.IsDefaultInitializer)
937 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
943 if (initialized_fields == null)
946 for (int i = 0; i < initialized_fields.Count; ++i) {
947 FieldInitializer fi = initialized_fields [i];
948 ExpressionStatement s = fi.ResolveStatement (ec);
953 // Field is re-initialized to its default value => removed
955 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
958 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
962 public override string DocComment {
974 public PendingImplementation PendingImplementations {
975 get { return pending; }
978 internal override void GenerateDocComment (DocumentationBuilder builder)
980 base.GenerateDocComment (builder);
982 foreach (var member in members)
983 member.GenerateDocComment (builder);
986 public TypeSpec GetAttributeCoClass ()
988 if (OptAttributes == null)
991 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
995 return a.GetCoClassAttributeValue ();
998 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1001 if (OptAttributes != null) {
1002 a = OptAttributes.Search (pa);
1008 return a.GetAttributeUsageAttribute ();
1011 public virtual CompilationSourceFile GetCompilationSourceFile ()
1013 TypeContainer ns = Parent;
1015 var sf = ns as CompilationSourceFile;
1023 public virtual void AddBasesForPart (List<FullNamedExpression> bases)
1029 /// This function computes the Base class and also the
1030 /// list of interfaces that the class or struct @c implements.
1032 /// The return value is an array (might be null) of
1033 /// interfaces implemented (as Types).
1035 /// The @base_class argument is set to the base object or null
1036 /// if this is `System.Object'.
1038 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1041 if (type_bases == null)
1044 int count = type_bases.Count;
1045 TypeSpec[] ifaces = null;
1046 var base_context = new BaseContext (this);
1047 for (int i = 0, j = 0; i < count; i++){
1048 FullNamedExpression fne = type_bases [i];
1050 var fne_resolved = fne.ResolveAsType (base_context);
1051 if (fne_resolved == null)
1054 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1055 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1056 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1057 GetSignatureForError ());
1062 base_type = fne_resolved;
1068 ifaces = new TypeSpec [count - i];
1070 if (fne_resolved.IsInterface) {
1071 for (int ii = 0; ii < j; ++ii) {
1072 if (fne_resolved == ifaces [ii]) {
1073 Report.Error (528, Location, "`{0}' is already listed in interface list",
1074 fne_resolved.GetSignatureForError ());
1079 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1080 Report.Error (61, fne.Location,
1081 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1082 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1085 Report.SymbolRelatedToPreviousError (fne_resolved);
1086 if (Kind != MemberKind.Class) {
1087 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1088 } else if (base_class != null)
1089 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1090 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1092 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1093 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1097 ifaces [j++] = fne_resolved;
1104 // Checks that some operators come in pairs:
1110 // They are matched based on the return type and the argument types
1112 void CheckPairedOperators ()
1114 bool has_equality_or_inequality = false;
1115 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1117 for (int i = 0; i < members.Count; ++i) {
1118 var o_a = members[i] as Operator;
1122 var o_type = o_a.OperatorType;
1123 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1124 has_equality_or_inequality = true;
1126 if (found_matched.Contains (o_type))
1129 var matching_type = o_a.GetMatchingOperator ();
1130 if (matching_type == Operator.OpType.TOP) {
1134 bool pair_found = false;
1135 for (int ii = i + 1; ii < members.Count; ++ii) {
1136 var o_b = members[ii] as Operator;
1137 if (o_b == null || o_b.OperatorType != matching_type)
1140 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1143 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1146 found_matched.Add (matching_type);
1152 Report.Error (216, o_a.Location,
1153 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1154 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1158 if (has_equality_or_inequality) {
1160 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1161 GetSignatureForError ());
1163 if (!HasGetHashCode)
1164 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1165 GetSignatureForError ());
1169 public override void CreateMetadataName (StringBuilder sb)
1171 if (Parent.MemberName != null) {
1172 Parent.CreateMetadataName (sb);
1174 if (sb.Length != 0) {
1179 sb.Append (MemberName.Basename);
1182 bool CreateTypeBuilder ()
1185 // Sets .size to 1 for structs with no instance fields
1187 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null ? 1 : 0;
1189 var parent_def = Parent as TypeDefinition;
1190 if (parent_def == null) {
1191 var sb = new StringBuilder ();
1192 CreateMetadataName (sb);
1193 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1195 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1198 if (DeclaringAssembly.Importer != null)
1199 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1201 spec.SetMetaInfo (TypeBuilder);
1202 spec.MemberCache = new MemberCache (this);
1204 TypeParameters parentAllTypeParameters = null;
1205 if (parent_def != null) {
1206 spec.DeclaringType = Parent.CurrentType;
1207 parent_def.MemberCache.AddMember (spec);
1208 parentAllTypeParameters = parent_def.all_type_parameters;
1211 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1212 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1214 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1216 if (CurrentTypeParameters != null)
1217 CurrentTypeParameters.Define (all_tp_builders, spec, CurrentTypeParametersStartIndex, this);
1223 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1226 int parent_offset = 0;
1227 if (parentAllTypeParameters != null) {
1228 if (CurrentTypeParameters == null) {
1229 all_type_parameters = parentAllTypeParameters;
1230 return parentAllTypeParameters.GetAllNames ();
1233 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1234 all_type_parameters = new TypeParameters (names.Length);
1235 all_type_parameters.Add (parentAllTypeParameters);
1237 parent_offset = all_type_parameters.Count;
1238 for (int i = 0; i < parent_offset; ++i)
1239 names[i] = all_type_parameters[i].MemberName.Name;
1242 names = new string[CurrentTypeParameters.Count];
1245 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1246 if (all_type_parameters != null)
1247 all_type_parameters.Add (MemberName.TypeParameters[i]);
1249 var name = CurrentTypeParameters[i].MemberName.Name;
1250 names[parent_offset + i] = name;
1251 for (int ii = 0; ii < parent_offset + i; ++ii) {
1252 if (names[ii] != name)
1255 var tp = CurrentTypeParameters[i];
1256 var conflict = all_type_parameters[ii];
1258 tp.WarningParentNameConflict (conflict);
1262 if (all_type_parameters == null)
1263 all_type_parameters = CurrentTypeParameters;
1269 public SourceMethodBuilder CreateMethodSymbolEntry ()
1271 if (Module.DeclaringAssembly.SymbolWriter == null)
1274 var source_file = GetCompilationSourceFile ();
1275 if (source_file == null)
1278 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1282 // Creates a proxy base method call inside this container for hoisted base member calls
1284 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1286 Method proxy_method;
1289 // One proxy per base method is enough
1291 if (hoisted_base_call_proxies == null) {
1292 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1293 proxy_method = null;
1295 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1298 if (proxy_method == null) {
1299 string name = CompilerGeneratedClass.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1300 var base_parameters = new Parameter[method.Parameters.Count];
1301 for (int i = 0; i < base_parameters.Length; ++i) {
1302 var base_param = method.Parameters.FixedParameters[i];
1303 base_parameters[i] = new Parameter (new TypeExpression (method.Parameters.Types[i], Location),
1304 base_param.Name, base_param.ModFlags, null, Location);
1305 base_parameters[i].Resolve (this, i);
1308 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1309 if (method.Parameters.HasArglist) {
1310 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1311 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1314 MemberName member_name;
1315 TypeArguments targs = null;
1316 if (method.IsGeneric) {
1318 // Copy all base generic method type parameters info
1320 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1321 var tparams = new TypeParameters ();
1323 targs = new TypeArguments ();
1324 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1325 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1326 var tp = hoisted_tparams[i];
1327 tparams.Add (new TypeParameter (tp, null, new MemberName (tp.Name, Location), null));
1329 targs.Add (new SimpleName (tp.Name, Location));
1330 targs.Arguments[i] = tp;
1333 member_name = new MemberName (name, tparams, Location);
1335 member_name = new MemberName (name);
1338 // Compiler generated proxy
1339 proxy_method = new Method (this, new TypeExpression (method.ReturnType, Location),
1340 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1341 member_name, cloned_params, null);
1343 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1344 IsCompilerGenerated = true
1347 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1348 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1350 mg.SetTypeArguments (rc, targs);
1352 // Get all the method parameters and pass them as arguments
1353 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1354 Statement statement;
1355 if (method.ReturnType.Kind == MemberKind.Void)
1356 statement = new StatementExpression (real_base_call);
1358 statement = new Return (real_base_call, Location);
1360 block.AddStatement (statement);
1361 proxy_method.Block = block;
1363 members.Add (proxy_method);
1364 proxy_method.Define ();
1366 hoisted_base_call_proxies.Add (method, proxy_method);
1369 return proxy_method.Spec;
1372 protected bool DefineBaseTypes ()
1374 iface_exprs = ResolveBaseTypes (out base_type_expr);
1377 if (IsPartialPart) {
1378 set_base_type = false;
1380 if (base_type_expr != null) {
1381 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1382 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1383 Report.Error (263, Location,
1384 "Partial declarations of `{0}' must not specify different base classes",
1385 GetSignatureForError ());
1387 PartialContainer.base_type_expr = base_type_expr;
1388 PartialContainer.base_type = base_type;
1389 set_base_type = true;
1393 if (iface_exprs != null) {
1394 if (PartialContainer.iface_exprs == null)
1395 PartialContainer.iface_exprs = iface_exprs;
1397 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1398 foreach (var iface_partial in iface_exprs) {
1399 if (ifaces.Contains (iface_partial))
1402 ifaces.Add (iface_partial);
1405 PartialContainer.iface_exprs = ifaces.ToArray ();
1409 PartialContainer.members.AddRange (members);
1410 if (containers != null) {
1411 if (PartialContainer.containers == null)
1412 PartialContainer.containers = new List<TypeContainer> ();
1414 PartialContainer.containers.AddRange (containers);
1417 members_defined = members_defined_ok = true;
1418 caching_flags |= Flags.CloseTypeCreated;
1420 set_base_type = true;
1423 var cycle = CheckRecursiveDefinition (this);
1424 if (cycle != null) {
1425 Report.SymbolRelatedToPreviousError (cycle);
1426 if (this is Interface) {
1427 Report.Error (529, Location,
1428 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1429 GetSignatureForError (), cycle.GetSignatureForError ());
1433 Report.Error (146, Location,
1434 "Circular base class dependency involving `{0}' and `{1}'",
1435 GetSignatureForError (), cycle.GetSignatureForError ());
1441 if (iface_exprs != null) {
1442 foreach (var iface_type in iface_exprs) {
1443 // Prevents a crash, the interface might not have been resolved: 442144
1444 if (iface_type == null)
1447 if (!spec.AddInterfaceDefined (iface_type))
1450 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1452 // Ensure the base is always setup
1453 var compiled_iface = iface_type.MemberDefinition as Interface;
1454 if (compiled_iface != null) {
1455 // TODO: Need DefineBaseType only
1456 compiled_iface.DefineContainer ();
1459 if (iface_type.Interfaces != null) {
1460 var base_ifaces = new List<TypeSpec> (iface_type.Interfaces);
1461 for (int i = 0; i < base_ifaces.Count; ++i) {
1462 var ii_iface_type = base_ifaces[i];
1463 if (spec.AddInterfaceDefined (ii_iface_type)) {
1464 TypeBuilder.AddInterfaceImplementation (ii_iface_type.GetMetaInfo ());
1466 if (ii_iface_type.Interfaces != null)
1467 base_ifaces.AddRange (ii_iface_type.Interfaces);
1474 if (Kind == MemberKind.Interface) {
1475 spec.BaseType = Compiler.BuiltinTypes.Object;
1479 if (set_base_type) {
1480 if (base_type != null) {
1481 spec.BaseType = base_type;
1483 // Set base type after type creation
1484 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1486 TypeBuilder.SetParent (null);
1493 public override void PrepareEmit ()
1495 foreach (var member in members) {
1496 var pm = member as IParametersMember;
1499 var p = pm.Parameters;
1503 ((ParametersCompiled) p).ResolveDefaultValues (member);
1506 var c = member as Const;
1511 base.PrepareEmit ();
1515 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1517 public override bool CreateContainer ()
1519 if (TypeBuilder != null)
1525 if (IsPartialPart) {
1526 spec = PartialContainer.spec;
1527 TypeBuilder = PartialContainer.TypeBuilder;
1528 all_tp_builders = PartialContainer.all_tp_builders;
1529 all_type_parameters = PartialContainer.all_type_parameters;
1531 if (!CreateTypeBuilder ()) {
1537 return base.CreateContainer ();
1540 protected override void DoDefineContainer ()
1544 DoResolveTypeParameters ();
1548 // Replaces normal spec with predefined one when compiling corlib
1549 // and this type container defines predefined type
1551 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1553 // When compiling build-in types we start with two
1554 // version of same type. One is of BuiltinTypeSpec and
1555 // second one is ordinary TypeSpec. The unification
1556 // happens at later stage when we know which type
1557 // really matches the builtin type signature. However
1558 // that means TypeSpec create during CreateType of this
1559 // type has to be replaced with builtin one
1561 spec.SetMetaInfo (TypeBuilder);
1562 spec.MemberCache = this.spec.MemberCache;
1563 spec.DeclaringType = this.spec.DeclaringType;
1566 current_type = null;
1569 void UpdateTypeParameterConstraints (TypeDefinition part)
1571 for (int i = 0; i < CurrentTypeParameters.Count; i++) {
1572 if (CurrentTypeParameters[i].AddPartialConstraints (part, part.MemberName.TypeParameters[i]))
1575 Report.SymbolRelatedToPreviousError (Location, "");
1576 Report.Error (265, part.Location,
1577 "Partial declarations of `{0}' have inconsistent constraints for type parameter `{1}'",
1578 GetSignatureForError (), CurrentTypeParameters[i].GetSignatureForError ());
1582 public override void RemoveContainer (TypeContainer cont)
1584 base.RemoveContainer (cont);
1585 Members.Remove (cont);
1586 Cache.Remove (cont.Basename);
1589 protected virtual bool DoResolveTypeParameters ()
1591 var tparams = CurrentTypeParameters;
1592 if (tparams == null)
1595 var base_context = new BaseContext (this);
1596 for (int i = 0; i < tparams.Count; ++i) {
1597 var tp = tparams[i];
1599 if (!tp.ResolveConstraints (base_context)) {
1605 if (IsPartialPart) {
1606 PartialContainer.UpdateTypeParameterConstraints (this);
1612 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1614 if (InTransit != null)
1619 if (base_type != null) {
1620 var ptc = base_type.MemberDefinition as TypeDefinition;
1621 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1625 if (iface_exprs != null) {
1626 foreach (var iface in iface_exprs) {
1627 // the interface might not have been resolved, prevents a crash, see #442144
1630 var ptc = iface.MemberDefinition as Interface;
1631 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1636 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1644 /// Populates our TypeBuilder with fields and methods
1646 public sealed override bool Define ()
1648 if (members_defined)
1649 return members_defined_ok;
1651 members_defined_ok = DoDefineMembers ();
1652 members_defined = true;
1656 return members_defined_ok;
1659 protected virtual bool DoDefineMembers ()
1661 Debug.Assert (!IsPartialPart);
1663 if (iface_exprs != null) {
1664 foreach (var iface_type in iface_exprs) {
1665 if (iface_type == null)
1668 // Ensure the base is always setup
1669 var compiled_iface = iface_type.MemberDefinition as Interface;
1670 if (compiled_iface != null)
1671 compiled_iface.Define ();
1673 if (Kind == MemberKind.Interface)
1674 MemberCache.AddInterface (iface_type);
1676 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1677 if (oa != null && !IsObsolete)
1678 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1680 if (iface_type.Arity > 0) {
1681 // TODO: passing `this' is wrong, should be base type iface instead
1682 TypeManager.CheckTypeVariance (iface_type, Variance.Covariant, this);
1684 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1685 Report.Error (1966, Location,
1686 "`{0}': cannot implement a dynamic interface `{1}'",
1687 GetSignatureForError (), iface_type.GetSignatureForError ());
1692 if (iface_type.IsGenericOrParentIsGeneric) {
1693 if (spec.Interfaces != null) {
1694 foreach (var prev_iface in iface_exprs) {
1695 if (prev_iface == iface_type)
1698 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1701 Report.Error (695, Location,
1702 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1703 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1710 if (base_type != null) {
1712 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1714 if (base_type_expr != null) {
1715 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1716 if (obsolete_attr != null && !IsObsolete)
1717 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1719 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1720 Report.Error (698, base_type_expr.Location,
1721 "A generic type cannot derive from `{0}' because it is an attribute class",
1722 base_type.GetSignatureForError ());
1726 if (base_type.Interfaces != null) {
1727 foreach (var iface in base_type.Interfaces)
1728 spec.AddInterface (iface);
1731 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1732 if (baseContainer != null) {
1733 baseContainer.Define ();
1736 // It can trigger define of this type (for generic types only)
1738 if (HasMembersDefined)
1743 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1744 pending = PendingImplementation.GetPendingImplementations (this);
1747 var count = members.Count;
1748 for (int i = 0; i < count; ++i) {
1749 var mc = members[i] as InterfaceMemberBase;
1750 if (mc == null || !mc.IsExplicitImpl)
1755 } catch (Exception e) {
1756 throw new InternalErrorException (mc, e);
1760 for (int i = 0; i < count; ++i) {
1761 var mc = members[i] as InterfaceMemberBase;
1762 if (mc != null && mc.IsExplicitImpl)
1765 if (members[i] is TypeContainer)
1769 members[i].Define ();
1770 } catch (Exception e) {
1771 throw new InternalErrorException (members[i], e);
1776 CheckPairedOperators ();
1779 if (requires_delayed_unmanagedtype_check) {
1780 requires_delayed_unmanagedtype_check = false;
1781 foreach (var member in members) {
1782 var f = member as Field;
1783 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1784 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1788 ComputeIndexerName();
1790 if (HasEquals && !HasGetHashCode) {
1791 Report.Warning (659, 3, Location,
1792 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1795 if (Kind == MemberKind.Interface && iface_exprs != null) {
1796 MemberCache.RemoveHiddenMembers (spec);
1802 void ComputeIndexerName ()
1804 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1805 if (indexers == null)
1808 string class_indexer_name = null;
1809 has_normal_indexers = true;
1812 // Check normal indexers for consistent name, explicit interface implementation
1813 // indexers are ignored
1815 foreach (var indexer in indexers) {
1816 if (class_indexer_name == null) {
1817 indexer_name = class_indexer_name = indexer.Name;
1821 if (indexer.Name != class_indexer_name)
1822 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
1823 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
1827 void EmitIndexerName ()
1829 if (!has_normal_indexers)
1832 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
1836 var encoder = new AttributeEncoder ();
1837 encoder.Encode (GetAttributeDefaultMember ());
1838 encoder.EncodeEmptyNamedArguments ();
1840 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1843 public override void VerifyMembers ()
1846 // Check for internal or private fields that were never assigned
1848 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
1849 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
1850 foreach (var member in members) {
1851 if (member is Event) {
1853 // An event can be assigned from same class only, so we can report
1854 // this warning for all accessibility modes
1857 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
1862 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
1863 if (is_type_exposed)
1866 member.SetIsUsed ();
1869 var f = member as Field;
1873 if (!member.IsUsed) {
1874 if ((member.caching_flags & Flags.IsAssigned) == 0) {
1875 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
1877 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
1878 member.GetSignatureForError ());
1883 if ((f.caching_flags & Flags.IsAssigned) != 0)
1887 // Only report 649 on level 4
1889 if (Compiler.Settings.WarningLevel < 4)
1893 // Don't be pendatic over serializable attributes
1895 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
1898 Constant c = New.Constantify (f.MemberType, f.Location);
1901 value = c.GetValueAsLiteral ();
1902 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
1905 // Ignore this warning for struct value fields (they are always initialized)
1906 if (f.MemberType.IsStruct)
1913 value = " `" + value + "'";
1915 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
1916 f.GetSignatureForError (), value);
1920 base.VerifyMembers ();
1923 public override void Emit ()
1925 if (OptAttributes != null)
1926 OptAttributes.Emit ();
1929 MemberSpec candidate;
1930 bool overrides = false;
1931 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
1932 if (conflict_symbol == null && candidate == null) {
1933 if ((ModFlags & Modifiers.NEW) != 0)
1934 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
1935 GetSignatureForError ());
1937 if ((ModFlags & Modifiers.NEW) == 0) {
1938 if (candidate == null)
1939 candidate = conflict_symbol;
1941 Report.SymbolRelatedToPreviousError (candidate);
1942 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
1943 GetSignatureForError (), candidate.GetSignatureForError ());
1948 // Run constraints check on all possible generic types
1949 if ((ModFlags & Modifiers.COMPILER_GENERATED) == 0) {
1950 if (base_type != null && base_type_expr != null) {
1951 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
1954 if (iface_exprs != null) {
1955 foreach (var iface_type in iface_exprs) {
1956 if (iface_type == null)
1959 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
1964 if (all_tp_builders != null) {
1965 int current_starts_index = CurrentTypeParametersStartIndex;
1966 for (int i = 0; i < all_tp_builders.Length; i++) {
1967 if (i < current_starts_index) {
1968 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
1970 var tp = CurrentTypeParameters [i - current_starts_index];
1971 tp.CheckGenericConstraints (!IsObsolete);
1977 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
1978 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
1981 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
1982 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
1987 for (int i = 0; i < members.Count; i++)
1991 CheckAttributeClsCompliance ();
1993 if (pending != null)
1994 pending.VerifyPendingMethods ();
1998 void CheckAttributeClsCompliance ()
2000 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2003 foreach (var m in members) {
2004 var c = m as Constructor;
2008 if (c.HasCompliantArgs)
2012 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2015 public sealed override void EmitContainer ()
2017 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2023 public override void CloseContainer ()
2025 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2028 // Close base type container first to avoid TypeLoadException
2029 if (spec.BaseType != null) {
2030 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2031 if (btype != null) {
2032 btype.CloseContainer ();
2034 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2040 caching_flags |= Flags.CloseTypeCreated;
2041 TypeBuilder.CreateType ();
2042 } catch (TypeLoadException) {
2044 // This is fine, the code still created the type
2046 } catch (Exception e) {
2047 throw new InternalErrorException (this, e);
2050 base.CloseContainer ();
2053 initialized_fields = null;
2054 initialized_static_fields = null;
2056 OptAttributes = null;
2060 // Performs the validation on a Method's modifiers (properties have
2061 // the same properties).
2063 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2065 public bool MethodModifiersValid (MemberCore mc)
2067 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2068 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2070 var flags = mc.ModFlags;
2073 // At most one of static, virtual or override
2075 if ((flags & Modifiers.STATIC) != 0){
2076 if ((flags & vao) != 0){
2077 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2078 mc.GetSignatureForError ());
2083 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2084 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2085 mc.GetSignatureForError ());
2090 // If the declaration includes the abstract modifier, then the
2091 // declaration does not include static, virtual or extern
2093 if ((flags & Modifiers.ABSTRACT) != 0){
2094 if ((flags & Modifiers.EXTERN) != 0){
2096 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2100 if ((flags & Modifiers.SEALED) != 0) {
2101 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2105 if ((flags & Modifiers.VIRTUAL) != 0){
2106 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2110 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2111 Report.SymbolRelatedToPreviousError (this);
2112 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2113 mc.GetSignatureForError (), GetSignatureForError ());
2118 if ((flags & Modifiers.PRIVATE) != 0){
2119 if ((flags & vao) != 0){
2120 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2125 if ((flags & Modifiers.SEALED) != 0){
2126 if ((flags & Modifiers.OVERRIDE) == 0){
2127 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2135 protected override bool VerifyClsCompliance ()
2137 if (!base.VerifyClsCompliance ())
2140 // Check all container names for user classes
2141 if (Kind != MemberKind.Delegate)
2142 MemberCache.VerifyClsCompliance (Definition, Report);
2144 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2145 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2146 GetSignatureForError (), BaseType.GetSignatureForError ());
2152 /// Performs checks for an explicit interface implementation. First it
2153 /// checks whether the `interface_type' is a base inteface implementation.
2154 /// Then it checks whether `name' exists in the interface type.
2156 public bool VerifyImplements (InterfaceMemberBase mb)
2158 var ifaces = spec.Interfaces;
2159 if (ifaces != null) {
2160 foreach (TypeSpec t in ifaces){
2161 if (t == mb.InterfaceType)
2166 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2167 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2168 mb.GetSignatureForError (), TypeManager.CSharpName (mb.InterfaceType));
2173 // Used for visiblity checks to tests whether this definition shares
2174 // base type baseType, it does member-definition search
2176 public bool IsBaseTypeDefinition (TypeSpec baseType)
2178 // RootContext check
2179 if (TypeBuilder == null)
2184 if (type.MemberDefinition == baseType.MemberDefinition)
2187 type = type.BaseType;
2188 } while (type != null);
2193 public override bool IsClsComplianceRequired ()
2196 return PartialContainer.IsClsComplianceRequired ();
2198 return base.IsClsComplianceRequired ();
2201 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2203 return Module.DeclaringAssembly == assembly;
2206 public virtual bool IsUnmanagedType ()
2211 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2213 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2217 // Public function used to locate types.
2219 // Set 'ignore_cs0104' to true if you want to ignore cs0104 errors.
2221 // Returns: Type or null if they type can not be found.
2223 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2225 FullNamedExpression e;
2226 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2232 var tp = CurrentTypeParameters;
2234 TypeParameter tparam = tp.Find (name);
2236 e = new TypeParameterExpr (tparam, Location.Null);
2241 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2243 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2244 e = new TypeExpression (t, Location.Null);
2246 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2250 // TODO MemberCache: How to cache arity stuff ?
2251 if (arity == 0 && mode == LookupMode.Normal)
2257 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2259 // Has any nested type
2260 // Does not work, because base type can have
2261 //if (PartialContainer.Types == null)
2264 var container = PartialContainer.CurrentType;
2265 return MemberCache.FindNestedType (container, name, arity);
2268 public void Mark_HasEquals ()
2270 cached_method |= CachedMethods.Equals;
2273 public void Mark_HasGetHashCode ()
2275 cached_method |= CachedMethods.GetHashCode;
2278 public override void WriteDebugSymbol (MonoSymbolFile file)
2283 foreach (var m in members) {
2284 m.WriteDebugSymbol (file);
2289 /// Method container contains Equals method
2291 public bool HasEquals {
2293 return (cached_method & CachedMethods.Equals) != 0;
2298 /// Method container contains GetHashCode method
2300 public bool HasGetHashCode {
2302 return (cached_method & CachedMethods.GetHashCode) != 0;
2306 public bool HasStaticFieldInitializer {
2308 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2312 cached_method |= CachedMethods.HasStaticFieldInitializer;
2314 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2318 public override string DocCommentHeader {
2319 get { return "T:"; }
2323 public abstract class ClassOrStruct : TypeDefinition
2325 SecurityType declarative_security;
2327 public ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2328 : base (parent, name, attrs, kind)
2332 protected override TypeAttributes TypeAttr {
2334 return has_static_constructor ? base.TypeAttr : base.TypeAttr | TypeAttributes.BeforeFieldInit;
2338 public override void AddNameToContainer (MemberCore symbol, string name)
2340 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2341 if (symbol is TypeParameter) {
2342 Report.Error (694, symbol.Location,
2343 "Type parameter `{0}' has same name as containing type, or method",
2344 symbol.GetSignatureForError ());
2348 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2349 if (imb == null || !imb.IsExplicitImpl) {
2350 Report.SymbolRelatedToPreviousError (this);
2351 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2352 symbol.GetSignatureForError ());
2357 base.AddNameToContainer (symbol, name);
2360 public override void VerifyMembers ()
2362 base.VerifyMembers ();
2364 if (containers != null) {
2365 foreach (var t in containers)
2370 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2372 if (a.IsValidSecurityAttribute ()) {
2373 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2377 if (a.Type == pa.StructLayout) {
2378 PartialContainer.HasStructLayout = true;
2379 if (a.IsExplicitLayoutKind ())
2380 PartialContainer.HasExplicitLayout = true;
2383 if (a.Type == pa.Dynamic) {
2384 a.Error_MisusedDynamicAttribute ();
2388 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2392 /// Defines the default constructors
2394 protected Constructor DefineDefaultConstructor (bool is_static)
2396 // The default instance constructor is public
2397 // If the class is abstract, the default constructor is protected
2398 // The default static constructor is private
2402 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2404 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2407 var c = new Constructor (this, MemberName.Name, mods, null, ParametersCompiled.EmptyReadOnlyParameters, Location);
2408 c.Initializer = new GeneratedBaseInitializer (Location);
2410 AddConstructor (c, true);
2411 c.Block = new ToplevelBlock (Compiler, ParametersCompiled.EmptyReadOnlyParameters, Location) {
2412 IsCompilerGenerated = true
2418 protected override bool DoDefineMembers ()
2420 CheckProtectedModifier ();
2422 base.DoDefineMembers ();
2427 public override void Emit ()
2429 if (!has_static_constructor && HasStaticFieldInitializer) {
2430 var c = DefineDefaultConstructor (true);
2436 if (declarative_security != null) {
2437 foreach (var de in declarative_security) {
2439 TypeBuilder.__AddDeclarativeSecurity (de);
2441 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2449 // TODO: should be sealed
2450 public class Class : ClassOrStruct {
2451 const Modifiers AllowedModifiers =
2454 Modifiers.PROTECTED |
2455 Modifiers.INTERNAL |
2457 Modifiers.ABSTRACT |
2462 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2464 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2465 : base (parent, name, attrs, MemberKind.Class)
2467 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2468 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2469 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2472 public override void Accept (StructuralVisitor visitor)
2474 visitor.Visit (this);
2477 public override void AddBasesForPart (List<FullNamedExpression> bases)
2479 var pmn = MemberName;
2480 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2481 Report.Error (537, Location,
2482 "The class System.Object cannot have a base class or implement an interface.");
2484 base.AddBasesForPart (bases);
2487 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2489 if (a.Type == pa.AttributeUsage) {
2490 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2491 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2495 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2496 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2500 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2501 a.Error_MissingGuidAttribute ();
2505 if (a.Type == pa.Extension) {
2506 a.Error_MisusedExtensionAttribute ();
2510 if (a.Type.IsConditionallyExcluded (this, Location))
2513 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2516 public override AttributeTargets AttributeTargets {
2518 return AttributeTargets.Class;
2522 protected override bool DoDefineMembers ()
2524 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2525 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2528 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2529 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2533 foreach (var m in Members) {
2534 if (m is Operator) {
2535 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2539 if (m is Destructor) {
2540 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2545 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2549 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2552 if (m is Constructor) {
2553 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2557 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2560 if (!PartialContainer.HasInstanceConstructor)
2561 DefineDefaultConstructor (false);
2564 return base.DoDefineMembers ();
2567 public override void Emit ()
2571 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2572 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2574 if (base_type != null && base_type.HasDynamicElement) {
2575 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2579 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2581 var ifaces = base.ResolveBaseTypes (out base_class);
2583 if (base_class == null) {
2584 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2585 base_type = Compiler.BuiltinTypes.Object;
2587 if (base_type.IsGenericParameter){
2588 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2589 GetSignatureForError (), base_type.GetSignatureForError ());
2590 } else if (base_type.IsStatic) {
2591 Report.SymbolRelatedToPreviousError (base_type);
2592 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2593 GetSignatureForError (), base_type.GetSignatureForError ());
2594 } else if (base_type.IsSealed) {
2595 Report.SymbolRelatedToPreviousError (base_type);
2596 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2597 GetSignatureForError (), base_type.GetSignatureForError ());
2598 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2599 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2600 GetSignatureForError (), base_type.GetSignatureForError ());
2603 switch (base_type.BuiltinType) {
2604 case BuiltinTypeSpec.Type.Enum:
2605 case BuiltinTypeSpec.Type.ValueType:
2606 case BuiltinTypeSpec.Type.MulticastDelegate:
2607 case BuiltinTypeSpec.Type.Delegate:
2608 case BuiltinTypeSpec.Type.Array:
2609 if (!(spec is BuiltinTypeSpec)) {
2610 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2611 GetSignatureForError (), base_type.GetSignatureForError ());
2613 base_type = Compiler.BuiltinTypes.Object;
2618 if (!IsAccessibleAs (base_type)) {
2619 Report.SymbolRelatedToPreviousError (base_type);
2620 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2621 base_type.GetSignatureForError (), GetSignatureForError ());
2625 if (PartialContainer.IsStatic && ifaces != null) {
2626 foreach (var t in ifaces)
2627 Report.SymbolRelatedToPreviousError (t);
2628 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2634 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2635 /// Valid only for attribute classes.
2636 public override string[] ConditionalConditions ()
2638 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2641 caching_flags &= ~Flags.Excluded_Undetected;
2643 if (OptAttributes == null)
2646 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2650 string[] conditions = new string[attrs.Length];
2651 for (int i = 0; i < conditions.Length; ++i)
2652 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2654 caching_flags |= Flags.Excluded;
2659 // FIXME: How do we deal with the user specifying a different
2662 protected override TypeAttributes TypeAttr {
2664 TypeAttributes ta = base.TypeAttr | TypeAttributes.AutoLayout | TypeAttributes.Class;
2666 ta |= StaticClassAttribute;
2672 public sealed class Struct : ClassOrStruct {
2674 bool is_unmanaged, has_unmanaged_check_done;
2678 // Modifiers allowed in a struct declaration
2680 const Modifiers AllowedModifiers =
2683 Modifiers.PROTECTED |
2684 Modifiers.INTERNAL |
2688 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2689 : base (parent, name, attrs, MemberKind.Struct)
2691 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2692 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2693 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2696 public override AttributeTargets AttributeTargets {
2698 return AttributeTargets.Struct;
2702 public override void Accept (StructuralVisitor visitor)
2704 visitor.Visit (this);
2707 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2709 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2712 // When struct constains fixed fixed and struct layout has explicitly
2713 // set CharSet, its value has to be propagated to compiler generated
2716 if (a.Type == pa.StructLayout) {
2717 var value = a.GetNamedValue ("CharSet");
2721 for (int i = 0; i < Members.Count; ++i) {
2722 FixedField ff = Members [i] as FixedField;
2726 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2731 bool CheckStructCycles ()
2737 foreach (var member in Members) {
2738 var field = member as Field;
2742 TypeSpec ftype = field.Spec.MemberType;
2743 if (!ftype.IsStruct)
2746 if (ftype is BuiltinTypeSpec)
2749 foreach (var targ in ftype.TypeArguments) {
2750 if (!CheckFieldTypeCycle (targ)) {
2751 Report.Error (523, field.Location,
2752 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2753 field.GetSignatureForError (), ftype.GetSignatureForError ());
2759 // Static fields of exactly same type are allowed
2761 if (field.IsStatic && ftype == CurrentType)
2764 if (!CheckFieldTypeCycle (ftype)) {
2765 Report.Error (523, field.Location,
2766 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2767 field.GetSignatureForError (), ftype.GetSignatureForError ());
2776 static bool CheckFieldTypeCycle (TypeSpec ts)
2778 var fts = ts.MemberDefinition as Struct;
2782 return fts.CheckStructCycles ();
2785 public override void Emit ()
2787 CheckStructCycles ();
2792 public override bool IsUnmanagedType ()
2794 if (has_unmanaged_check_done)
2795 return is_unmanaged;
2797 if (requires_delayed_unmanagedtype_check)
2800 var parent_def = Parent.PartialContainer;
2801 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
2802 has_unmanaged_check_done = true;
2806 if (first_nonstatic_field != null) {
2807 requires_delayed_unmanagedtype_check = true;
2809 foreach (var member in Members) {
2810 var f = member as Field;
2817 // It can happen when recursive unmanaged types are defined
2818 // struct S { S* s; }
2819 TypeSpec mt = f.MemberType;
2827 has_unmanaged_check_done = true;
2831 has_unmanaged_check_done = true;
2834 is_unmanaged = true;
2838 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2840 var ifaces = base.ResolveBaseTypes (out base_class);
2841 base_type = Compiler.BuiltinTypes.ValueType;
2845 protected override TypeAttributes TypeAttr {
2847 const TypeAttributes DefaultTypeAttributes =
2848 TypeAttributes.SequentialLayout |
2849 TypeAttributes.Sealed;
2851 return base.TypeAttr | DefaultTypeAttributes;
2855 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
2857 if ((field.ModFlags & Modifiers.STATIC) == 0) {
2858 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
2859 field.GetSignatureForError ());
2862 base.RegisterFieldForInitialization (field, expression);
2870 public sealed class Interface : TypeDefinition {
2873 /// Modifiers allowed in a class declaration
2875 const Modifiers AllowedModifiers =
2878 Modifiers.PROTECTED |
2879 Modifiers.INTERNAL |
2883 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2884 : base (parent, name, attrs, MemberKind.Interface)
2886 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2888 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
2889 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2894 public override AttributeTargets AttributeTargets {
2896 return AttributeTargets.Interface;
2900 protected override TypeAttributes TypeAttr {
2902 const TypeAttributes DefaultTypeAttributes =
2903 TypeAttributes.AutoLayout |
2904 TypeAttributes.Abstract |
2905 TypeAttributes.Interface;
2907 return base.TypeAttr | DefaultTypeAttributes;
2913 public override void Accept (StructuralVisitor visitor)
2915 visitor.Visit (this);
2918 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2920 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2921 a.Error_MissingGuidAttribute ();
2925 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2928 protected override bool VerifyClsCompliance ()
2930 if (!base.VerifyClsCompliance ())
2933 if (iface_exprs != null) {
2934 foreach (var iface in iface_exprs) {
2935 if (iface.IsCLSCompliant ())
2938 Report.SymbolRelatedToPreviousError (iface);
2939 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
2940 GetSignatureForError (), TypeManager.CSharpName (iface));
2948 public abstract class InterfaceMemberBase : MemberBase
2951 // Common modifiers allowed in a class declaration
2953 protected const Modifiers AllowedModifiersClass =
2956 Modifiers.PROTECTED |
2957 Modifiers.INTERNAL |
2962 Modifiers.OVERRIDE |
2963 Modifiers.ABSTRACT |
2968 // Common modifiers allowed in a struct declaration
2970 protected const Modifiers AllowedModifiersStruct =
2973 Modifiers.PROTECTED |
2974 Modifiers.INTERNAL |
2977 Modifiers.OVERRIDE |
2982 // Common modifiers allowed in a interface declaration
2984 protected const Modifiers AllowedModifiersInterface =
2989 // Whether this is an interface member.
2991 public bool IsInterface;
2994 // If true, this is an explicit interface implementation
2996 public readonly bool IsExplicitImpl;
2998 protected bool is_external_implementation;
3001 // The interface type we are explicitly implementing
3003 public TypeSpec InterfaceType;
3006 // The method we're overriding if this is an override method.
3008 protected MethodSpec base_method;
3010 readonly Modifiers explicit_mod_flags;
3011 public MethodAttributes flags;
3013 public InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3014 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3016 IsInterface = parent.Kind == MemberKind.Interface;
3017 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3018 explicit_mod_flags = mod;
3021 public abstract Variance ExpectedMemberTypeVariance { get; }
3023 protected override bool CheckBase ()
3025 if (!base.CheckBase ())
3028 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3029 CheckForDuplications ();
3034 // For System.Object only
3035 if (Parent.BaseType == null)
3038 MemberSpec candidate;
3039 bool overrides = false;
3040 var base_member = FindBaseMember (out candidate, ref overrides);
3042 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3043 if (base_member == null) {
3044 if (candidate == null) {
3045 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3046 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3047 "object.Finalize()");
3049 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3050 GetSignatureForError (), SimpleName.GetMemberType (this));
3053 Report.SymbolRelatedToPreviousError (candidate);
3055 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3056 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3057 else if (this is PropertyBase)
3058 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3059 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3061 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3062 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3069 // Handles ambiguous overrides
3071 if (candidate != null) {
3072 Report.SymbolRelatedToPreviousError (candidate);
3073 Report.SymbolRelatedToPreviousError (base_member);
3075 // Get member definition for error reporting
3076 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3077 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3079 Report.Error (462, Location,
3080 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3081 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3084 if (!CheckOverrideAgainstBase (base_member))
3087 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3089 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3090 Report.SymbolRelatedToPreviousError (base_member);
3091 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3092 GetSignatureForError (), base_member.GetSignatureForError ());
3095 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3096 Report.SymbolRelatedToPreviousError (base_member);
3097 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3098 GetSignatureForError (), base_member.GetSignatureForError ());
3102 base_method = base_member as MethodSpec;
3106 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3107 base_member = candidate;
3109 if (base_member == null) {
3110 if ((ModFlags & Modifiers.NEW) != 0) {
3111 if (base_member == null) {
3112 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3113 GetSignatureForError ());
3117 if ((ModFlags & Modifiers.NEW) == 0) {
3118 ModFlags |= Modifiers.NEW;
3119 if (!IsCompilerGenerated) {
3120 Report.SymbolRelatedToPreviousError (base_member);
3121 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3122 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",
3123 GetSignatureForError (), base_member.GetSignatureForError ());
3125 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3126 GetSignatureForError (), base_member.GetSignatureForError ());
3131 if (!IsInterface && base_member.IsAbstract && !overrides) {
3132 Report.SymbolRelatedToPreviousError (base_member);
3133 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3134 GetSignatureForError (), base_member.GetSignatureForError ());
3141 protected virtual bool CheckForDuplications ()
3143 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3147 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3148 // that have been defined.
3150 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3154 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3155 Report.SymbolRelatedToPreviousError (base_member);
3156 Report.Error (506, Location,
3157 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3158 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3162 // Now we check that the overriden method is not final
3163 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3164 Report.SymbolRelatedToPreviousError (base_member);
3165 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3166 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3170 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3171 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3172 Report.SymbolRelatedToPreviousError (base_member);
3173 if (this is PropertyBasedMember) {
3174 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3175 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3177 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3178 GetSignatureForError (), TypeManager.CSharpName (base_member_type), TypeManager.CSharpSignature (base_member));
3186 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3188 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3189 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3191 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3193 // It must be at least "protected"
3195 if ((thisp & Modifiers.PROTECTED) == 0) {
3200 // when overriding protected internal, the method can be declared
3201 // protected internal only within the same assembly or assembly
3202 // which has InternalsVisibleTo
3204 if ((thisp & Modifiers.INTERNAL) != 0) {
3205 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3209 // protected overriding protected internal inside same assembly
3210 // requires internal modifier as well
3212 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3219 return thisp == base_classp;
3222 public override bool Define ()
3225 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3226 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3228 flags = MethodAttributes.Public |
3229 MethodAttributes.Abstract |
3230 MethodAttributes.HideBySig |
3231 MethodAttributes.NewSlot |
3232 MethodAttributes.Virtual;
3234 Parent.PartialContainer.MethodModifiersValid (this);
3236 flags = ModifiersExtensions.MethodAttr (ModFlags);
3239 if (IsExplicitImpl) {
3240 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3241 if (InterfaceType == null)
3244 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3245 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3246 GetSignatureForError ());
3249 if (!InterfaceType.IsInterface) {
3250 Report.SymbolRelatedToPreviousError (InterfaceType);
3251 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3252 TypeManager.CSharpName (InterfaceType));
3254 Parent.PartialContainer.VerifyImplements (this);
3257 ModifiersExtensions.Check (Modifiers.AllowedExplicitImplFlags, explicit_mod_flags, 0, Location, Report);
3260 return base.Define ();
3263 protected bool DefineParameters (ParametersCompiled parameters)
3265 if (!parameters.Resolve (this))
3269 for (int i = 0; i < parameters.Count; ++i) {
3270 Parameter p = parameters [i];
3272 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3273 p.Warning_UselessOptionalParameter (Report);
3275 if (p.CheckAccessibility (this))
3278 TypeSpec t = parameters.Types [i];
3279 Report.SymbolRelatedToPreviousError (t);
3280 if (this is Indexer)
3281 Report.Error (55, Location,
3282 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3283 TypeManager.CSharpName (t), GetSignatureForError ());
3284 else if (this is Operator)
3285 Report.Error (57, Location,
3286 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3287 TypeManager.CSharpName (t), GetSignatureForError ());
3289 Report.Error (51, Location,
3290 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3291 TypeManager.CSharpName (t), GetSignatureForError ());
3297 protected override void DoMemberTypeDependentChecks ()
3299 base.DoMemberTypeDependentChecks ();
3301 TypeManager.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3304 public override void Emit()
3306 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3307 // We are more strict than csc and report this as an error because SRE does not allow emit that
3308 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation) {
3309 if (this is Constructor) {
3310 Report.Warning (824, 1, Location,
3311 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3313 Report.Warning (626, 1, Location,
3314 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3315 GetSignatureForError ());
3322 public override bool EnableOverloadChecks (MemberCore overload)
3325 // Two members can differ in their explicit interface
3326 // type parameter only
3328 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3329 if (imb != null && imb.IsExplicitImpl) {
3330 if (IsExplicitImpl) {
3331 caching_flags |= Flags.MethodOverloadsExist;
3336 return IsExplicitImpl;
3339 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3341 var base_modifiers = base_member.Modifiers;
3343 // Remove internal modifier from types which are not internally accessible
3344 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3345 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3346 base_modifiers = Modifiers.PROTECTED;
3348 Report.SymbolRelatedToPreviousError (base_member);
3349 Report.Error (507, member.Location,
3350 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3351 member.GetSignatureForError (),
3352 ModifiersExtensions.AccessibilityName (base_modifiers),
3353 base_member.GetSignatureForError ());
3356 protected void Error_StaticReturnType ()
3358 Report.Error (722, Location,
3359 "`{0}': static types cannot be used as return types",
3360 MemberType.GetSignatureForError ());
3364 /// Gets base method and its return type
3366 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3368 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3372 // The "short" name of this property / indexer / event. This is the
3373 // name without the explicit interface.
3375 public string ShortName {
3376 get { return MemberName.Name; }
3380 // Returns full metadata method name
3382 public string GetFullName (MemberName name)
3384 return GetFullName (name.Name);
3387 public string GetFullName (string name)
3389 if (!IsExplicitImpl)
3393 // When dealing with explicit members a full interface type
3394 // name is added to member name to avoid possible name conflicts
3396 // We use CSharpName which gets us full name with benefit of
3397 // replacing predefined names which saves some space and name
3400 return TypeManager.CSharpName (InterfaceType) + "." + name;
3403 public override string GetSignatureForDocumentation ()
3406 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3408 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3411 public override bool IsUsed
3413 get { return IsExplicitImpl || base.IsUsed; }
3418 public abstract class MemberBase : MemberCore
3420 protected FullNamedExpression type_expr;
3421 protected TypeSpec member_type;
3422 public new TypeDefinition Parent;
3424 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3425 : base (parent, name, attrs)
3427 this.Parent = parent;
3428 this.type_expr = type;
3429 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3434 public TypeSpec MemberType {
3440 public FullNamedExpression TypeExpression {
3449 // Main member define entry
3451 public override bool Define ()
3453 DoMemberTypeIndependentChecks ();
3456 // Returns false only when type resolution failed
3458 if (!ResolveMemberType ())
3461 DoMemberTypeDependentChecks ();
3466 // Any type_name independent checks
3468 protected virtual void DoMemberTypeIndependentChecks ()
3470 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3471 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3472 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3473 GetSignatureForError (), Parent.GetSignatureForError ());
3478 // Any type_name dependent checks
3480 protected virtual void DoMemberTypeDependentChecks ()
3482 // verify accessibility
3483 if (!IsAccessibleAs (MemberType)) {
3484 Report.SymbolRelatedToPreviousError (MemberType);
3485 if (this is Property)
3486 Report.Error (53, Location,
3487 "Inconsistent accessibility: property type `" +
3488 TypeManager.CSharpName (MemberType) + "' is less " +
3489 "accessible than property `" + GetSignatureForError () + "'");
3490 else if (this is Indexer)
3491 Report.Error (54, Location,
3492 "Inconsistent accessibility: indexer return type `" +
3493 TypeManager.CSharpName (MemberType) + "' is less " +
3494 "accessible than indexer `" + GetSignatureForError () + "'");
3495 else if (this is MethodCore) {
3496 if (this is Operator)
3497 Report.Error (56, Location,
3498 "Inconsistent accessibility: return type `" +
3499 TypeManager.CSharpName (MemberType) + "' is less " +
3500 "accessible than operator `" + GetSignatureForError () + "'");
3502 Report.Error (50, Location,
3503 "Inconsistent accessibility: return type `" +
3504 TypeManager.CSharpName (MemberType) + "' is less " +
3505 "accessible than method `" + GetSignatureForError () + "'");
3507 Report.Error (52, Location,
3508 "Inconsistent accessibility: field type `" +
3509 TypeManager.CSharpName (MemberType) + "' is less " +
3510 "accessible than field `" + GetSignatureForError () + "'");
3515 protected void IsTypePermitted ()
3517 if (MemberType.IsSpecialRuntimeType) {
3518 if (Parent is StateMachine) {
3519 Report.Error (4012, Location,
3520 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3521 MemberType.GetSignatureForError ());
3522 } else if (Parent is HoistedStoreyClass) {
3523 Report.Error (4013, Location,
3524 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3525 MemberType.GetSignatureForError ());
3527 Report.Error (610, Location,
3528 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3533 protected virtual bool CheckBase ()
3535 CheckProtectedModifier ();
3540 public override string GetSignatureForDocumentation ()
3542 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3545 protected virtual bool ResolveMemberType ()
3547 if (member_type != null)
3548 throw new InternalErrorException ("Multi-resolve");
3550 member_type = type_expr.ResolveAsType (this);
3551 return member_type != null;