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)
17 using System.Collections.Generic;
18 using System.Runtime.InteropServices;
19 using System.Security;
20 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 int CounterAnonymousMethods { get; set; }
58 public int CounterAnonymousContainers { get; set; }
59 public int CounterSwitchTypes { get; set; }
61 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
62 : base (parent, name, attrs)
66 this.Basename = name.Basename;
68 defined_names = new Dictionary<string, MemberCore> ();
71 public override TypeSpec CurrentType {
77 public Dictionary<string, MemberCore> DefinedNames {
83 public TypeDefinition PartialContainer {
85 return main_container;
88 main_container = value;
92 public IList<TypeContainer> Containers {
99 // Any unattached attributes during parsing get added here. User
102 public Attributes UnattachedAttributes {
106 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
108 AddTypeContainerMember (c);
111 public virtual void AddPartial (TypeDefinition next_part)
114 (PartialContainer ?? this).defined_names.TryGetValue (next_part.Basename, out mc);
116 AddPartial (next_part, mc as TypeDefinition);
119 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
121 next_part.ModFlags |= Modifiers.PARTIAL;
123 if (existing == null) {
124 AddTypeContainer (next_part);
128 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
129 if (existing.Kind != next_part.Kind) {
130 AddTypeContainer (next_part);
132 Report.SymbolRelatedToPreviousError (next_part);
133 Error_MissingPartialModifier (existing);
139 if (existing.Kind != next_part.Kind) {
140 Report.SymbolRelatedToPreviousError (existing);
141 Report.Error (261, next_part.Location,
142 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
143 next_part.GetSignatureForError ());
146 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
147 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
148 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
149 Report.SymbolRelatedToPreviousError (existing);
150 Report.Error (262, next_part.Location,
151 "Partial declarations of `{0}' have conflicting accessibility modifiers",
152 next_part.GetSignatureForError ());
155 var tc_names = existing.CurrentTypeParameters;
156 if (tc_names != null) {
157 for (int i = 0; i < tc_names.Count; ++i) {
158 var tp = next_part.MemberName.TypeParameters[i];
159 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
160 Report.SymbolRelatedToPreviousError (existing.Location, "");
161 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
162 next_part.GetSignatureForError ());
166 if (tc_names[i].Variance != tp.Variance) {
167 Report.SymbolRelatedToPreviousError (existing.Location, "");
168 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
169 next_part.GetSignatureForError ());
175 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
176 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
177 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
178 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
179 existing.ModFlags |= next_part.ModFlags;
181 existing.ModFlags |= next_part.ModFlags;
184 existing.Definition.Modifiers = existing.ModFlags;
186 if (next_part.attributes != null) {
187 if (existing.attributes == null)
188 existing.attributes = next_part.attributes;
190 existing.attributes.AddAttributes (next_part.attributes.Attrs);
193 next_part.PartialContainer = existing;
195 existing.AddPartialPart (next_part);
197 AddTypeContainerMember (next_part);
200 public virtual void AddTypeContainer (TypeContainer tc)
202 AddTypeContainerMember (tc);
204 var tparams = tc.MemberName.TypeParameters;
205 if (tparams != null && tc.PartialContainer != null) {
206 var td = (TypeDefinition) tc;
207 for (int i = 0; i < tparams.Count; ++i) {
209 if (tp.MemberName == null)
212 td.AddNameToContainer (tp, tp.Name);
217 protected virtual void AddTypeContainerMember (TypeContainer tc)
222 public virtual void CloseContainer ()
224 if (containers != null) {
225 foreach (TypeContainer tc in containers) {
226 tc.CloseContainer ();
231 public virtual void CreateMetadataName (StringBuilder sb)
233 if (Parent != null && Parent.MemberName != null)
234 Parent.CreateMetadataName (sb);
236 MemberName.CreateMetadataName (sb);
239 public virtual bool CreateContainer ()
241 if (containers != null) {
242 foreach (TypeContainer tc in containers) {
243 tc.CreateContainer ();
250 public override bool Define ()
252 if (containers != null) {
253 foreach (TypeContainer tc in containers) {
258 // Release cache used by parser only
259 if (Module.Evaluator == null) {
260 defined_names = null;
262 defined_names.Clear ();
268 public virtual void PrepareEmit ()
270 if (containers != null) {
271 foreach (var t in containers) {
274 } catch (Exception e) {
275 if (MemberName == MemberName.Null)
278 throw new InternalErrorException (t, e);
284 public virtual bool DefineContainer ()
291 DoDefineContainer ();
293 if (containers != null) {
294 foreach (TypeContainer tc in containers) {
296 tc.DefineContainer ();
297 } catch (Exception e) {
298 if (MemberName == MemberName.Null)
301 throw new InternalErrorException (tc, e);
309 public virtual void ExpandBaseInterfaces ()
311 if (containers != null) {
312 foreach (TypeContainer tc in containers) {
313 tc.ExpandBaseInterfaces ();
318 protected virtual void DefineNamespace ()
320 if (containers != null) {
321 foreach (var tc in containers) {
323 tc.DefineNamespace ();
324 } catch (Exception e) {
325 throw new InternalErrorException (tc, e);
331 protected virtual void DoDefineContainer ()
335 public virtual void EmitContainer ()
337 if (containers != null) {
338 for (int i = 0; i < containers.Count; ++i)
339 containers[i].EmitContainer ();
343 protected void Error_MissingPartialModifier (MemberCore type)
345 Report.Error (260, type.Location,
346 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
347 type.GetSignatureForError ());
350 public override string GetSignatureForDocumentation ()
352 if (Parent != null && Parent.MemberName != null)
353 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
355 return MemberName.GetSignatureForDocumentation ();
358 public override string GetSignatureForError ()
360 if (Parent != null && Parent.MemberName != null)
361 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
363 return MemberName.GetSignatureForError ();
366 public string GetSignatureForMetadata ()
368 if (Parent is TypeDefinition) {
369 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (MemberName.Basename);
372 var sb = new StringBuilder ();
373 CreateMetadataName (sb);
374 return sb.ToString ();
377 public virtual void RemoveContainer (TypeContainer cont)
379 if (containers != null)
380 containers.Remove (cont);
382 var tc = Parent == Module ? Module : this;
383 tc.defined_names.Remove (cont.Basename);
386 public virtual void VerifyMembers ()
388 if (containers != null) {
389 foreach (TypeContainer tc in containers)
394 public override void WriteDebugSymbol (MonoSymbolFile file)
396 if (containers != null) {
397 foreach (TypeContainer tc in containers) {
398 tc.WriteDebugSymbol (file);
404 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
407 // Different context is needed when resolving type container base
408 // types. Type names come from the parent scope but type parameter
409 // names from the container scope.
411 public struct BaseContext : IMemberContext
415 public BaseContext (TypeContainer tc)
420 #region IMemberContext Members
422 public CompilerContext Compiler {
423 get { return tc.Compiler; }
426 public TypeSpec CurrentType {
427 get { return tc.PartialContainer.CurrentType; }
430 public TypeParameters CurrentTypeParameters {
431 get { return tc.PartialContainer.CurrentTypeParameters; }
434 public MemberCore CurrentMemberDefinition {
438 public bool IsObsolete {
439 get { return tc.IsObsolete; }
442 public bool IsUnsafe {
443 get { return tc.IsUnsafe; }
446 public bool IsStatic {
447 get { return tc.IsStatic; }
450 public ModuleContainer Module {
451 get { return tc.Module; }
454 public string GetSignatureForError ()
456 return tc.GetSignatureForError ();
459 public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity)
464 public FullNamedExpression LookupNamespaceAlias (string name)
466 return tc.Parent.LookupNamespaceAlias (name);
469 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
472 var tp = CurrentTypeParameters;
474 TypeParameter t = tp.Find (name);
476 return new TypeParameterExpr (t, loc);
480 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
490 GetHashCode = 1 << 1,
491 HasStaticFieldInitializer = 1 << 2
494 readonly List<MemberCore> members;
496 // Holds a list of fields that have initializers
497 protected List<FieldInitializer> initialized_fields;
499 // Holds a list of static fields that have initializers
500 protected List<FieldInitializer> initialized_static_fields;
502 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
504 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
507 // Points to the first non-static field added to the container.
509 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
510 // and the first one's as good as any.
512 protected FieldBase first_nonstatic_field;
515 // This one is computed after we can distinguish interfaces
516 // from classes from the arraylist `type_bases'
518 protected TypeSpec base_type;
519 FullNamedExpression base_type_expr; // TODO: It's temporary variable
520 protected TypeSpec[] iface_exprs;
522 protected List<FullNamedExpression> type_bases;
524 // Partial parts for classes only
525 List<TypeDefinition> class_partial_parts;
527 TypeDefinition InTransit;
529 public TypeBuilder TypeBuilder;
530 GenericTypeParameterBuilder[] all_tp_builders;
532 // All recursive type parameters put together sharing same
533 // TypeParameter instances
535 TypeParameters all_type_parameters;
537 public const string DefaultIndexerName = "Item";
539 bool has_normal_indexers;
541 protected bool requires_delayed_unmanagedtype_check;
543 bool members_defined;
544 bool members_defined_ok;
545 protected bool has_static_constructor;
547 private CachedMethods cached_method;
549 protected TypeSpec spec;
550 TypeSpec current_type;
552 public int DynamicSitesCounter;
553 public int AnonymousMethodsCounter;
554 public int MethodGroupsCounter;
556 static readonly string[] attribute_targets = new string[] { "type" };
559 /// The pending methods that need to be implemented
560 // (interfaces or abstract methods)
562 PendingImplementation pending;
564 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
565 : base (parent, name, attrs, kind)
567 PartialContainer = this;
568 members = new List<MemberCore> ();
573 public List<FullNamedExpression> BaseTypeExpressions {
579 public override TypeSpec CurrentType {
581 if (current_type == null) {
582 if (IsGenericOrParentIsGeneric) {
584 // Switch to inflated version as it's used by all expressions
586 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
587 current_type = spec.MakeGenericType (this, targs);
597 public override TypeParameters CurrentTypeParameters {
599 return PartialContainer.MemberName.TypeParameters;
603 int CurrentTypeParametersStartIndex {
605 int total = all_tp_builders.Length;
606 if (CurrentTypeParameters != null) {
607 return total - CurrentTypeParameters.Count;
613 public virtual AssemblyDefinition DeclaringAssembly {
615 return Module.DeclaringAssembly;
619 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
621 return Module.DeclaringAssembly;
625 public TypeSpec Definition {
631 public bool HasMembersDefined {
633 return members_defined;
637 public bool HasInstanceConstructor {
639 return (caching_flags & Flags.HasInstanceConstructor) != 0;
642 caching_flags |= Flags.HasInstanceConstructor;
646 // Indicated whether container has StructLayout attribute set Explicit
647 public bool HasExplicitLayout {
648 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
649 set { caching_flags |= Flags.HasExplicitLayout; }
652 public bool HasOperators {
654 return (caching_flags & Flags.HasUserOperators) != 0;
657 caching_flags |= Flags.HasUserOperators;
661 public bool HasStructLayout {
662 get { return (caching_flags & Flags.HasStructLayout) != 0; }
663 set { caching_flags |= Flags.HasStructLayout; }
666 public TypeSpec[] Interfaces {
672 public bool IsGenericOrParentIsGeneric {
674 return all_type_parameters != null;
678 public bool IsTopLevel {
680 return !(Parent is TypeDefinition);
684 public bool IsPartial {
686 return (ModFlags & Modifiers.PARTIAL) != 0;
690 bool ITypeDefinition.IsTypeForwarder {
696 bool ITypeDefinition.IsCyclicTypeForwarder {
703 // Returns true for secondary partial containers
707 return PartialContainer != this;
711 public MemberCache MemberCache {
713 return spec.MemberCache;
717 public List<MemberCore> Members {
723 string ITypeDefinition.Namespace {
726 while (p.Kind != MemberKind.Namespace)
729 return p.MemberName == null ? null : p.GetSignatureForError ();
733 public ParametersCompiled PrimaryConstructorParameters { get; set; }
735 public TypeParameters TypeParametersAll {
737 return all_type_parameters;
741 public override string[] ValidAttributeTargets {
743 return attribute_targets;
749 public override void Accept (StructuralVisitor visitor)
751 visitor.Visit (this);
754 public void AddMember (MemberCore symbol)
756 if (symbol.MemberName.ExplicitInterface != null) {
757 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
758 Report.Error (541, symbol.Location,
759 "`{0}': explicit interface declaration can only be declared in a class or struct",
760 symbol.GetSignatureForError ());
764 AddNameToContainer (symbol, symbol.MemberName.Name);
765 members.Add (symbol);
768 public override void AddTypeContainer (TypeContainer tc)
770 AddNameToContainer (tc, tc.Basename);
772 base.AddTypeContainer (tc);
775 protected override void AddTypeContainerMember (TypeContainer tc)
779 if (containers == null)
780 containers = new List<TypeContainer> ();
782 base.AddTypeContainerMember (tc);
786 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
788 public virtual void AddNameToContainer (MemberCore symbol, string name)
790 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
794 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
795 PartialContainer.defined_names.Add (name, symbol);
799 if (symbol.EnableOverloadChecks (mc))
802 InterfaceMemberBase im = mc as InterfaceMemberBase;
803 if (im != null && im.IsExplicitImpl)
806 Report.SymbolRelatedToPreviousError (mc);
807 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
808 Error_MissingPartialModifier (symbol);
812 if (symbol is TypeParameter) {
813 Report.Error (692, symbol.Location,
814 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
815 } else if (symbol is PrimaryConstructorField && mc is TypeParameter) {
816 Report.Error (9003, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
817 symbol.Parent.GetSignatureForError (), symbol.GetSignatureForError ());
819 Report.Error (102, symbol.Location,
820 "The type `{0}' already contains a definition for `{1}'",
821 GetSignatureForError (), name);
827 public void AddConstructor (Constructor c)
829 AddConstructor (c, false);
832 public void AddConstructor (Constructor c, bool isDefault)
834 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
836 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
838 if (is_static && c.ParameterInfo.IsEmpty) {
839 PartialContainer.has_static_constructor = true;
841 PartialContainer.HasInstanceConstructor = true;
847 public bool AddField (FieldBase field)
851 if ((field.ModFlags & Modifiers.STATIC) != 0)
854 var first_field = PartialContainer.first_nonstatic_field;
855 if (first_field == null) {
856 PartialContainer.first_nonstatic_field = field;
860 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
861 Report.SymbolRelatedToPreviousError (first_field.Parent);
862 Report.Warning (282, 3, field.Location,
863 "struct instance field `{0}' found in different declaration from instance field `{1}'",
864 field.GetSignatureForError (), first_field.GetSignatureForError ());
870 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
872 public void AddIndexer (Indexer i)
877 public void AddOperator (Operator op)
879 PartialContainer.HasOperators = true;
883 public void AddPartialPart (TypeDefinition part)
885 if (Kind != MemberKind.Class)
888 if (class_partial_parts == null)
889 class_partial_parts = new List<TypeDefinition> ();
891 class_partial_parts.Add (part);
894 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
896 if (has_normal_indexers && a.Type == pa.DefaultMember) {
897 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
901 if (a.Type == pa.Required) {
902 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
906 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
909 public override AttributeTargets AttributeTargets {
911 throw new NotSupportedException ();
915 public TypeSpec BaseType {
917 return spec.BaseType;
921 protected virtual TypeAttributes TypeAttr {
923 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
927 public int TypeParametersCount {
929 return MemberName.Arity;
933 TypeParameterSpec[] ITypeDefinition.TypeParameters {
935 return PartialContainer.CurrentTypeParameters.Types;
939 public string GetAttributeDefaultMember ()
941 return indexer_name ?? DefaultIndexerName;
944 public bool IsComImport {
946 if (OptAttributes == null)
949 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
953 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
956 PartialContainer.RegisterFieldForInitialization (field, expression);
958 if ((field.ModFlags & Modifiers.STATIC) != 0){
959 if (initialized_static_fields == null) {
960 HasStaticFieldInitializer = true;
961 initialized_static_fields = new List<FieldInitializer> (4);
964 initialized_static_fields.Add (expression);
966 if (initialized_fields == null)
967 initialized_fields = new List<FieldInitializer> (4);
969 initialized_fields.Add (expression);
973 public void ResolveFieldInitializers (BlockContext ec)
975 Debug.Assert (!IsPartialPart);
978 if (initialized_static_fields == null)
981 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
983 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
984 for (i = 0; i < initialized_static_fields.Count; ++i) {
985 FieldInitializer fi = initialized_static_fields [i];
986 ExpressionStatement s = fi.ResolveStatement (ec);
988 s = EmptyExpressionStatement.Instance;
989 } else if (!fi.IsSideEffectFree) {
990 has_complex_initializer = true;
996 for (i = 0; i < initialized_static_fields.Count; ++i) {
997 FieldInitializer fi = initialized_static_fields [i];
999 // Need special check to not optimize code like this
1000 // static int a = b = 5;
1001 // static int b = 0;
1003 if (!has_complex_initializer && fi.IsDefaultInitializer)
1006 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1007 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1013 if (initialized_fields == null)
1016 for (int i = 0; i < initialized_fields.Count; ++i) {
1017 FieldInitializer fi = initialized_fields [i];
1020 // Clone before resolving otherwise when field initializer is needed
1021 // in more than 1 constructor any resolve after the initial one would
1022 // only took the resolved expression which is problem for expressions
1023 // that generate extra expressions or code during Resolve phase
1025 var cloned = fi.Clone (new CloneContext ());
1027 ExpressionStatement s = fi.ResolveStatement (ec);
1029 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1034 // Field is re-initialized to its default value => removed
1036 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
1039 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1040 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1041 initialized_fields [i] = (FieldInitializer) cloned;
1045 public override string DocComment {
1057 public PendingImplementation PendingImplementations {
1058 get { return pending; }
1061 internal override void GenerateDocComment (DocumentationBuilder builder)
1066 base.GenerateDocComment (builder);
1068 foreach (var member in members)
1069 member.GenerateDocComment (builder);
1072 public TypeSpec GetAttributeCoClass ()
1074 if (OptAttributes == null)
1077 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1081 return a.GetCoClassAttributeValue ();
1084 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1087 if (OptAttributes != null) {
1088 a = OptAttributes.Search (pa);
1094 return a.GetAttributeUsageAttribute ();
1097 public virtual CompilationSourceFile GetCompilationSourceFile ()
1099 TypeContainer ns = Parent;
1101 var sf = ns as CompilationSourceFile;
1109 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1111 type_bases = baseTypes;
1115 /// This function computes the Base class and also the
1116 /// list of interfaces that the class or struct @c implements.
1118 /// The return value is an array (might be null) of
1119 /// interfaces implemented (as Types).
1121 /// The @base_class argument is set to the base object or null
1122 /// if this is `System.Object'.
1124 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1127 if (type_bases == null)
1130 int count = type_bases.Count;
1131 TypeSpec[] ifaces = null;
1132 var base_context = new BaseContext (this);
1133 for (int i = 0, j = 0; i < count; i++){
1134 FullNamedExpression fne = type_bases [i];
1136 var fne_resolved = fne.ResolveAsType (base_context);
1137 if (fne_resolved == null)
1140 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1141 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1142 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1143 GetSignatureForError ());
1148 base_type = fne_resolved;
1154 ifaces = new TypeSpec [count - i];
1156 if (fne_resolved.IsInterface) {
1157 for (int ii = 0; ii < j; ++ii) {
1158 if (fne_resolved == ifaces [ii]) {
1159 Report.Error (528, Location, "`{0}' is already listed in interface list",
1160 fne_resolved.GetSignatureForError ());
1165 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1166 Report.Error (61, fne.Location,
1167 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1168 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1171 Report.SymbolRelatedToPreviousError (fne_resolved);
1172 if (Kind != MemberKind.Class) {
1173 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1174 } else if (base_class != null)
1175 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1176 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1178 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1179 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1183 ifaces [j++] = fne_resolved;
1190 // Checks that some operators come in pairs:
1196 // They are matched based on the return type and the argument types
1198 void CheckPairedOperators ()
1200 bool has_equality_or_inequality = false;
1201 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1203 for (int i = 0; i < members.Count; ++i) {
1204 var o_a = members[i] as Operator;
1208 var o_type = o_a.OperatorType;
1209 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1210 has_equality_or_inequality = true;
1212 if (found_matched.Contains (o_type))
1215 var matching_type = o_a.GetMatchingOperator ();
1216 if (matching_type == Operator.OpType.TOP) {
1220 bool pair_found = false;
1221 for (int ii = 0; ii < members.Count; ++ii) {
1222 var o_b = members[ii] as Operator;
1223 if (o_b == null || o_b.OperatorType != matching_type)
1226 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1229 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1232 found_matched.Add (matching_type);
1238 Report.Error (216, o_a.Location,
1239 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1240 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1244 if (has_equality_or_inequality) {
1246 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1247 GetSignatureForError ());
1249 if (!HasGetHashCode)
1250 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1251 GetSignatureForError ());
1255 public override void CreateMetadataName (StringBuilder sb)
1257 if (Parent.MemberName != null) {
1258 Parent.CreateMetadataName (sb);
1260 if (sb.Length != 0) {
1265 sb.Append (MemberName.Basename);
1268 bool CreateTypeBuilder ()
1271 // Sets .size to 1 for structs with no instance fields
1273 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1275 var parent_def = Parent as TypeDefinition;
1276 if (parent_def == null) {
1277 var sb = new StringBuilder ();
1278 CreateMetadataName (sb);
1279 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1281 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1284 if (DeclaringAssembly.Importer != null)
1285 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1287 spec.SetMetaInfo (TypeBuilder);
1288 spec.MemberCache = new MemberCache (this);
1290 TypeParameters parentAllTypeParameters = null;
1291 if (parent_def != null) {
1292 spec.DeclaringType = Parent.CurrentType;
1293 parent_def.MemberCache.AddMember (spec);
1294 parentAllTypeParameters = parent_def.all_type_parameters;
1297 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1298 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1300 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1302 if (CurrentTypeParameters != null) {
1303 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1304 CurrentTypeParameters.Define (all_tp_builders);
1311 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1314 int parent_offset = 0;
1315 if (parentAllTypeParameters != null) {
1316 if (CurrentTypeParameters == null) {
1317 all_type_parameters = parentAllTypeParameters;
1318 return parentAllTypeParameters.GetAllNames ();
1321 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1322 all_type_parameters = new TypeParameters (names.Length);
1323 all_type_parameters.Add (parentAllTypeParameters);
1325 parent_offset = all_type_parameters.Count;
1326 for (int i = 0; i < parent_offset; ++i)
1327 names[i] = all_type_parameters[i].MemberName.Name;
1330 names = new string[CurrentTypeParameters.Count];
1333 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1334 if (all_type_parameters != null)
1335 all_type_parameters.Add (MemberName.TypeParameters[i]);
1337 var name = CurrentTypeParameters[i].MemberName.Name;
1338 names[parent_offset + i] = name;
1339 for (int ii = 0; ii < parent_offset + i; ++ii) {
1340 if (names[ii] != name)
1343 var tp = CurrentTypeParameters[i];
1344 var conflict = all_type_parameters[ii];
1346 tp.WarningParentNameConflict (conflict);
1350 if (all_type_parameters == null)
1351 all_type_parameters = CurrentTypeParameters;
1357 public SourceMethodBuilder CreateMethodSymbolEntry ()
1359 if (Module.DeclaringAssembly.SymbolWriter == null)
1362 var source_file = GetCompilationSourceFile ();
1363 if (source_file == null)
1366 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1370 // Creates a proxy base method call inside this container for hoisted base member calls
1372 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1374 Method proxy_method;
1377 // One proxy per base method is enough
1379 if (hoisted_base_call_proxies == null) {
1380 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1381 proxy_method = null;
1383 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1386 if (proxy_method == null) {
1387 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1389 MemberName member_name;
1390 TypeArguments targs = null;
1391 TypeSpec return_type = method.ReturnType;
1392 var local_param_types = method.Parameters.Types;
1394 if (method.IsGeneric) {
1396 // Copy all base generic method type parameters info
1398 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1399 var tparams = new TypeParameters ();
1401 targs = new TypeArguments ();
1402 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1403 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1404 var tp = hoisted_tparams[i];
1405 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1406 tparams.Add (local_tp);
1408 targs.Add (new SimpleName (tp.Name, Location));
1409 targs.Arguments[i] = local_tp.Type;
1412 member_name = new MemberName (name, tparams, Location);
1415 // Mutate any method type parameters from original
1416 // to newly created hoisted version
1418 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1419 return_type = mutator.Mutate (return_type);
1420 local_param_types = mutator.Mutate (local_param_types);
1422 member_name = new MemberName (name);
1425 var base_parameters = new Parameter[method.Parameters.Count];
1426 for (int i = 0; i < base_parameters.Length; ++i) {
1427 var base_param = method.Parameters.FixedParameters[i];
1428 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1429 base_param.Name, base_param.ModFlags, null, Location);
1430 base_parameters[i].Resolve (this, i);
1433 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1434 if (method.Parameters.HasArglist) {
1435 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1436 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1439 // Compiler generated proxy
1440 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1441 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1442 member_name, cloned_params, null);
1444 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1445 IsCompilerGenerated = true
1448 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1449 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1451 mg.SetTypeArguments (rc, targs);
1453 // Get all the method parameters and pass them as arguments
1454 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1455 Statement statement;
1456 if (method.ReturnType.Kind == MemberKind.Void)
1457 statement = new StatementExpression (real_base_call);
1459 statement = new Return (real_base_call, Location);
1461 block.AddStatement (statement);
1462 proxy_method.Block = block;
1464 members.Add (proxy_method);
1465 proxy_method.Define ();
1466 proxy_method.PrepareEmit ();
1468 hoisted_base_call_proxies.Add (method, proxy_method);
1471 return proxy_method.Spec;
1474 protected bool DefineBaseTypes ()
1476 if (IsPartialPart && Kind == MemberKind.Class)
1479 return DoDefineBaseType ();
1482 bool DoDefineBaseType ()
1484 iface_exprs = ResolveBaseTypes (out base_type_expr);
1487 if (IsPartialPart) {
1488 set_base_type = false;
1490 if (base_type_expr != null) {
1491 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1492 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1493 Report.Error (263, Location,
1494 "Partial declarations of `{0}' must not specify different base classes",
1495 GetSignatureForError ());
1497 PartialContainer.base_type_expr = base_type_expr;
1498 PartialContainer.base_type = base_type;
1499 set_base_type = true;
1503 if (iface_exprs != null) {
1504 if (PartialContainer.iface_exprs == null)
1505 PartialContainer.iface_exprs = iface_exprs;
1507 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1508 foreach (var iface_partial in iface_exprs) {
1509 if (ifaces.Contains (iface_partial))
1512 ifaces.Add (iface_partial);
1515 PartialContainer.iface_exprs = ifaces.ToArray ();
1519 PartialContainer.members.AddRange (members);
1520 if (containers != null) {
1521 if (PartialContainer.containers == null)
1522 PartialContainer.containers = new List<TypeContainer> ();
1524 PartialContainer.containers.AddRange (containers);
1527 if (PrimaryConstructorParameters != null) {
1528 if (PartialContainer.PrimaryConstructorParameters != null) {
1529 Report.Error (9001, Location, "Only one part of a partial type can declare primary constructor parameters");
1531 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1535 members_defined = members_defined_ok = true;
1536 caching_flags |= Flags.CloseTypeCreated;
1538 set_base_type = true;
1541 var cycle = CheckRecursiveDefinition (this);
1542 if (cycle != null) {
1543 Report.SymbolRelatedToPreviousError (cycle);
1544 if (this is Interface) {
1545 Report.Error (529, Location,
1546 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1547 GetSignatureForError (), cycle.GetSignatureForError ());
1550 PartialContainer.iface_exprs = null;
1552 Report.Error (146, Location,
1553 "Circular base class dependency involving `{0}' and `{1}'",
1554 GetSignatureForError (), cycle.GetSignatureForError ());
1557 PartialContainer.base_type = null;
1561 if (iface_exprs != null) {
1562 foreach (var iface_type in iface_exprs) {
1563 // Prevents a crash, the interface might not have been resolved: 442144
1564 if (iface_type == null)
1567 if (!spec.AddInterfaceDefined (iface_type))
1570 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1574 if (Kind == MemberKind.Interface) {
1575 spec.BaseType = Compiler.BuiltinTypes.Object;
1579 if (set_base_type) {
1584 // Base type of partial container has to be resolved before we
1585 // resolve any nested types of the container. We need to know
1586 // partial parts because the base type can be specified in file
1587 // defined after current container
1589 if (class_partial_parts != null) {
1590 foreach (var pp in class_partial_parts)
1591 pp.DoDefineBaseType ();
1600 if (base_type == null) {
1601 TypeBuilder.SetParent (null);
1605 if (spec.BaseType == base_type)
1608 spec.BaseType = base_type;
1611 spec.UpdateInflatedInstancesBaseType ();
1613 // Set base type after type creation
1614 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1617 public override void ExpandBaseInterfaces ()
1620 DoExpandBaseInterfaces ();
1622 base.ExpandBaseInterfaces ();
1625 public void DoExpandBaseInterfaces ()
1627 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1630 caching_flags |= Flags.InterfacesExpanded;
1633 // Expand base interfaces. It cannot be done earlier because all partial
1634 // interface parts need to be defined before the type they are used from
1636 if (iface_exprs != null) {
1637 foreach (var iface in iface_exprs) {
1641 var td = iface.MemberDefinition as TypeDefinition;
1643 td.DoExpandBaseInterfaces ();
1645 if (iface.Interfaces == null)
1648 foreach (var biface in iface.Interfaces) {
1649 if (spec.AddInterfaceDefined (biface)) {
1650 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1657 // Include all base type interfaces too, see ImportTypeBase for details
1659 if (base_type != null) {
1660 var td = base_type.MemberDefinition as TypeDefinition;
1662 td.DoExpandBaseInterfaces ();
1665 // Simply use base interfaces only, they are all expanded which makes
1666 // it easy to handle generic type argument propagation with single
1669 // interface IA<T> : IB<T>
1670 // interface IB<U> : IC<U>
1673 if (base_type.Interfaces != null) {
1674 foreach (var iface in base_type.Interfaces) {
1675 spec.AddInterfaceDefined (iface);
1681 public override void PrepareEmit ()
1683 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1686 foreach (var member in members) {
1687 var pbm = member as PropertyBasedMember;
1691 var pm = member as IParametersMember;
1693 var mc = member as MethodOrOperator;
1698 var p = pm.Parameters;
1702 ((ParametersCompiled) p).ResolveDefaultValues (member);
1706 var c = member as Const;
1711 base.PrepareEmit ();
1715 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1717 public override bool CreateContainer ()
1719 if (TypeBuilder != null)
1725 if (IsPartialPart) {
1726 spec = PartialContainer.spec;
1727 TypeBuilder = PartialContainer.TypeBuilder;
1728 all_tp_builders = PartialContainer.all_tp_builders;
1729 all_type_parameters = PartialContainer.all_type_parameters;
1731 if (!CreateTypeBuilder ()) {
1737 return base.CreateContainer ();
1740 protected override void DoDefineContainer ()
1744 DoResolveTypeParameters ();
1748 // Replaces normal spec with predefined one when compiling corlib
1749 // and this type container defines predefined type
1751 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1753 // When compiling build-in types we start with two
1754 // version of same type. One is of BuiltinTypeSpec and
1755 // second one is ordinary TypeSpec. The unification
1756 // happens at later stage when we know which type
1757 // really matches the builtin type signature. However
1758 // that means TypeSpec create during CreateType of this
1759 // type has to be replaced with builtin one
1761 spec.SetMetaInfo (TypeBuilder);
1762 spec.MemberCache = this.spec.MemberCache;
1763 spec.DeclaringType = this.spec.DeclaringType;
1766 current_type = null;
1769 public override void RemoveContainer (TypeContainer cont)
1771 base.RemoveContainer (cont);
1772 Members.Remove (cont);
1773 Cache.Remove (cont.Basename);
1776 protected virtual bool DoResolveTypeParameters ()
1778 var tparams = CurrentTypeParameters;
1779 if (tparams == null)
1782 var base_context = new BaseContext (this);
1783 for (int i = 0; i < tparams.Count; ++i) {
1784 var tp = tparams[i];
1786 if (!tp.ResolveConstraints (base_context)) {
1792 if (IsPartialPart) {
1793 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1799 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1801 if (InTransit != null)
1806 if (base_type != null) {
1807 var ptc = base_type.MemberDefinition as TypeDefinition;
1808 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1812 if (iface_exprs != null) {
1813 foreach (var iface in iface_exprs) {
1814 // the interface might not have been resolved, prevents a crash, see #442144
1817 var ptc = iface.MemberDefinition as Interface;
1818 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1823 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1831 /// Populates our TypeBuilder with fields and methods
1833 public sealed override bool Define ()
1835 if (members_defined)
1836 return members_defined_ok;
1838 members_defined_ok = DoDefineMembers ();
1839 members_defined = true;
1843 return members_defined_ok;
1846 protected virtual bool DoDefineMembers ()
1848 Debug.Assert (!IsPartialPart);
1850 if (iface_exprs != null) {
1851 foreach (var iface_type in iface_exprs) {
1852 if (iface_type == null)
1855 // Ensure the base is always setup
1856 var compiled_iface = iface_type.MemberDefinition as Interface;
1857 if (compiled_iface != null)
1858 compiled_iface.Define ();
1860 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1861 if (oa != null && !IsObsolete)
1862 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1864 if (iface_type.Arity > 0) {
1865 // TODO: passing `this' is wrong, should be base type iface instead
1866 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1868 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1869 Report.Error (1966, Location,
1870 "`{0}': cannot implement a dynamic interface `{1}'",
1871 GetSignatureForError (), iface_type.GetSignatureForError ());
1876 if (iface_type.IsGenericOrParentIsGeneric) {
1877 foreach (var prev_iface in iface_exprs) {
1878 if (prev_iface == iface_type || prev_iface == null)
1881 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1884 Report.Error (695, Location,
1885 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1886 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1891 if (Kind == MemberKind.Interface) {
1892 foreach (var iface in spec.Interfaces) {
1893 MemberCache.AddInterface (iface);
1898 if (base_type != null) {
1900 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1902 if (base_type_expr != null) {
1903 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1904 if (obsolete_attr != null && !IsObsolete)
1905 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1907 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1908 Report.Error (698, base_type_expr.Location,
1909 "A generic type cannot derive from `{0}' because it is an attribute class",
1910 base_type.GetSignatureForError ());
1914 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1915 if (baseContainer != null) {
1916 baseContainer.Define ();
1919 // It can trigger define of this type (for generic types only)
1921 if (HasMembersDefined)
1926 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1927 pending = PendingImplementation.GetPendingImplementations (this);
1930 var count = members.Count;
1931 for (int i = 0; i < count; ++i) {
1932 var mc = members[i] as InterfaceMemberBase;
1933 if (mc == null || !mc.IsExplicitImpl)
1938 } catch (Exception e) {
1939 throw new InternalErrorException (mc, e);
1943 for (int i = 0; i < count; ++i) {
1944 var mc = members[i] as InterfaceMemberBase;
1945 if (mc != null && mc.IsExplicitImpl)
1948 if (members[i] is TypeContainer)
1952 members[i].Define ();
1953 } catch (Exception e) {
1954 throw new InternalErrorException (members[i], e);
1959 CheckPairedOperators ();
1962 if (requires_delayed_unmanagedtype_check) {
1963 requires_delayed_unmanagedtype_check = false;
1964 foreach (var member in members) {
1965 var f = member as Field;
1966 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
1967 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
1971 ComputeIndexerName();
1973 if (HasEquals && !HasGetHashCode) {
1974 Report.Warning (659, 3, Location,
1975 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
1978 if (Kind == MemberKind.Interface && iface_exprs != null) {
1979 MemberCache.RemoveHiddenMembers (spec);
1985 void ComputeIndexerName ()
1987 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
1988 if (indexers == null)
1991 string class_indexer_name = null;
1994 // Check normal indexers for consistent name, explicit interface implementation
1995 // indexers are ignored
1997 foreach (var indexer in indexers) {
1999 // FindMembers can return unfiltered full hierarchy names
2001 if (indexer.DeclaringType != spec)
2004 has_normal_indexers = true;
2006 if (class_indexer_name == null) {
2007 indexer_name = class_indexer_name = indexer.Name;
2011 if (indexer.Name != class_indexer_name)
2012 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2013 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2017 void EmitIndexerName ()
2019 if (!has_normal_indexers)
2022 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2026 var encoder = new AttributeEncoder ();
2027 encoder.Encode (GetAttributeDefaultMember ());
2028 encoder.EncodeEmptyNamedArguments ();
2030 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2033 public override void VerifyMembers ()
2036 // Check for internal or private fields that were never assigned
2038 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2039 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2040 foreach (var member in members) {
2041 if (member is Event) {
2043 // An event can be assigned from same class only, report
2044 // this warning for all accessibility modes
2046 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2047 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2052 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2053 if (is_type_exposed)
2056 member.SetIsUsed ();
2059 var f = member as Field;
2063 if (!member.IsUsed) {
2064 if (!PartialContainer.HasStructLayout) {
2065 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2066 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2068 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2069 member.GetSignatureForError ());
2076 if ((f.caching_flags & Flags.IsAssigned) != 0)
2080 // Only report 649 on level 4
2082 if (Compiler.Settings.WarningLevel < 4)
2086 // Don't be pedantic when type requires specific layout
2088 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2091 Constant c = New.Constantify (f.MemberType, f.Location);
2094 value = c.GetValueAsLiteral ();
2095 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2102 value = " `" + value + "'";
2104 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2105 f.GetSignatureForError (), value);
2109 base.VerifyMembers ();
2112 public override void Emit ()
2114 if (OptAttributes != null)
2115 OptAttributes.Emit ();
2117 if (!IsCompilerGenerated) {
2119 MemberSpec candidate;
2120 bool overrides = false;
2121 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2122 if (conflict_symbol == null && candidate == null) {
2123 if ((ModFlags & Modifiers.NEW) != 0)
2124 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2125 GetSignatureForError ());
2127 if ((ModFlags & Modifiers.NEW) == 0) {
2128 if (candidate == null)
2129 candidate = conflict_symbol;
2131 Report.SymbolRelatedToPreviousError (candidate);
2132 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2133 GetSignatureForError (), candidate.GetSignatureForError ());
2138 // Run constraints check on all possible generic types
2139 if (base_type != null && base_type_expr != null) {
2140 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2143 if (iface_exprs != null) {
2144 foreach (var iface_type in iface_exprs) {
2145 if (iface_type == null)
2148 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2153 if (all_tp_builders != null) {
2154 int current_starts_index = CurrentTypeParametersStartIndex;
2155 for (int i = 0; i < all_tp_builders.Length; i++) {
2156 if (i < current_starts_index) {
2157 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2159 var tp = CurrentTypeParameters [i - current_starts_index];
2160 tp.CheckGenericConstraints (!IsObsolete);
2166 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2167 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2170 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2171 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2176 for (int i = 0; i < members.Count; i++) {
2178 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2185 CheckAttributeClsCompliance ();
2187 if (pending != null)
2188 pending.VerifyPendingMethods ();
2192 void CheckAttributeClsCompliance ()
2194 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2197 foreach (var m in members) {
2198 var c = m as Constructor;
2202 if (c.HasCompliantArgs)
2206 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2209 public sealed override void EmitContainer ()
2211 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2217 public override void CloseContainer ()
2219 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2222 // Close base type container first to avoid TypeLoadException
2223 if (spec.BaseType != null) {
2224 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2225 if (btype != null) {
2226 btype.CloseContainer ();
2228 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2234 caching_flags |= Flags.CloseTypeCreated;
2235 TypeBuilder.CreateType ();
2236 } catch (TypeLoadException) {
2238 // This is fine, the code still created the type
2240 } catch (Exception e) {
2241 throw new InternalErrorException (this, e);
2244 base.CloseContainer ();
2247 initialized_fields = null;
2248 initialized_static_fields = null;
2250 OptAttributes = null;
2254 // Performs the validation on a Method's modifiers (properties have
2255 // the same properties).
2257 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2259 public bool MethodModifiersValid (MemberCore mc)
2261 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2262 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2264 var flags = mc.ModFlags;
2267 // At most one of static, virtual or override
2269 if ((flags & Modifiers.STATIC) != 0){
2270 if ((flags & vao) != 0){
2271 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2272 mc.GetSignatureForError ());
2277 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2278 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2279 mc.GetSignatureForError ());
2284 // If the declaration includes the abstract modifier, then the
2285 // declaration does not include static, virtual or extern
2287 if ((flags & Modifiers.ABSTRACT) != 0){
2288 if ((flags & Modifiers.EXTERN) != 0){
2290 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2294 if ((flags & Modifiers.SEALED) != 0) {
2295 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2299 if ((flags & Modifiers.VIRTUAL) != 0){
2300 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2304 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2305 Report.SymbolRelatedToPreviousError (this);
2306 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2307 mc.GetSignatureForError (), GetSignatureForError ());
2312 if ((flags & Modifiers.PRIVATE) != 0){
2313 if ((flags & vao) != 0){
2314 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2319 if ((flags & Modifiers.SEALED) != 0){
2320 if ((flags & Modifiers.OVERRIDE) == 0){
2321 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2329 protected override bool VerifyClsCompliance ()
2331 if (!base.VerifyClsCompliance ())
2334 // Check all container names for user classes
2335 if (Kind != MemberKind.Delegate)
2336 MemberCache.VerifyClsCompliance (Definition, Report);
2338 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2339 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2340 GetSignatureForError (), BaseType.GetSignatureForError ());
2346 /// Performs checks for an explicit interface implementation. First it
2347 /// checks whether the `interface_type' is a base inteface implementation.
2348 /// Then it checks whether `name' exists in the interface type.
2350 public bool VerifyImplements (InterfaceMemberBase mb)
2352 var ifaces = PartialContainer.Interfaces;
2353 if (ifaces != null) {
2354 foreach (TypeSpec t in ifaces){
2355 if (t == mb.InterfaceType)
2358 var expanded_base = t.Interfaces;
2359 if (expanded_base == null)
2362 foreach (var bt in expanded_base) {
2363 if (bt == mb.InterfaceType)
2369 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2370 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2371 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2376 // Used for visiblity checks to tests whether this definition shares
2377 // base type baseType, it does member-definition search
2379 public bool IsBaseTypeDefinition (TypeSpec baseType)
2381 // RootContext check
2382 if (TypeBuilder == null)
2387 if (type.MemberDefinition == baseType.MemberDefinition)
2390 type = type.BaseType;
2391 } while (type != null);
2396 public override bool IsClsComplianceRequired ()
2399 return PartialContainer.IsClsComplianceRequired ();
2401 return base.IsClsComplianceRequired ();
2404 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2406 return Module.DeclaringAssembly == assembly;
2409 public virtual bool IsUnmanagedType ()
2414 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2416 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2420 // Public function used to locate types.
2422 // Returns: Type or null if they type can not be found.
2424 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2426 FullNamedExpression e;
2427 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2433 var tp = CurrentTypeParameters;
2435 TypeParameter tparam = tp.Find (name);
2437 e = new TypeParameterExpr (tparam, Location.Null);
2442 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2444 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2445 e = new TypeExpression (t, Location.Null);
2447 var errors = Compiler.Report.Errors;
2448 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2450 // TODO: LookupNamespaceOrType does more than just lookup. The result
2451 // cannot be cached or the error reporting won't happen
2452 if (errors != Compiler.Report.Errors)
2457 // TODO MemberCache: How to cache arity stuff ?
2458 if (arity == 0 && mode == LookupMode.Normal)
2464 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2466 // Has any nested type
2467 // Does not work, because base type can have
2468 //if (PartialContainer.Types == null)
2471 var container = PartialContainer.CurrentType;
2472 return MemberCache.FindNestedType (container, name, arity);
2475 public void Mark_HasEquals ()
2477 cached_method |= CachedMethods.Equals;
2480 public void Mark_HasGetHashCode ()
2482 cached_method |= CachedMethods.GetHashCode;
2485 public override void WriteDebugSymbol (MonoSymbolFile file)
2490 foreach (var m in members) {
2491 m.WriteDebugSymbol (file);
2496 /// Method container contains Equals method
2498 public bool HasEquals {
2500 return (cached_method & CachedMethods.Equals) != 0;
2505 /// Method container contains GetHashCode method
2507 public bool HasGetHashCode {
2509 return (cached_method & CachedMethods.GetHashCode) != 0;
2513 public bool HasStaticFieldInitializer {
2515 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2519 cached_method |= CachedMethods.HasStaticFieldInitializer;
2521 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2525 public override string DocCommentHeader {
2526 get { return "T:"; }
2530 public abstract class ClassOrStruct : TypeDefinition
2532 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2534 SecurityType declarative_security;
2535 protected Constructor generated_primary_constructor;
2537 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2538 : base (parent, name, attrs, kind)
2542 public Arguments PrimaryConstructorBaseArguments { get; set; }
2544 protected override TypeAttributes TypeAttr {
2546 TypeAttributes ta = base.TypeAttr;
2547 if (!has_static_constructor)
2548 ta |= TypeAttributes.BeforeFieldInit;
2550 if (Kind == MemberKind.Class) {
2551 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2553 ta |= StaticClassAttribute;
2555 ta |= TypeAttributes.SequentialLayout;
2562 public override void AddNameToContainer (MemberCore symbol, string name)
2564 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2565 if (symbol is TypeParameter) {
2566 Report.Error (694, symbol.Location,
2567 "Type parameter `{0}' has same name as containing type, or method",
2568 symbol.GetSignatureForError ());
2572 if (symbol is PrimaryConstructorField) {
2573 Report.Error (9004, symbol.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2574 symbol.Parent.GetSignatureForError ());
2578 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2579 if (imb == null || !imb.IsExplicitImpl) {
2580 Report.SymbolRelatedToPreviousError (this);
2581 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2582 symbol.GetSignatureForError ());
2587 base.AddNameToContainer (symbol, name);
2590 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2592 if (a.IsValidSecurityAttribute ()) {
2593 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2597 if (a.Type == pa.StructLayout) {
2598 PartialContainer.HasStructLayout = true;
2599 if (a.IsExplicitLayoutKind ())
2600 PartialContainer.HasExplicitLayout = true;
2603 if (a.Type == pa.Dynamic) {
2604 a.Error_MisusedDynamicAttribute ();
2608 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2612 /// Defines the default constructors
2614 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2616 // The default instance constructor is public
2617 // If the class is abstract, the default constructor is protected
2618 // The default static constructor is private
2622 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2624 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2627 var c = new Constructor (this, MemberName.Name, mods, null, PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters, Location);
2628 if (Kind == MemberKind.Class)
2629 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2631 if (PrimaryConstructorParameters != null)
2632 c.IsPrimaryConstructor = true;
2634 AddConstructor (c, true);
2635 c.Block = new ToplevelBlock (Compiler, c.ParameterInfo, Location) {
2636 IsCompilerGenerated = true
2642 protected override bool DoDefineMembers ()
2644 CheckProtectedModifier ();
2646 if (PrimaryConstructorParameters != null) {
2647 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2648 if ((p.ModFlags & Parameter.Modifier.RefOutMask) != 0)
2651 var f = new PrimaryConstructorField (this, p);
2654 generated_primary_constructor.Block.AddStatement (
2655 new StatementExpression (new PrimaryConstructorAssign (f, p), p.Location));
2659 base.DoDefineMembers ();
2664 public override void Emit ()
2666 if (!has_static_constructor && HasStaticFieldInitializer) {
2667 var c = DefineDefaultConstructor (true);
2673 if (declarative_security != null) {
2674 foreach (var de in declarative_security) {
2676 TypeBuilder.__AddDeclarativeSecurity (de);
2678 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2686 public sealed class Class : ClassOrStruct
2688 const Modifiers AllowedModifiers =
2691 Modifiers.PROTECTED |
2692 Modifiers.INTERNAL |
2694 Modifiers.ABSTRACT |
2699 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2700 : base (parent, name, attrs, MemberKind.Class)
2702 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2703 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2704 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2707 public override void Accept (StructuralVisitor visitor)
2709 visitor.Visit (this);
2712 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2714 var pmn = MemberName;
2715 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2716 Report.Error (537, Location,
2717 "The class System.Object cannot have a base class or implement an interface.");
2719 base.SetBaseTypes (baseTypes);
2722 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2724 if (a.Type == pa.AttributeUsage) {
2725 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2726 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2730 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2731 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2735 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2736 a.Error_MissingGuidAttribute ();
2740 if (a.Type == pa.Extension) {
2741 a.Error_MisusedExtensionAttribute ();
2745 if (a.Type.IsConditionallyExcluded (this))
2748 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2751 public override AttributeTargets AttributeTargets {
2753 return AttributeTargets.Class;
2757 protected override bool DoDefineMembers ()
2759 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2760 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2763 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2764 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2768 if (PrimaryConstructorParameters != null) {
2769 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2770 PrimaryConstructorParameters = null;
2773 foreach (var m in Members) {
2774 if (m is Operator) {
2775 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2779 if (m is Destructor) {
2780 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2785 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2789 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2792 if (m is Constructor) {
2793 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2797 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2800 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2801 generated_primary_constructor = DefineDefaultConstructor (false);
2804 return base.DoDefineMembers ();
2807 public override void Emit ()
2811 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2812 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2814 if (base_type != null && base_type.HasDynamicElement) {
2815 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2819 public override void GetCompletionStartingWith (string prefix, List<string> results)
2821 base.GetCompletionStartingWith (prefix, results);
2824 while (bt != null) {
2825 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2830 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2832 var ifaces = base.ResolveBaseTypes (out base_class);
2834 if (base_class == null) {
2835 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2836 base_type = Compiler.BuiltinTypes.Object;
2838 if (base_type.IsGenericParameter){
2839 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2840 GetSignatureForError (), base_type.GetSignatureForError ());
2841 } else if (base_type.IsStatic) {
2842 Report.SymbolRelatedToPreviousError (base_type);
2843 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2844 GetSignatureForError (), base_type.GetSignatureForError ());
2845 } else if (base_type.IsSealed) {
2846 Report.SymbolRelatedToPreviousError (base_type);
2847 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2848 GetSignatureForError (), base_type.GetSignatureForError ());
2849 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2850 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2851 GetSignatureForError (), base_type.GetSignatureForError ());
2854 switch (base_type.BuiltinType) {
2855 case BuiltinTypeSpec.Type.Enum:
2856 case BuiltinTypeSpec.Type.ValueType:
2857 case BuiltinTypeSpec.Type.MulticastDelegate:
2858 case BuiltinTypeSpec.Type.Delegate:
2859 case BuiltinTypeSpec.Type.Array:
2860 if (!(spec is BuiltinTypeSpec)) {
2861 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2862 GetSignatureForError (), base_type.GetSignatureForError ());
2864 base_type = Compiler.BuiltinTypes.Object;
2869 if (!IsAccessibleAs (base_type)) {
2870 Report.SymbolRelatedToPreviousError (base_type);
2871 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2872 base_type.GetSignatureForError (), GetSignatureForError ());
2876 if (PartialContainer.IsStatic && ifaces != null) {
2877 foreach (var t in ifaces)
2878 Report.SymbolRelatedToPreviousError (t);
2879 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2885 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2886 /// Valid only for attribute classes.
2887 public override string[] ConditionalConditions ()
2889 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2892 caching_flags &= ~Flags.Excluded_Undetected;
2894 if (OptAttributes == null)
2897 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2901 string[] conditions = new string[attrs.Length];
2902 for (int i = 0; i < conditions.Length; ++i)
2903 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2905 caching_flags |= Flags.Excluded;
2910 public sealed class Struct : ClassOrStruct
2912 bool is_unmanaged, has_unmanaged_check_done;
2916 // Modifiers allowed in a struct declaration
2918 const Modifiers AllowedModifiers =
2921 Modifiers.PROTECTED |
2922 Modifiers.INTERNAL |
2926 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2927 : base (parent, name, attrs, MemberKind.Struct)
2929 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2930 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2931 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2934 public override AttributeTargets AttributeTargets {
2936 return AttributeTargets.Struct;
2940 public override void Accept (StructuralVisitor visitor)
2942 visitor.Visit (this);
2945 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2947 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2950 // When struct constains fixed fixed and struct layout has explicitly
2951 // set CharSet, its value has to be propagated to compiler generated
2954 if (a.Type == pa.StructLayout) {
2955 var value = a.GetNamedValue ("CharSet");
2959 for (int i = 0; i < Members.Count; ++i) {
2960 FixedField ff = Members [i] as FixedField;
2964 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
2969 bool CheckStructCycles ()
2975 foreach (var member in Members) {
2976 var field = member as Field;
2980 TypeSpec ftype = field.Spec.MemberType;
2981 if (!ftype.IsStruct)
2984 if (ftype is BuiltinTypeSpec)
2987 foreach (var targ in ftype.TypeArguments) {
2988 if (!CheckFieldTypeCycle (targ)) {
2989 Report.Error (523, field.Location,
2990 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
2991 field.GetSignatureForError (), ftype.GetSignatureForError ());
2997 // Static fields of exactly same type are allowed
2999 if (field.IsStatic && ftype == CurrentType)
3002 if (!CheckFieldTypeCycle (ftype)) {
3003 Report.Error (523, field.Location,
3004 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3005 field.GetSignatureForError (), ftype.GetSignatureForError ());
3014 static bool CheckFieldTypeCycle (TypeSpec ts)
3016 var fts = ts.MemberDefinition as Struct;
3020 return fts.CheckStructCycles ();
3023 protected override bool DoDefineMembers ()
3025 if (PrimaryConstructorParameters != null)
3026 generated_primary_constructor = DefineDefaultConstructor (false);
3028 return base.DoDefineMembers ();
3031 public override void Emit ()
3033 CheckStructCycles ();
3038 public override bool IsUnmanagedType ()
3040 if (has_unmanaged_check_done)
3041 return is_unmanaged;
3043 if (requires_delayed_unmanagedtype_check)
3046 var parent_def = Parent.PartialContainer;
3047 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3048 has_unmanaged_check_done = true;
3052 if (first_nonstatic_field != null) {
3053 requires_delayed_unmanagedtype_check = true;
3055 foreach (var member in Members) {
3056 var f = member as Field;
3063 // It can happen when recursive unmanaged types are defined
3064 // struct S { S* s; }
3065 TypeSpec mt = f.MemberType;
3073 has_unmanaged_check_done = true;
3077 has_unmanaged_check_done = true;
3080 is_unmanaged = true;
3084 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3086 var ifaces = base.ResolveBaseTypes (out base_class);
3087 base_type = Compiler.BuiltinTypes.ValueType;
3091 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3093 if ((field.ModFlags & Modifiers.STATIC) == 0) {
3094 Report.Error (573, field.Location, "`{0}': Structs cannot have instance field initializers",
3095 field.GetSignatureForError ());
3098 base.RegisterFieldForInitialization (field, expression);
3106 public sealed class Interface : TypeDefinition {
3109 /// Modifiers allowed in a class declaration
3111 const Modifiers AllowedModifiers =
3114 Modifiers.PROTECTED |
3115 Modifiers.INTERNAL |
3119 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3120 : base (parent, name, attrs, MemberKind.Interface)
3122 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3124 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3125 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3130 public override AttributeTargets AttributeTargets {
3132 return AttributeTargets.Interface;
3136 protected override TypeAttributes TypeAttr {
3138 const TypeAttributes DefaultTypeAttributes =
3139 TypeAttributes.AutoLayout |
3140 TypeAttributes.Abstract |
3141 TypeAttributes.Interface;
3143 return base.TypeAttr | DefaultTypeAttributes;
3149 public override void Accept (StructuralVisitor visitor)
3151 visitor.Visit (this);
3154 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3156 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3157 a.Error_MissingGuidAttribute ();
3161 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3164 protected override bool VerifyClsCompliance ()
3166 if (!base.VerifyClsCompliance ())
3169 if (iface_exprs != null) {
3170 foreach (var iface in iface_exprs) {
3171 if (iface.IsCLSCompliant ())
3174 Report.SymbolRelatedToPreviousError (iface);
3175 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3176 GetSignatureForError (), iface.GetSignatureForError ());
3184 public abstract class InterfaceMemberBase : MemberBase
3187 // Common modifiers allowed in a class declaration
3189 protected const Modifiers AllowedModifiersClass =
3192 Modifiers.PROTECTED |
3193 Modifiers.INTERNAL |
3198 Modifiers.OVERRIDE |
3199 Modifiers.ABSTRACT |
3204 // Common modifiers allowed in a struct declaration
3206 protected const Modifiers AllowedModifiersStruct =
3209 Modifiers.PROTECTED |
3210 Modifiers.INTERNAL |
3213 Modifiers.OVERRIDE |
3218 // Common modifiers allowed in a interface declaration
3220 protected const Modifiers AllowedModifiersInterface =
3225 // Whether this is an interface member.
3227 public bool IsInterface;
3230 // If true, this is an explicit interface implementation
3232 public readonly bool IsExplicitImpl;
3234 protected bool is_external_implementation;
3237 // The interface type we are explicitly implementing
3239 public TypeSpec InterfaceType;
3242 // The method we're overriding if this is an override method.
3244 protected MethodSpec base_method;
3246 readonly Modifiers explicit_mod_flags;
3247 public MethodAttributes flags;
3249 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3250 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3252 IsInterface = parent.Kind == MemberKind.Interface;
3253 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3254 explicit_mod_flags = mod;
3257 public abstract Variance ExpectedMemberTypeVariance { get; }
3259 protected override bool CheckBase ()
3261 if (!base.CheckBase ())
3264 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3265 CheckForDuplications ();
3270 // For System.Object only
3271 if (Parent.BaseType == null)
3274 MemberSpec candidate;
3275 bool overrides = false;
3276 var base_member = FindBaseMember (out candidate, ref overrides);
3278 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3279 if (base_member == null) {
3280 if (candidate == null) {
3281 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3282 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3283 "object.Finalize()");
3285 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3286 GetSignatureForError (), SimpleName.GetMemberType (this));
3289 Report.SymbolRelatedToPreviousError (candidate);
3291 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3292 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3293 else if (this is PropertyBase)
3294 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3295 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3297 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3298 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3305 // Handles ambiguous overrides
3307 if (candidate != null) {
3308 Report.SymbolRelatedToPreviousError (candidate);
3309 Report.SymbolRelatedToPreviousError (base_member);
3311 // Get member definition for error reporting
3312 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3313 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3315 Report.Error (462, Location,
3316 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3317 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3320 if (!CheckOverrideAgainstBase (base_member))
3323 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3325 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3326 Report.SymbolRelatedToPreviousError (base_member);
3327 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3328 GetSignatureForError (), base_member.GetSignatureForError ());
3331 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3332 Report.SymbolRelatedToPreviousError (base_member);
3333 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3334 GetSignatureForError (), base_member.GetSignatureForError ());
3338 base_method = base_member as MethodSpec;
3342 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3343 base_member = candidate;
3345 if (base_member == null) {
3346 if ((ModFlags & Modifiers.NEW) != 0) {
3347 if (base_member == null) {
3348 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3349 GetSignatureForError ());
3353 if ((ModFlags & Modifiers.NEW) == 0) {
3354 ModFlags |= Modifiers.NEW;
3355 if (!IsCompilerGenerated) {
3356 Report.SymbolRelatedToPreviousError (base_member);
3357 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3358 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",
3359 GetSignatureForError (), base_member.GetSignatureForError ());
3361 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3362 GetSignatureForError (), base_member.GetSignatureForError ());
3367 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3368 Report.SymbolRelatedToPreviousError (base_member);
3369 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3370 GetSignatureForError (), base_member.GetSignatureForError ());
3377 protected virtual bool CheckForDuplications ()
3379 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3383 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3384 // that have been defined.
3386 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3390 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3391 Report.SymbolRelatedToPreviousError (base_member);
3392 Report.Error (506, Location,
3393 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3394 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3398 // Now we check that the overriden method is not final
3399 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3400 Report.SymbolRelatedToPreviousError (base_member);
3401 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3402 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3406 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3407 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3408 Report.SymbolRelatedToPreviousError (base_member);
3409 if (this is PropertyBasedMember) {
3410 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3411 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3413 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3414 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3422 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3424 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3425 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3427 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3429 // It must be at least "protected"
3431 if ((thisp & Modifiers.PROTECTED) == 0) {
3436 // when overriding protected internal, the method can be declared
3437 // protected internal only within the same assembly or assembly
3438 // which has InternalsVisibleTo
3440 if ((thisp & Modifiers.INTERNAL) != 0) {
3441 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3445 // protected overriding protected internal inside same assembly
3446 // requires internal modifier as well
3448 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3455 return thisp == base_classp;
3458 public override bool Define ()
3461 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3462 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3464 flags = MethodAttributes.Public |
3465 MethodAttributes.Abstract |
3466 MethodAttributes.HideBySig |
3467 MethodAttributes.NewSlot |
3468 MethodAttributes.Virtual;
3470 Parent.PartialContainer.MethodModifiersValid (this);
3472 flags = ModifiersExtensions.MethodAttr (ModFlags);
3475 if (IsExplicitImpl) {
3476 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3477 if (InterfaceType == null)
3480 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3481 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3482 GetSignatureForError ());
3485 if (!InterfaceType.IsInterface) {
3486 Report.SymbolRelatedToPreviousError (InterfaceType);
3487 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3488 InterfaceType.GetSignatureForError ());
3490 Parent.PartialContainer.VerifyImplements (this);
3493 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3495 allowed_explicit |= Modifiers.ASYNC;
3497 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3500 return base.Define ();
3503 protected bool DefineParameters (ParametersCompiled parameters)
3505 if (!parameters.Resolve (this))
3509 for (int i = 0; i < parameters.Count; ++i) {
3510 Parameter p = parameters [i];
3512 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3513 p.Warning_UselessOptionalParameter (Report);
3515 if (p.CheckAccessibility (this))
3518 TypeSpec t = parameters.Types [i];
3519 Report.SymbolRelatedToPreviousError (t);
3520 if (this is Indexer)
3521 Report.Error (55, Location,
3522 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3523 t.GetSignatureForError (), GetSignatureForError ());
3524 else if (this is Operator)
3525 Report.Error (57, Location,
3526 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3527 t.GetSignatureForError (), GetSignatureForError ());
3529 Report.Error (51, Location,
3530 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3531 t.GetSignatureForError (), GetSignatureForError ());
3537 protected override void DoMemberTypeDependentChecks ()
3539 base.DoMemberTypeDependentChecks ();
3541 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3544 public override void Emit()
3546 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3547 // We are more strict than csc and report this as an error because SRE does not allow emit that
3548 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3549 if (this is Constructor) {
3550 Report.Warning (824, 1, Location,
3551 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3553 Report.Warning (626, 1, Location,
3554 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3555 GetSignatureForError ());
3562 public override bool EnableOverloadChecks (MemberCore overload)
3565 // Two members can differ in their explicit interface
3566 // type parameter only
3568 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3569 if (imb != null && imb.IsExplicitImpl) {
3570 if (IsExplicitImpl) {
3571 caching_flags |= Flags.MethodOverloadsExist;
3576 return IsExplicitImpl;
3579 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3581 var base_modifiers = base_member.Modifiers;
3583 // Remove internal modifier from types which are not internally accessible
3584 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3585 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3586 base_modifiers = Modifiers.PROTECTED;
3588 Report.SymbolRelatedToPreviousError (base_member);
3589 Report.Error (507, member.Location,
3590 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3591 member.GetSignatureForError (),
3592 ModifiersExtensions.AccessibilityName (base_modifiers),
3593 base_member.GetSignatureForError ());
3596 protected void Error_StaticReturnType ()
3598 Report.Error (722, Location,
3599 "`{0}': static types cannot be used as return types",
3600 MemberType.GetSignatureForError ());
3604 /// Gets base method and its return type
3606 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3608 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3612 // The "short" name of this property / indexer / event. This is the
3613 // name without the explicit interface.
3615 public string ShortName {
3616 get { return MemberName.Name; }
3620 // Returns full metadata method name
3622 public string GetFullName (MemberName name)
3624 return GetFullName (name.Name);
3627 public string GetFullName (string name)
3629 if (!IsExplicitImpl)
3633 // When dealing with explicit members a full interface type
3634 // name is added to member name to avoid possible name conflicts
3636 // We use CSharpName which gets us full name with benefit of
3637 // replacing predefined names which saves some space and name
3640 return InterfaceType.GetSignatureForError () + "." + name;
3643 public override string GetSignatureForDocumentation ()
3646 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3648 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3651 public override bool IsUsed
3653 get { return IsExplicitImpl || base.IsUsed; }
3656 public override void SetConstraints (List<Constraints> constraints_list)
3658 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3659 Report.Error (460, Location,
3660 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3661 GetSignatureForError ());
3664 base.SetConstraints (constraints_list);
3668 public abstract class MemberBase : MemberCore
3670 protected FullNamedExpression type_expr;
3671 protected TypeSpec member_type;
3672 public new TypeDefinition Parent;
3674 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3675 : base (parent, name, attrs)
3677 this.Parent = parent;
3678 this.type_expr = type;
3680 if (name != MemberName.Null)
3681 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3686 public TypeSpec MemberType {
3692 public FullNamedExpression TypeExpression {
3701 // Main member define entry
3703 public override bool Define ()
3705 DoMemberTypeIndependentChecks ();
3708 // Returns false only when type resolution failed
3710 if (!ResolveMemberType ())
3713 DoMemberTypeDependentChecks ();
3718 // Any type_name independent checks
3720 protected virtual void DoMemberTypeIndependentChecks ()
3722 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3723 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3724 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3725 GetSignatureForError (), Parent.GetSignatureForError ());
3730 // Any type_name dependent checks
3732 protected virtual void DoMemberTypeDependentChecks ()
3734 // verify accessibility
3735 if (!IsAccessibleAs (MemberType)) {
3736 Report.SymbolRelatedToPreviousError (MemberType);
3737 if (this is Property)
3738 Report.Error (53, Location,
3739 "Inconsistent accessibility: property type `" +
3740 MemberType.GetSignatureForError () + "' is less " +
3741 "accessible than property `" + GetSignatureForError () + "'");
3742 else if (this is Indexer)
3743 Report.Error (54, Location,
3744 "Inconsistent accessibility: indexer return type `" +
3745 MemberType.GetSignatureForError () + "' is less " +
3746 "accessible than indexer `" + GetSignatureForError () + "'");
3747 else if (this is MethodCore) {
3748 if (this is Operator)
3749 Report.Error (56, Location,
3750 "Inconsistent accessibility: return type `" +
3751 MemberType.GetSignatureForError () + "' is less " +
3752 "accessible than operator `" + GetSignatureForError () + "'");
3754 Report.Error (50, Location,
3755 "Inconsistent accessibility: return type `" +
3756 MemberType.GetSignatureForError () + "' is less " +
3757 "accessible than method `" + GetSignatureForError () + "'");
3758 } else if (this is Event) {
3759 Report.Error (7025, Location,
3760 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3761 MemberType.GetSignatureForError (), GetSignatureForError ());
3763 Report.Error (52, Location,
3764 "Inconsistent accessibility: field type `" +
3765 MemberType.GetSignatureForError () + "' is less " +
3766 "accessible than field `" + GetSignatureForError () + "'");
3771 protected void IsTypePermitted ()
3773 if (MemberType.IsSpecialRuntimeType) {
3774 if (Parent is StateMachine) {
3775 Report.Error (4012, Location,
3776 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3777 MemberType.GetSignatureForError ());
3778 } else if (Parent is HoistedStoreyClass) {
3779 Report.Error (4013, Location,
3780 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3781 MemberType.GetSignatureForError ());
3783 Report.Error (610, Location,
3784 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3789 protected virtual bool CheckBase ()
3791 CheckProtectedModifier ();
3796 public override string GetSignatureForDocumentation ()
3798 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3801 protected virtual bool ResolveMemberType ()
3803 if (member_type != null)
3804 throw new InternalErrorException ("Multi-resolve");
3806 member_type = type_expr.ResolveAsType (this);
3807 return member_type != null;