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 [] { "type" };
557 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
560 /// The pending methods that need to be implemented
561 // (interfaces or abstract methods)
563 PendingImplementation pending;
565 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
566 : base (parent, name, attrs, kind)
568 PartialContainer = this;
569 members = new List<MemberCore> ();
574 public List<FullNamedExpression> BaseTypeExpressions {
580 public override TypeSpec CurrentType {
582 if (current_type == null) {
583 if (IsGenericOrParentIsGeneric) {
585 // Switch to inflated version as it's used by all expressions
587 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
588 current_type = spec.MakeGenericType (this, targs);
598 public override TypeParameters CurrentTypeParameters {
600 return PartialContainer.MemberName.TypeParameters;
604 int CurrentTypeParametersStartIndex {
606 int total = all_tp_builders.Length;
607 if (CurrentTypeParameters != null) {
608 return total - CurrentTypeParameters.Count;
614 public virtual AssemblyDefinition DeclaringAssembly {
616 return Module.DeclaringAssembly;
620 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
622 return Module.DeclaringAssembly;
626 public TypeSpec Definition {
632 public bool HasMembersDefined {
634 return members_defined;
638 public bool HasInstanceConstructor {
640 return (caching_flags & Flags.HasInstanceConstructor) != 0;
643 caching_flags |= Flags.HasInstanceConstructor;
647 // Indicated whether container has StructLayout attribute set Explicit
648 public bool HasExplicitLayout {
649 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
650 set { caching_flags |= Flags.HasExplicitLayout; }
653 public bool HasOperators {
655 return (caching_flags & Flags.HasUserOperators) != 0;
658 caching_flags |= Flags.HasUserOperators;
662 public bool HasStructLayout {
663 get { return (caching_flags & Flags.HasStructLayout) != 0; }
664 set { caching_flags |= Flags.HasStructLayout; }
667 public TypeSpec[] Interfaces {
673 public bool IsGenericOrParentIsGeneric {
675 return all_type_parameters != null;
679 public bool IsTopLevel {
681 return !(Parent is TypeDefinition);
685 public bool IsPartial {
687 return (ModFlags & Modifiers.PARTIAL) != 0;
691 bool ITypeDefinition.IsTypeForwarder {
697 bool ITypeDefinition.IsCyclicTypeForwarder {
704 // Returns true for secondary partial containers
708 return PartialContainer != this;
712 public MemberCache MemberCache {
714 return spec.MemberCache;
718 public List<MemberCore> Members {
724 string ITypeDefinition.Namespace {
727 while (p.Kind != MemberKind.Namespace)
730 return p.MemberName == null ? null : p.GetSignatureForError ();
734 public ParametersCompiled PrimaryConstructorParameters { get; set; }
736 public Arguments PrimaryConstructorBaseArguments { get; set; }
738 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
740 public TypeParameters TypeParametersAll {
742 return all_type_parameters;
746 public override string[] ValidAttributeTargets {
748 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
754 public override void Accept (StructuralVisitor visitor)
756 visitor.Visit (this);
759 public void AddMember (MemberCore symbol)
761 if (symbol.MemberName.ExplicitInterface != null) {
762 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
763 Report.Error (541, symbol.Location,
764 "`{0}': explicit interface declaration can only be declared in a class or struct",
765 symbol.GetSignatureForError ());
769 AddNameToContainer (symbol, symbol.MemberName.Name);
770 members.Add (symbol);
773 public override void AddTypeContainer (TypeContainer tc)
775 AddNameToContainer (tc, tc.Basename);
777 base.AddTypeContainer (tc);
780 protected override void AddTypeContainerMember (TypeContainer tc)
784 if (containers == null)
785 containers = new List<TypeContainer> ();
787 base.AddTypeContainerMember (tc);
791 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
793 public virtual void AddNameToContainer (MemberCore symbol, string name)
795 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
799 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
800 PartialContainer.defined_names.Add (name, symbol);
804 if (symbol.EnableOverloadChecks (mc))
807 InterfaceMemberBase im = mc as InterfaceMemberBase;
808 if (im != null && im.IsExplicitImpl)
811 Report.SymbolRelatedToPreviousError (mc);
812 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
813 Error_MissingPartialModifier (symbol);
817 if (symbol is TypeParameter) {
818 Report.Error (692, symbol.Location,
819 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
821 Report.Error (102, symbol.Location,
822 "The type `{0}' already contains a definition for `{1}'",
823 GetSignatureForError (), name);
829 public void AddConstructor (Constructor c)
831 AddConstructor (c, false);
834 public void AddConstructor (Constructor c, bool isDefault)
836 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
838 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
840 if (is_static && c.ParameterInfo.IsEmpty) {
841 PartialContainer.has_static_constructor = true;
843 PartialContainer.HasInstanceConstructor = true;
849 public bool AddField (FieldBase field)
853 if ((field.ModFlags & Modifiers.STATIC) != 0)
856 var first_field = PartialContainer.first_nonstatic_field;
857 if (first_field == null) {
858 PartialContainer.first_nonstatic_field = field;
862 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
863 Report.SymbolRelatedToPreviousError (first_field.Parent);
864 Report.Warning (282, 3, field.Location,
865 "struct instance field `{0}' found in different declaration from instance field `{1}'",
866 field.GetSignatureForError (), first_field.GetSignatureForError ());
872 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
874 public void AddIndexer (Indexer i)
879 public void AddOperator (Operator op)
881 PartialContainer.HasOperators = true;
885 public void AddPartialPart (TypeDefinition part)
887 if (Kind != MemberKind.Class)
890 if (class_partial_parts == null)
891 class_partial_parts = new List<TypeDefinition> ();
893 class_partial_parts.Add (part);
896 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
898 if (a.Target == AttributeTargets.Method) {
899 foreach (var m in members) {
900 var c = m as Constructor;
904 if (c.IsPrimaryConstructor) {
905 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
910 throw new InternalErrorException ();
913 if (has_normal_indexers && a.Type == pa.DefaultMember) {
914 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
918 if (a.Type == pa.Required) {
919 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
923 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
926 public override AttributeTargets AttributeTargets {
928 throw new NotSupportedException ();
932 public TypeSpec BaseType {
934 return spec.BaseType;
938 protected virtual TypeAttributes TypeAttr {
940 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
944 public int TypeParametersCount {
946 return MemberName.Arity;
950 TypeParameterSpec[] ITypeDefinition.TypeParameters {
952 return PartialContainer.CurrentTypeParameters.Types;
956 public string GetAttributeDefaultMember ()
958 return indexer_name ?? DefaultIndexerName;
961 public bool IsComImport {
963 if (OptAttributes == null)
966 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
970 public virtual void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
973 PartialContainer.RegisterFieldForInitialization (field, expression);
975 if ((field.ModFlags & Modifiers.STATIC) != 0){
976 if (initialized_static_fields == null) {
977 HasStaticFieldInitializer = true;
978 initialized_static_fields = new List<FieldInitializer> (4);
981 initialized_static_fields.Add (expression);
983 if (initialized_fields == null)
984 initialized_fields = new List<FieldInitializer> (4);
986 initialized_fields.Add (expression);
990 public void ResolveFieldInitializers (BlockContext ec)
992 Debug.Assert (!IsPartialPart);
995 if (initialized_static_fields == null)
998 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
1000 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1001 for (i = 0; i < initialized_static_fields.Count; ++i) {
1002 FieldInitializer fi = initialized_static_fields [i];
1003 ExpressionStatement s = fi.ResolveStatement (ec);
1005 s = EmptyExpressionStatement.Instance;
1006 } else if (!fi.IsSideEffectFree) {
1007 has_complex_initializer = true;
1013 for (i = 0; i < initialized_static_fields.Count; ++i) {
1014 FieldInitializer fi = initialized_static_fields [i];
1016 // Need special check to not optimize code like this
1017 // static int a = b = 5;
1018 // static int b = 0;
1020 if (!has_complex_initializer && fi.IsDefaultInitializer)
1023 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1024 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1030 if (initialized_fields == null)
1033 for (int i = 0; i < initialized_fields.Count; ++i) {
1034 FieldInitializer fi = initialized_fields [i];
1037 // Clone before resolving otherwise when field initializer is needed
1038 // in more than 1 constructor any resolve after the initial one would
1039 // only took the resolved expression which is problem for expressions
1040 // that generate extra expressions or code during Resolve phase
1042 var cloned = fi.Clone (new CloneContext ());
1044 ExpressionStatement s = fi.ResolveStatement (ec);
1046 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1051 // Field is re-initialized to its default value => removed
1053 if (fi.IsDefaultInitializer && ec.Module.Compiler.Settings.Optimize)
1056 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1057 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1058 initialized_fields [i] = (FieldInitializer) cloned;
1062 public override string DocComment {
1074 public PendingImplementation PendingImplementations {
1075 get { return pending; }
1078 internal override void GenerateDocComment (DocumentationBuilder builder)
1083 base.GenerateDocComment (builder);
1085 foreach (var member in members)
1086 member.GenerateDocComment (builder);
1089 public TypeSpec GetAttributeCoClass ()
1091 if (OptAttributes == null)
1094 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1098 return a.GetCoClassAttributeValue ();
1101 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1104 if (OptAttributes != null) {
1105 a = OptAttributes.Search (pa);
1111 return a.GetAttributeUsageAttribute ();
1114 public virtual CompilationSourceFile GetCompilationSourceFile ()
1116 TypeContainer ns = Parent;
1118 var sf = ns as CompilationSourceFile;
1126 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1128 type_bases = baseTypes;
1132 /// This function computes the Base class and also the
1133 /// list of interfaces that the class or struct @c implements.
1135 /// The return value is an array (might be null) of
1136 /// interfaces implemented (as Types).
1138 /// The @base_class argument is set to the base object or null
1139 /// if this is `System.Object'.
1141 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1144 if (type_bases == null)
1147 int count = type_bases.Count;
1148 TypeSpec[] ifaces = null;
1149 var base_context = new BaseContext (this);
1150 for (int i = 0, j = 0; i < count; i++){
1151 FullNamedExpression fne = type_bases [i];
1153 var fne_resolved = fne.ResolveAsType (base_context);
1154 if (fne_resolved == null)
1157 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1158 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1159 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1160 GetSignatureForError ());
1165 base_type = fne_resolved;
1171 ifaces = new TypeSpec [count - i];
1173 if (fne_resolved.IsInterface) {
1174 for (int ii = 0; ii < j; ++ii) {
1175 if (fne_resolved == ifaces [ii]) {
1176 Report.Error (528, Location, "`{0}' is already listed in interface list",
1177 fne_resolved.GetSignatureForError ());
1182 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1183 Report.Error (61, fne.Location,
1184 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1185 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1188 Report.SymbolRelatedToPreviousError (fne_resolved);
1189 if (Kind != MemberKind.Class) {
1190 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1191 } else if (base_class != null)
1192 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1193 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1195 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1196 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1200 ifaces [j++] = fne_resolved;
1207 // Checks that some operators come in pairs:
1213 // They are matched based on the return type and the argument types
1215 void CheckPairedOperators ()
1217 bool has_equality_or_inequality = false;
1218 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1220 for (int i = 0; i < members.Count; ++i) {
1221 var o_a = members[i] as Operator;
1225 var o_type = o_a.OperatorType;
1226 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1227 has_equality_or_inequality = true;
1229 if (found_matched.Contains (o_type))
1232 var matching_type = o_a.GetMatchingOperator ();
1233 if (matching_type == Operator.OpType.TOP) {
1237 bool pair_found = false;
1238 for (int ii = 0; ii < members.Count; ++ii) {
1239 var o_b = members[ii] as Operator;
1240 if (o_b == null || o_b.OperatorType != matching_type)
1243 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1246 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1249 found_matched.Add (matching_type);
1255 Report.Error (216, o_a.Location,
1256 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1257 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1261 if (has_equality_or_inequality) {
1263 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1264 GetSignatureForError ());
1266 if (!HasGetHashCode)
1267 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1268 GetSignatureForError ());
1272 public override void CreateMetadataName (StringBuilder sb)
1274 if (Parent.MemberName != null) {
1275 Parent.CreateMetadataName (sb);
1277 if (sb.Length != 0) {
1282 sb.Append (MemberName.Basename);
1285 bool CreateTypeBuilder ()
1288 // Sets .size to 1 for structs with no instance fields
1290 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1292 var parent_def = Parent as TypeDefinition;
1293 if (parent_def == null) {
1294 var sb = new StringBuilder ();
1295 CreateMetadataName (sb);
1296 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1298 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (Basename, TypeAttr, null, type_size);
1301 if (DeclaringAssembly.Importer != null)
1302 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1304 spec.SetMetaInfo (TypeBuilder);
1305 spec.MemberCache = new MemberCache (this);
1307 TypeParameters parentAllTypeParameters = null;
1308 if (parent_def != null) {
1309 spec.DeclaringType = Parent.CurrentType;
1310 parent_def.MemberCache.AddMember (spec);
1311 parentAllTypeParameters = parent_def.all_type_parameters;
1314 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1315 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1317 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1319 if (CurrentTypeParameters != null) {
1320 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1321 CurrentTypeParameters.Define (all_tp_builders);
1328 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1331 int parent_offset = 0;
1332 if (parentAllTypeParameters != null) {
1333 if (CurrentTypeParameters == null) {
1334 all_type_parameters = parentAllTypeParameters;
1335 return parentAllTypeParameters.GetAllNames ();
1338 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1339 all_type_parameters = new TypeParameters (names.Length);
1340 all_type_parameters.Add (parentAllTypeParameters);
1342 parent_offset = all_type_parameters.Count;
1343 for (int i = 0; i < parent_offset; ++i)
1344 names[i] = all_type_parameters[i].MemberName.Name;
1347 names = new string[CurrentTypeParameters.Count];
1350 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1351 if (all_type_parameters != null)
1352 all_type_parameters.Add (MemberName.TypeParameters[i]);
1354 var name = CurrentTypeParameters[i].MemberName.Name;
1355 names[parent_offset + i] = name;
1356 for (int ii = 0; ii < parent_offset + i; ++ii) {
1357 if (names[ii] != name)
1360 var tp = CurrentTypeParameters[i];
1361 var conflict = all_type_parameters[ii];
1363 tp.WarningParentNameConflict (conflict);
1367 if (all_type_parameters == null)
1368 all_type_parameters = CurrentTypeParameters;
1374 public SourceMethodBuilder CreateMethodSymbolEntry ()
1376 if (Module.DeclaringAssembly.SymbolWriter == null)
1379 var source_file = GetCompilationSourceFile ();
1380 if (source_file == null)
1383 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1387 // Creates a proxy base method call inside this container for hoisted base member calls
1389 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1391 Method proxy_method;
1394 // One proxy per base method is enough
1396 if (hoisted_base_call_proxies == null) {
1397 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1398 proxy_method = null;
1400 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1403 if (proxy_method == null) {
1404 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1406 MemberName member_name;
1407 TypeArguments targs = null;
1408 TypeSpec return_type = method.ReturnType;
1409 var local_param_types = method.Parameters.Types;
1411 if (method.IsGeneric) {
1413 // Copy all base generic method type parameters info
1415 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1416 var tparams = new TypeParameters ();
1418 targs = new TypeArguments ();
1419 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1420 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1421 var tp = hoisted_tparams[i];
1422 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1423 tparams.Add (local_tp);
1425 targs.Add (new SimpleName (tp.Name, Location));
1426 targs.Arguments[i] = local_tp.Type;
1429 member_name = new MemberName (name, tparams, Location);
1432 // Mutate any method type parameters from original
1433 // to newly created hoisted version
1435 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1436 return_type = mutator.Mutate (return_type);
1437 local_param_types = mutator.Mutate (local_param_types);
1439 member_name = new MemberName (name);
1442 var base_parameters = new Parameter[method.Parameters.Count];
1443 for (int i = 0; i < base_parameters.Length; ++i) {
1444 var base_param = method.Parameters.FixedParameters[i];
1445 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1446 base_param.Name, base_param.ModFlags, null, Location);
1447 base_parameters[i].Resolve (this, i);
1450 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1451 if (method.Parameters.HasArglist) {
1452 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1453 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1456 // Compiler generated proxy
1457 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1458 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1459 member_name, cloned_params, null);
1461 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1462 IsCompilerGenerated = true
1465 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1466 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1468 mg.SetTypeArguments (rc, targs);
1470 // Get all the method parameters and pass them as arguments
1471 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1472 Statement statement;
1473 if (method.ReturnType.Kind == MemberKind.Void)
1474 statement = new StatementExpression (real_base_call);
1476 statement = new Return (real_base_call, Location);
1478 block.AddStatement (statement);
1479 proxy_method.Block = block;
1481 members.Add (proxy_method);
1482 proxy_method.Define ();
1483 proxy_method.PrepareEmit ();
1485 hoisted_base_call_proxies.Add (method, proxy_method);
1488 return proxy_method.Spec;
1491 protected bool DefineBaseTypes ()
1493 if (IsPartialPart && Kind == MemberKind.Class)
1496 return DoDefineBaseType ();
1499 bool DoDefineBaseType ()
1501 iface_exprs = ResolveBaseTypes (out base_type_expr);
1504 if (IsPartialPart) {
1505 set_base_type = false;
1507 if (base_type_expr != null) {
1508 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1509 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1510 Report.Error (263, Location,
1511 "Partial declarations of `{0}' must not specify different base classes",
1512 GetSignatureForError ());
1514 PartialContainer.base_type_expr = base_type_expr;
1515 PartialContainer.base_type = base_type;
1516 set_base_type = true;
1520 if (iface_exprs != null) {
1521 if (PartialContainer.iface_exprs == null)
1522 PartialContainer.iface_exprs = iface_exprs;
1524 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1525 foreach (var iface_partial in iface_exprs) {
1526 if (ifaces.Contains (iface_partial))
1529 ifaces.Add (iface_partial);
1532 PartialContainer.iface_exprs = ifaces.ToArray ();
1536 PartialContainer.members.AddRange (members);
1537 if (containers != null) {
1538 if (PartialContainer.containers == null)
1539 PartialContainer.containers = new List<TypeContainer> ();
1541 PartialContainer.containers.AddRange (containers);
1544 if (PrimaryConstructorParameters != null) {
1545 if (PartialContainer.PrimaryConstructorParameters != null) {
1546 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1548 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1552 members_defined = members_defined_ok = true;
1553 caching_flags |= Flags.CloseTypeCreated;
1555 set_base_type = true;
1558 var cycle = CheckRecursiveDefinition (this);
1559 if (cycle != null) {
1560 Report.SymbolRelatedToPreviousError (cycle);
1561 if (this is Interface) {
1562 Report.Error (529, Location,
1563 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1564 GetSignatureForError (), cycle.GetSignatureForError ());
1567 PartialContainer.iface_exprs = null;
1569 Report.Error (146, Location,
1570 "Circular base class dependency involving `{0}' and `{1}'",
1571 GetSignatureForError (), cycle.GetSignatureForError ());
1574 PartialContainer.base_type = null;
1578 if (iface_exprs != null) {
1579 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1580 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1583 foreach (var iface_type in iface_exprs) {
1584 // Prevents a crash, the interface might not have been resolved: 442144
1585 if (iface_type == null)
1588 if (!spec.AddInterfaceDefined (iface_type))
1591 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1595 if (Kind == MemberKind.Interface) {
1596 spec.BaseType = Compiler.BuiltinTypes.Object;
1600 if (set_base_type) {
1605 // Base type of partial container has to be resolved before we
1606 // resolve any nested types of the container. We need to know
1607 // partial parts because the base type can be specified in file
1608 // defined after current container
1610 if (class_partial_parts != null) {
1611 foreach (var pp in class_partial_parts) {
1612 if (pp.PrimaryConstructorBaseArguments != null)
1613 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1615 pp.DoDefineBaseType ();
1625 if (base_type == null) {
1626 TypeBuilder.SetParent (null);
1630 if (spec.BaseType == base_type)
1633 spec.BaseType = base_type;
1636 spec.UpdateInflatedInstancesBaseType ();
1638 // Set base type after type creation
1639 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1642 public override void ExpandBaseInterfaces ()
1645 DoExpandBaseInterfaces ();
1647 base.ExpandBaseInterfaces ();
1650 public void DoExpandBaseInterfaces ()
1652 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1655 caching_flags |= Flags.InterfacesExpanded;
1658 // Expand base interfaces. It cannot be done earlier because all partial
1659 // interface parts need to be defined before the type they are used from
1661 if (iface_exprs != null) {
1662 foreach (var iface in iface_exprs) {
1666 var td = iface.MemberDefinition as TypeDefinition;
1668 td.DoExpandBaseInterfaces ();
1670 if (iface.Interfaces == null)
1673 foreach (var biface in iface.Interfaces) {
1674 if (spec.AddInterfaceDefined (biface)) {
1675 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1682 // Include all base type interfaces too, see ImportTypeBase for details
1684 if (base_type != null) {
1685 var td = base_type.MemberDefinition as TypeDefinition;
1687 td.DoExpandBaseInterfaces ();
1690 // Simply use base interfaces only, they are all expanded which makes
1691 // it easy to handle generic type argument propagation with single
1694 // interface IA<T> : IB<T>
1695 // interface IB<U> : IC<U>
1698 if (base_type.Interfaces != null) {
1699 foreach (var iface in base_type.Interfaces) {
1700 spec.AddInterfaceDefined (iface);
1706 public override void PrepareEmit ()
1708 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1711 foreach (var member in members) {
1712 var pbm = member as PropertyBasedMember;
1716 var pm = member as IParametersMember;
1718 var mc = member as MethodOrOperator;
1723 var p = pm.Parameters;
1727 ((ParametersCompiled) p).ResolveDefaultValues (member);
1731 var c = member as Const;
1736 base.PrepareEmit ();
1740 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1742 public override bool CreateContainer ()
1744 if (TypeBuilder != null)
1750 if (IsPartialPart) {
1751 spec = PartialContainer.spec;
1752 TypeBuilder = PartialContainer.TypeBuilder;
1753 all_tp_builders = PartialContainer.all_tp_builders;
1754 all_type_parameters = PartialContainer.all_type_parameters;
1756 if (!CreateTypeBuilder ()) {
1762 return base.CreateContainer ();
1765 protected override void DoDefineContainer ()
1769 DoResolveTypeParameters ();
1773 // Replaces normal spec with predefined one when compiling corlib
1774 // and this type container defines predefined type
1776 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1778 // When compiling build-in types we start with two
1779 // version of same type. One is of BuiltinTypeSpec and
1780 // second one is ordinary TypeSpec. The unification
1781 // happens at later stage when we know which type
1782 // really matches the builtin type signature. However
1783 // that means TypeSpec create during CreateType of this
1784 // type has to be replaced with builtin one
1786 spec.SetMetaInfo (TypeBuilder);
1787 spec.MemberCache = this.spec.MemberCache;
1788 spec.DeclaringType = this.spec.DeclaringType;
1791 current_type = null;
1794 public override void RemoveContainer (TypeContainer cont)
1796 base.RemoveContainer (cont);
1797 Members.Remove (cont);
1798 Cache.Remove (cont.Basename);
1801 protected virtual bool DoResolveTypeParameters ()
1803 var tparams = MemberName.TypeParameters;
1804 if (tparams == null)
1807 var base_context = new BaseContext (this);
1808 for (int i = 0; i < tparams.Count; ++i) {
1809 var tp = tparams[i];
1811 if (!tp.ResolveConstraints (base_context)) {
1816 if (IsPartialPart) {
1817 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1819 tp.Create (spec, this);
1822 if (tp.OptAttributes != null) {
1823 if (pc_tp.OptAttributes == null)
1824 pc_tp.OptAttributes = tp.OptAttributes;
1826 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1831 if (IsPartialPart) {
1832 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1838 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1840 if (InTransit != null)
1845 if (base_type != null) {
1846 var ptc = base_type.MemberDefinition as TypeDefinition;
1847 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1851 if (iface_exprs != null) {
1852 foreach (var iface in iface_exprs) {
1853 // the interface might not have been resolved, prevents a crash, see #442144
1856 var ptc = iface.MemberDefinition as Interface;
1857 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1862 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1870 /// Populates our TypeBuilder with fields and methods
1872 public sealed override bool Define ()
1874 if (members_defined)
1875 return members_defined_ok;
1877 members_defined_ok = DoDefineMembers ();
1878 members_defined = true;
1882 return members_defined_ok;
1885 protected virtual bool DoDefineMembers ()
1887 Debug.Assert (!IsPartialPart);
1889 if (iface_exprs != null) {
1890 foreach (var iface_type in iface_exprs) {
1891 if (iface_type == null)
1894 // Ensure the base is always setup
1895 var compiled_iface = iface_type.MemberDefinition as Interface;
1896 if (compiled_iface != null)
1897 compiled_iface.Define ();
1899 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1900 if (oa != null && !IsObsolete)
1901 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1903 if (iface_type.Arity > 0) {
1904 // TODO: passing `this' is wrong, should be base type iface instead
1905 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1907 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1908 Report.Error (1966, Location,
1909 "`{0}': cannot implement a dynamic interface `{1}'",
1910 GetSignatureForError (), iface_type.GetSignatureForError ());
1915 if (iface_type.IsGenericOrParentIsGeneric) {
1916 foreach (var prev_iface in iface_exprs) {
1917 if (prev_iface == iface_type || prev_iface == null)
1920 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1923 Report.Error (695, Location,
1924 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1925 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1930 if (Kind == MemberKind.Interface) {
1931 foreach (var iface in spec.Interfaces) {
1932 MemberCache.AddInterface (iface);
1937 if (base_type != null) {
1939 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1941 if (base_type_expr != null) {
1942 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1943 if (obsolete_attr != null && !IsObsolete)
1944 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1946 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1947 Report.Error (698, base_type_expr.Location,
1948 "A generic type cannot derive from `{0}' because it is an attribute class",
1949 base_type.GetSignatureForError ());
1953 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1954 if (baseContainer != null) {
1955 baseContainer.Define ();
1958 // It can trigger define of this type (for generic types only)
1960 if (HasMembersDefined)
1965 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1966 pending = PendingImplementation.GetPendingImplementations (this);
1969 var count = members.Count;
1970 for (int i = 0; i < count; ++i) {
1971 var mc = members[i] as InterfaceMemberBase;
1972 if (mc == null || !mc.IsExplicitImpl)
1977 } catch (Exception e) {
1978 throw new InternalErrorException (mc, e);
1982 for (int i = 0; i < count; ++i) {
1983 var mc = members[i] as InterfaceMemberBase;
1984 if (mc != null && mc.IsExplicitImpl)
1987 if (members[i] is TypeContainer)
1991 members[i].Define ();
1992 } catch (Exception e) {
1993 throw new InternalErrorException (members[i], e);
1998 CheckPairedOperators ();
2001 if (requires_delayed_unmanagedtype_check) {
2002 requires_delayed_unmanagedtype_check = false;
2003 foreach (var member in members) {
2004 var f = member as Field;
2005 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2006 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2010 ComputeIndexerName();
2012 if (HasEquals && !HasGetHashCode) {
2013 Report.Warning (659, 3, Location,
2014 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2017 if (Kind == MemberKind.Interface && iface_exprs != null) {
2018 MemberCache.RemoveHiddenMembers (spec);
2024 void ComputeIndexerName ()
2026 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2027 if (indexers == null)
2030 string class_indexer_name = null;
2033 // Check normal indexers for consistent name, explicit interface implementation
2034 // indexers are ignored
2036 foreach (var indexer in indexers) {
2038 // FindMembers can return unfiltered full hierarchy names
2040 if (indexer.DeclaringType != spec)
2043 has_normal_indexers = true;
2045 if (class_indexer_name == null) {
2046 indexer_name = class_indexer_name = indexer.Name;
2050 if (indexer.Name != class_indexer_name)
2051 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2052 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2056 void EmitIndexerName ()
2058 if (!has_normal_indexers)
2061 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2065 var encoder = new AttributeEncoder ();
2066 encoder.Encode (GetAttributeDefaultMember ());
2067 encoder.EncodeEmptyNamedArguments ();
2069 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2072 public override void VerifyMembers ()
2075 // Check for internal or private fields that were never assigned
2077 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2078 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2079 foreach (var member in members) {
2080 if (member is Event) {
2082 // An event can be assigned from same class only, report
2083 // this warning for all accessibility modes
2085 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2086 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2091 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2092 if (is_type_exposed)
2095 member.SetIsUsed ();
2098 var f = member as Field;
2102 if (!member.IsUsed) {
2103 if (!PartialContainer.HasStructLayout) {
2104 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2105 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2107 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2108 member.GetSignatureForError ());
2115 if ((f.caching_flags & Flags.IsAssigned) != 0)
2119 // Only report 649 on level 4
2121 if (Compiler.Settings.WarningLevel < 4)
2125 // Don't be pedantic when type requires specific layout
2127 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2130 Constant c = New.Constantify (f.MemberType, f.Location);
2133 value = c.GetValueAsLiteral ();
2134 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2141 value = " `" + value + "'";
2143 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2144 f.GetSignatureForError (), value);
2148 base.VerifyMembers ();
2151 public override void Emit ()
2153 if (OptAttributes != null)
2154 OptAttributes.Emit ();
2156 if (!IsCompilerGenerated) {
2158 MemberSpec candidate;
2159 bool overrides = false;
2160 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2161 if (conflict_symbol == null && candidate == null) {
2162 if ((ModFlags & Modifiers.NEW) != 0)
2163 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2164 GetSignatureForError ());
2166 if ((ModFlags & Modifiers.NEW) == 0) {
2167 if (candidate == null)
2168 candidate = conflict_symbol;
2170 Report.SymbolRelatedToPreviousError (candidate);
2171 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2172 GetSignatureForError (), candidate.GetSignatureForError ());
2177 // Run constraints check on all possible generic types
2178 if (base_type != null && base_type_expr != null) {
2179 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2182 if (iface_exprs != null) {
2183 foreach (var iface_type in iface_exprs) {
2184 if (iface_type == null)
2187 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2192 if (all_tp_builders != null) {
2193 int current_starts_index = CurrentTypeParametersStartIndex;
2194 for (int i = 0; i < all_tp_builders.Length; i++) {
2195 if (i < current_starts_index) {
2196 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2198 var tp = CurrentTypeParameters [i - current_starts_index];
2199 tp.CheckGenericConstraints (!IsObsolete);
2205 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2206 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2209 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2210 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2215 for (int i = 0; i < members.Count; i++) {
2217 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2224 CheckAttributeClsCompliance ();
2226 if (pending != null)
2227 pending.VerifyPendingMethods ();
2231 void CheckAttributeClsCompliance ()
2233 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2236 foreach (var m in members) {
2237 var c = m as Constructor;
2241 if (c.HasCompliantArgs)
2245 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2248 public sealed override void EmitContainer ()
2250 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2256 public override void CloseContainer ()
2258 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2261 // Close base type container first to avoid TypeLoadException
2262 if (spec.BaseType != null) {
2263 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2264 if (btype != null) {
2265 btype.CloseContainer ();
2267 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2273 caching_flags |= Flags.CloseTypeCreated;
2274 TypeBuilder.CreateType ();
2275 } catch (TypeLoadException) {
2277 // This is fine, the code still created the type
2279 } catch (Exception e) {
2280 throw new InternalErrorException (this, e);
2283 base.CloseContainer ();
2286 initialized_fields = null;
2287 initialized_static_fields = null;
2289 OptAttributes = null;
2293 // Performs the validation on a Method's modifiers (properties have
2294 // the same properties).
2296 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2298 public bool MethodModifiersValid (MemberCore mc)
2300 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2301 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2303 var flags = mc.ModFlags;
2306 // At most one of static, virtual or override
2308 if ((flags & Modifiers.STATIC) != 0){
2309 if ((flags & vao) != 0){
2310 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2311 mc.GetSignatureForError ());
2316 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2317 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2318 mc.GetSignatureForError ());
2323 // If the declaration includes the abstract modifier, then the
2324 // declaration does not include static, virtual or extern
2326 if ((flags & Modifiers.ABSTRACT) != 0){
2327 if ((flags & Modifiers.EXTERN) != 0){
2329 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2333 if ((flags & Modifiers.SEALED) != 0) {
2334 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2338 if ((flags & Modifiers.VIRTUAL) != 0){
2339 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2343 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2344 Report.SymbolRelatedToPreviousError (this);
2345 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2346 mc.GetSignatureForError (), GetSignatureForError ());
2351 if ((flags & Modifiers.PRIVATE) != 0){
2352 if ((flags & vao) != 0){
2353 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2358 if ((flags & Modifiers.SEALED) != 0){
2359 if ((flags & Modifiers.OVERRIDE) == 0){
2360 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2368 protected override bool VerifyClsCompliance ()
2370 if (!base.VerifyClsCompliance ())
2373 // Check all container names for user classes
2374 if (Kind != MemberKind.Delegate)
2375 MemberCache.VerifyClsCompliance (Definition, Report);
2377 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2378 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2379 GetSignatureForError (), BaseType.GetSignatureForError ());
2385 /// Performs checks for an explicit interface implementation. First it
2386 /// checks whether the `interface_type' is a base inteface implementation.
2387 /// Then it checks whether `name' exists in the interface type.
2389 public bool VerifyImplements (InterfaceMemberBase mb)
2391 var ifaces = PartialContainer.Interfaces;
2392 if (ifaces != null) {
2393 foreach (TypeSpec t in ifaces){
2394 if (t == mb.InterfaceType)
2397 var expanded_base = t.Interfaces;
2398 if (expanded_base == null)
2401 foreach (var bt in expanded_base) {
2402 if (bt == mb.InterfaceType)
2408 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2409 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2410 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2415 // Used for visiblity checks to tests whether this definition shares
2416 // base type baseType, it does member-definition search
2418 public bool IsBaseTypeDefinition (TypeSpec baseType)
2420 // RootContext check
2421 if (TypeBuilder == null)
2426 if (type.MemberDefinition == baseType.MemberDefinition)
2429 type = type.BaseType;
2430 } while (type != null);
2435 public override bool IsClsComplianceRequired ()
2438 return PartialContainer.IsClsComplianceRequired ();
2440 return base.IsClsComplianceRequired ();
2443 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2445 return Module.DeclaringAssembly == assembly;
2448 public virtual bool IsUnmanagedType ()
2453 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2455 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2459 // Public function used to locate types.
2461 // Returns: Type or null if they type can not be found.
2463 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2465 FullNamedExpression e;
2466 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2472 var tp = CurrentTypeParameters;
2474 TypeParameter tparam = tp.Find (name);
2476 e = new TypeParameterExpr (tparam, Location.Null);
2481 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2483 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2484 e = new TypeExpression (t, Location.Null);
2486 var errors = Compiler.Report.Errors;
2487 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2489 // TODO: LookupNamespaceOrType does more than just lookup. The result
2490 // cannot be cached or the error reporting won't happen
2491 if (errors != Compiler.Report.Errors)
2496 // TODO MemberCache: How to cache arity stuff ?
2497 if (arity == 0 && mode == LookupMode.Normal)
2503 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2505 // Has any nested type
2506 // Does not work, because base type can have
2507 //if (PartialContainer.Types == null)
2510 var container = PartialContainer.CurrentType;
2511 return MemberCache.FindNestedType (container, name, arity);
2514 public void Mark_HasEquals ()
2516 cached_method |= CachedMethods.Equals;
2519 public void Mark_HasGetHashCode ()
2521 cached_method |= CachedMethods.GetHashCode;
2524 public override void WriteDebugSymbol (MonoSymbolFile file)
2529 foreach (var m in members) {
2530 m.WriteDebugSymbol (file);
2535 /// Method container contains Equals method
2537 public bool HasEquals {
2539 return (cached_method & CachedMethods.Equals) != 0;
2544 /// Method container contains GetHashCode method
2546 public bool HasGetHashCode {
2548 return (cached_method & CachedMethods.GetHashCode) != 0;
2552 public bool HasStaticFieldInitializer {
2554 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2558 cached_method |= CachedMethods.HasStaticFieldInitializer;
2560 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2564 public override string DocCommentHeader {
2565 get { return "T:"; }
2569 public abstract class ClassOrStruct : TypeDefinition
2571 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2573 SecurityType declarative_security;
2574 protected Constructor generated_primary_constructor;
2576 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2577 : base (parent, name, attrs, kind)
2581 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2583 protected override TypeAttributes TypeAttr {
2585 TypeAttributes ta = base.TypeAttr;
2586 if (!has_static_constructor)
2587 ta |= TypeAttributes.BeforeFieldInit;
2589 if (Kind == MemberKind.Class) {
2590 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2592 ta |= StaticClassAttribute;
2594 ta |= TypeAttributes.SequentialLayout;
2601 public override void AddNameToContainer (MemberCore symbol, string name)
2603 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2604 if (symbol is TypeParameter) {
2605 Report.Error (694, symbol.Location,
2606 "Type parameter `{0}' has same name as containing type, or method",
2607 symbol.GetSignatureForError ());
2611 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2612 if (imb == null || !imb.IsExplicitImpl) {
2613 Report.SymbolRelatedToPreviousError (this);
2614 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2615 symbol.GetSignatureForError ());
2620 base.AddNameToContainer (symbol, name);
2623 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2625 if (a.IsValidSecurityAttribute ()) {
2626 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2630 if (a.Type == pa.StructLayout) {
2631 PartialContainer.HasStructLayout = true;
2632 if (a.IsExplicitLayoutKind ())
2633 PartialContainer.HasExplicitLayout = true;
2636 if (a.Type == pa.Dynamic) {
2637 a.Error_MisusedDynamicAttribute ();
2641 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2645 /// Defines the default constructors
2647 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2649 // The default instance constructor is public
2650 // If the class is abstract, the default constructor is protected
2651 // The default static constructor is private
2654 ParametersCompiled parameters = null;
2656 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2657 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2659 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2660 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2663 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2664 if (Kind == MemberKind.Class)
2665 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2667 if (PrimaryConstructorParameters != null && !is_static)
2668 c.IsPrimaryConstructor = true;
2670 AddConstructor (c, true);
2671 if (PrimaryConstructorBlock == null) {
2672 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2673 IsCompilerGenerated = true
2676 c.Block = PrimaryConstructorBlock;
2682 protected override bool DoDefineMembers ()
2684 CheckProtectedModifier ();
2686 if (PrimaryConstructorParameters != null) {
2687 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2688 if (p.Name == MemberName.Name) {
2689 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2690 GetSignatureForError ());
2693 if (CurrentTypeParameters != null) {
2694 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2695 var tp = CurrentTypeParameters [i];
2696 if (p.Name == tp.Name) {
2697 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2698 GetSignatureForError (), p.GetSignatureForError ());
2705 base.DoDefineMembers ();
2710 public override void Emit ()
2712 if (!has_static_constructor && HasStaticFieldInitializer) {
2713 var c = DefineDefaultConstructor (true);
2719 if (declarative_security != null) {
2720 foreach (var de in declarative_security) {
2722 TypeBuilder.__AddDeclarativeSecurity (de);
2724 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2732 public sealed class Class : ClassOrStruct
2734 const Modifiers AllowedModifiers =
2737 Modifiers.PROTECTED |
2738 Modifiers.INTERNAL |
2740 Modifiers.ABSTRACT |
2745 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2746 : base (parent, name, attrs, MemberKind.Class)
2748 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2749 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2750 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2753 public override void Accept (StructuralVisitor visitor)
2755 visitor.Visit (this);
2758 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2760 var pmn = MemberName;
2761 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2762 Report.Error (537, Location,
2763 "The class System.Object cannot have a base class or implement an interface.");
2765 base.SetBaseTypes (baseTypes);
2768 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2770 if (a.Type == pa.AttributeUsage) {
2771 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2772 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2776 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2777 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2781 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2782 a.Error_MissingGuidAttribute ();
2786 if (a.Type == pa.Extension) {
2787 a.Error_MisusedExtensionAttribute ();
2791 if (a.Type.IsConditionallyExcluded (this))
2794 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2797 public override AttributeTargets AttributeTargets {
2799 return AttributeTargets.Class;
2803 protected override bool DoDefineMembers ()
2805 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2806 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2809 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2810 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2814 if (PrimaryConstructorParameters != null) {
2815 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2816 PrimaryConstructorParameters = null;
2819 foreach (var m in Members) {
2820 if (m is Operator) {
2821 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2825 if (m is Destructor) {
2826 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2831 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2835 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2838 if (m is Constructor) {
2839 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2843 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2846 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2847 generated_primary_constructor = DefineDefaultConstructor (false);
2850 return base.DoDefineMembers ();
2853 public override void Emit ()
2857 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2858 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2860 if (base_type != null && base_type.HasDynamicElement) {
2861 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2865 public override void GetCompletionStartingWith (string prefix, List<string> results)
2867 base.GetCompletionStartingWith (prefix, results);
2870 while (bt != null) {
2871 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2876 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2878 var ifaces = base.ResolveBaseTypes (out base_class);
2880 if (base_class == null) {
2881 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2882 base_type = Compiler.BuiltinTypes.Object;
2884 if (base_type.IsGenericParameter){
2885 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2886 GetSignatureForError (), base_type.GetSignatureForError ());
2887 } else if (base_type.IsStatic) {
2888 Report.SymbolRelatedToPreviousError (base_type);
2889 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2890 GetSignatureForError (), base_type.GetSignatureForError ());
2891 } else if (base_type.IsSealed) {
2892 Report.SymbolRelatedToPreviousError (base_type);
2893 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2894 GetSignatureForError (), base_type.GetSignatureForError ());
2895 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2896 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2897 GetSignatureForError (), base_type.GetSignatureForError ());
2900 switch (base_type.BuiltinType) {
2901 case BuiltinTypeSpec.Type.Enum:
2902 case BuiltinTypeSpec.Type.ValueType:
2903 case BuiltinTypeSpec.Type.MulticastDelegate:
2904 case BuiltinTypeSpec.Type.Delegate:
2905 case BuiltinTypeSpec.Type.Array:
2906 if (!(spec is BuiltinTypeSpec)) {
2907 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2908 GetSignatureForError (), base_type.GetSignatureForError ());
2910 base_type = Compiler.BuiltinTypes.Object;
2915 if (!IsAccessibleAs (base_type)) {
2916 Report.SymbolRelatedToPreviousError (base_type);
2917 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2918 base_type.GetSignatureForError (), GetSignatureForError ());
2922 if (PartialContainer.IsStatic && ifaces != null) {
2923 foreach (var t in ifaces)
2924 Report.SymbolRelatedToPreviousError (t);
2925 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2931 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2932 /// Valid only for attribute classes.
2933 public override string[] ConditionalConditions ()
2935 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2938 caching_flags &= ~Flags.Excluded_Undetected;
2940 if (OptAttributes == null)
2943 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2947 string[] conditions = new string[attrs.Length];
2948 for (int i = 0; i < conditions.Length; ++i)
2949 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2951 caching_flags |= Flags.Excluded;
2956 public sealed class Struct : ClassOrStruct
2958 bool is_unmanaged, has_unmanaged_check_done;
2962 // Modifiers allowed in a struct declaration
2964 const Modifiers AllowedModifiers =
2967 Modifiers.PROTECTED |
2968 Modifiers.INTERNAL |
2972 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2973 : base (parent, name, attrs, MemberKind.Struct)
2975 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2976 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2977 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2980 public override AttributeTargets AttributeTargets {
2982 return AttributeTargets.Struct;
2986 public override void Accept (StructuralVisitor visitor)
2988 visitor.Visit (this);
2991 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2993 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2996 // When struct constains fixed fixed and struct layout has explicitly
2997 // set CharSet, its value has to be propagated to compiler generated
3000 if (a.Type == pa.StructLayout) {
3001 var value = a.GetNamedValue ("CharSet");
3005 for (int i = 0; i < Members.Count; ++i) {
3006 FixedField ff = Members [i] as FixedField;
3010 ff.CharSet = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3015 bool CheckStructCycles ()
3021 foreach (var member in Members) {
3022 var field = member as Field;
3026 TypeSpec ftype = field.Spec.MemberType;
3027 if (!ftype.IsStruct)
3030 if (ftype is BuiltinTypeSpec)
3033 foreach (var targ in ftype.TypeArguments) {
3034 if (!CheckFieldTypeCycle (targ)) {
3035 Report.Error (523, field.Location,
3036 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3037 field.GetSignatureForError (), ftype.GetSignatureForError ());
3043 // Static fields of exactly same type are allowed
3045 if (field.IsStatic && ftype == CurrentType)
3048 if (!CheckFieldTypeCycle (ftype)) {
3049 Report.Error (523, field.Location,
3050 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3051 field.GetSignatureForError (), ftype.GetSignatureForError ());
3060 static bool CheckFieldTypeCycle (TypeSpec ts)
3062 var fts = ts.MemberDefinition as Struct;
3066 return fts.CheckStructCycles ();
3069 protected override bool DoDefineMembers ()
3071 if (PrimaryConstructorParameters != null)
3072 generated_primary_constructor = DefineDefaultConstructor (false);
3074 return base.DoDefineMembers ();
3077 public override void Emit ()
3079 CheckStructCycles ();
3084 bool HasExplicitConstructor ()
3086 foreach (var m in Members) {
3087 var c = m as Constructor;
3091 if (!c.ParameterInfo.IsEmpty)
3098 public override bool IsUnmanagedType ()
3100 if (has_unmanaged_check_done)
3101 return is_unmanaged;
3103 if (requires_delayed_unmanagedtype_check)
3106 var parent_def = Parent.PartialContainer;
3107 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3108 has_unmanaged_check_done = true;
3112 if (first_nonstatic_field != null) {
3113 requires_delayed_unmanagedtype_check = true;
3115 foreach (var member in Members) {
3116 var f = member as Field;
3123 // It can happen when recursive unmanaged types are defined
3124 // struct S { S* s; }
3125 TypeSpec mt = f.MemberType;
3133 has_unmanaged_check_done = true;
3137 has_unmanaged_check_done = true;
3140 is_unmanaged = true;
3144 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3146 var ifaces = base.ResolveBaseTypes (out base_class);
3147 base_type = Compiler.BuiltinTypes.ValueType;
3151 public override void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
3153 if ((field.ModFlags & Modifiers.STATIC) == 0 && !HasExplicitConstructor ()) {
3154 Report.Error (8054, field.Location, "`{0}': Structs without explicit constructors cannot contain members with initializers",
3155 field.GetSignatureForError ());
3160 base.RegisterFieldForInitialization (field, expression);
3167 public sealed class Interface : TypeDefinition {
3170 /// Modifiers allowed in a class declaration
3172 const Modifiers AllowedModifiers =
3175 Modifiers.PROTECTED |
3176 Modifiers.INTERNAL |
3180 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3181 : base (parent, name, attrs, MemberKind.Interface)
3183 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3185 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3186 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3191 public override AttributeTargets AttributeTargets {
3193 return AttributeTargets.Interface;
3197 protected override TypeAttributes TypeAttr {
3199 const TypeAttributes DefaultTypeAttributes =
3200 TypeAttributes.AutoLayout |
3201 TypeAttributes.Abstract |
3202 TypeAttributes.Interface;
3204 return base.TypeAttr | DefaultTypeAttributes;
3210 public override void Accept (StructuralVisitor visitor)
3212 visitor.Visit (this);
3215 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3217 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3218 a.Error_MissingGuidAttribute ();
3222 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3225 protected override bool VerifyClsCompliance ()
3227 if (!base.VerifyClsCompliance ())
3230 if (iface_exprs != null) {
3231 foreach (var iface in iface_exprs) {
3232 if (iface.IsCLSCompliant ())
3235 Report.SymbolRelatedToPreviousError (iface);
3236 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3237 GetSignatureForError (), iface.GetSignatureForError ());
3245 public abstract class InterfaceMemberBase : MemberBase
3248 // Common modifiers allowed in a class declaration
3250 protected const Modifiers AllowedModifiersClass =
3253 Modifiers.PROTECTED |
3254 Modifiers.INTERNAL |
3259 Modifiers.OVERRIDE |
3260 Modifiers.ABSTRACT |
3265 // Common modifiers allowed in a struct declaration
3267 protected const Modifiers AllowedModifiersStruct =
3270 Modifiers.PROTECTED |
3271 Modifiers.INTERNAL |
3274 Modifiers.OVERRIDE |
3279 // Common modifiers allowed in a interface declaration
3281 protected const Modifiers AllowedModifiersInterface =
3286 // Whether this is an interface member.
3288 public bool IsInterface;
3291 // If true, this is an explicit interface implementation
3293 public readonly bool IsExplicitImpl;
3295 protected bool is_external_implementation;
3298 // The interface type we are explicitly implementing
3300 public TypeSpec InterfaceType;
3303 // The method we're overriding if this is an override method.
3305 protected MethodSpec base_method;
3307 readonly Modifiers explicit_mod_flags;
3308 public MethodAttributes flags;
3310 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3311 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3313 IsInterface = parent.Kind == MemberKind.Interface;
3314 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3315 explicit_mod_flags = mod;
3318 public abstract Variance ExpectedMemberTypeVariance { get; }
3320 protected override bool CheckBase ()
3322 if (!base.CheckBase ())
3325 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3326 CheckForDuplications ();
3331 // For System.Object only
3332 if (Parent.BaseType == null)
3335 MemberSpec candidate;
3336 bool overrides = false;
3337 var base_member = FindBaseMember (out candidate, ref overrides);
3339 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3340 if (base_member == null) {
3341 if (candidate == null) {
3342 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3343 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3344 "object.Finalize()");
3346 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3347 GetSignatureForError (), SimpleName.GetMemberType (this));
3350 Report.SymbolRelatedToPreviousError (candidate);
3352 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3353 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3354 else if (this is PropertyBase)
3355 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3356 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3358 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3359 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3366 // Handles ambiguous overrides
3368 if (candidate != null) {
3369 Report.SymbolRelatedToPreviousError (candidate);
3370 Report.SymbolRelatedToPreviousError (base_member);
3372 // Get member definition for error reporting
3373 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3374 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3376 Report.Error (462, Location,
3377 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3378 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3381 if (!CheckOverrideAgainstBase (base_member))
3384 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3386 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3387 Report.SymbolRelatedToPreviousError (base_member);
3388 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3389 GetSignatureForError (), base_member.GetSignatureForError ());
3392 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3393 Report.SymbolRelatedToPreviousError (base_member);
3394 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3395 GetSignatureForError (), base_member.GetSignatureForError ());
3399 base_method = base_member as MethodSpec;
3403 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3404 base_member = candidate;
3406 if (base_member == null) {
3407 if ((ModFlags & Modifiers.NEW) != 0) {
3408 if (base_member == null) {
3409 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3410 GetSignatureForError ());
3414 if ((ModFlags & Modifiers.NEW) == 0) {
3415 ModFlags |= Modifiers.NEW;
3416 if (!IsCompilerGenerated) {
3417 Report.SymbolRelatedToPreviousError (base_member);
3418 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3419 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",
3420 GetSignatureForError (), base_member.GetSignatureForError ());
3422 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3423 GetSignatureForError (), base_member.GetSignatureForError ());
3428 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3429 Report.SymbolRelatedToPreviousError (base_member);
3430 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3431 GetSignatureForError (), base_member.GetSignatureForError ());
3438 protected virtual bool CheckForDuplications ()
3440 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3444 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3445 // that have been defined.
3447 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3451 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3452 Report.SymbolRelatedToPreviousError (base_member);
3453 Report.Error (506, Location,
3454 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3455 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3459 // Now we check that the overriden method is not final
3460 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3461 Report.SymbolRelatedToPreviousError (base_member);
3462 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3463 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3467 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3468 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3469 Report.SymbolRelatedToPreviousError (base_member);
3470 if (this is PropertyBasedMember) {
3471 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3472 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3474 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3475 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3483 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3485 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3486 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3488 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3490 // It must be at least "protected"
3492 if ((thisp & Modifiers.PROTECTED) == 0) {
3497 // when overriding protected internal, the method can be declared
3498 // protected internal only within the same assembly or assembly
3499 // which has InternalsVisibleTo
3501 if ((thisp & Modifiers.INTERNAL) != 0) {
3502 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3506 // protected overriding protected internal inside same assembly
3507 // requires internal modifier as well
3509 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3516 return thisp == base_classp;
3519 public override bool Define ()
3522 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3523 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3525 flags = MethodAttributes.Public |
3526 MethodAttributes.Abstract |
3527 MethodAttributes.HideBySig |
3528 MethodAttributes.NewSlot |
3529 MethodAttributes.Virtual;
3531 Parent.PartialContainer.MethodModifiersValid (this);
3533 flags = ModifiersExtensions.MethodAttr (ModFlags);
3536 if (IsExplicitImpl) {
3537 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3538 if (InterfaceType == null)
3541 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3542 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3543 GetSignatureForError ());
3546 if (!InterfaceType.IsInterface) {
3547 Report.SymbolRelatedToPreviousError (InterfaceType);
3548 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3549 InterfaceType.GetSignatureForError ());
3551 Parent.PartialContainer.VerifyImplements (this);
3554 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3556 allowed_explicit |= Modifiers.ASYNC;
3558 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3561 return base.Define ();
3564 protected bool DefineParameters (ParametersCompiled parameters)
3566 if (!parameters.Resolve (this))
3570 for (int i = 0; i < parameters.Count; ++i) {
3571 Parameter p = parameters [i];
3573 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3574 p.Warning_UselessOptionalParameter (Report);
3576 if (p.CheckAccessibility (this))
3579 TypeSpec t = parameters.Types [i];
3580 Report.SymbolRelatedToPreviousError (t);
3581 if (this is Indexer)
3582 Report.Error (55, Location,
3583 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3584 t.GetSignatureForError (), GetSignatureForError ());
3585 else if (this is Operator)
3586 Report.Error (57, Location,
3587 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3588 t.GetSignatureForError (), GetSignatureForError ());
3590 Report.Error (51, Location,
3591 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3592 t.GetSignatureForError (), GetSignatureForError ());
3598 protected override void DoMemberTypeDependentChecks ()
3600 base.DoMemberTypeDependentChecks ();
3602 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3605 public override void Emit()
3607 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3608 // We are more strict than csc and report this as an error because SRE does not allow emit that
3609 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3610 if (this is Constructor) {
3611 Report.Warning (824, 1, Location,
3612 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3614 Report.Warning (626, 1, Location,
3615 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3616 GetSignatureForError ());
3623 public override bool EnableOverloadChecks (MemberCore overload)
3626 // Two members can differ in their explicit interface
3627 // type parameter only
3629 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3630 if (imb != null && imb.IsExplicitImpl) {
3631 if (IsExplicitImpl) {
3632 caching_flags |= Flags.MethodOverloadsExist;
3637 return IsExplicitImpl;
3640 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3642 var base_modifiers = base_member.Modifiers;
3644 // Remove internal modifier from types which are not internally accessible
3645 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3646 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3647 base_modifiers = Modifiers.PROTECTED;
3649 Report.SymbolRelatedToPreviousError (base_member);
3650 Report.Error (507, member.Location,
3651 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3652 member.GetSignatureForError (),
3653 ModifiersExtensions.AccessibilityName (base_modifiers),
3654 base_member.GetSignatureForError ());
3657 protected void Error_StaticReturnType ()
3659 Report.Error (722, Location,
3660 "`{0}': static types cannot be used as return types",
3661 MemberType.GetSignatureForError ());
3665 /// Gets base method and its return type
3667 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3669 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3673 // The "short" name of this property / indexer / event. This is the
3674 // name without the explicit interface.
3676 public string ShortName {
3677 get { return MemberName.Name; }
3681 // Returns full metadata method name
3683 public string GetFullName (MemberName name)
3685 return GetFullName (name.Name);
3688 public string GetFullName (string name)
3690 if (!IsExplicitImpl)
3694 // When dealing with explicit members a full interface type
3695 // name is added to member name to avoid possible name conflicts
3697 // We use CSharpName which gets us full name with benefit of
3698 // replacing predefined names which saves some space and name
3701 return InterfaceType.GetSignatureForError () + "." + name;
3704 public override string GetSignatureForDocumentation ()
3707 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetExplicitNameSignatureForDocumentation () + "#" + ShortName;
3709 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3712 public override bool IsUsed
3714 get { return IsExplicitImpl || base.IsUsed; }
3717 public override void SetConstraints (List<Constraints> constraints_list)
3719 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3720 Report.Error (460, Location,
3721 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3722 GetSignatureForError ());
3725 base.SetConstraints (constraints_list);
3729 public abstract class MemberBase : MemberCore
3731 protected FullNamedExpression type_expr;
3732 protected TypeSpec member_type;
3733 public new TypeDefinition Parent;
3735 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3736 : base (parent, name, attrs)
3738 this.Parent = parent;
3739 this.type_expr = type;
3741 if (name != MemberName.Null)
3742 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3747 public TypeSpec MemberType {
3753 public FullNamedExpression TypeExpression {
3762 // Main member define entry
3764 public override bool Define ()
3766 DoMemberTypeIndependentChecks ();
3769 // Returns false only when type resolution failed
3771 if (!ResolveMemberType ())
3774 DoMemberTypeDependentChecks ();
3779 // Any type_name independent checks
3781 protected virtual void DoMemberTypeIndependentChecks ()
3783 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3784 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3785 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3786 GetSignatureForError (), Parent.GetSignatureForError ());
3791 // Any type_name dependent checks
3793 protected virtual void DoMemberTypeDependentChecks ()
3795 // verify accessibility
3796 if (!IsAccessibleAs (MemberType)) {
3797 Report.SymbolRelatedToPreviousError (MemberType);
3798 if (this is Property)
3799 Report.Error (53, Location,
3800 "Inconsistent accessibility: property type `" +
3801 MemberType.GetSignatureForError () + "' is less " +
3802 "accessible than property `" + GetSignatureForError () + "'");
3803 else if (this is Indexer)
3804 Report.Error (54, Location,
3805 "Inconsistent accessibility: indexer return type `" +
3806 MemberType.GetSignatureForError () + "' is less " +
3807 "accessible than indexer `" + GetSignatureForError () + "'");
3808 else if (this is MethodCore) {
3809 if (this is Operator)
3810 Report.Error (56, Location,
3811 "Inconsistent accessibility: return type `" +
3812 MemberType.GetSignatureForError () + "' is less " +
3813 "accessible than operator `" + GetSignatureForError () + "'");
3815 Report.Error (50, Location,
3816 "Inconsistent accessibility: return type `" +
3817 MemberType.GetSignatureForError () + "' is less " +
3818 "accessible than method `" + GetSignatureForError () + "'");
3819 } else if (this is Event) {
3820 Report.Error (7025, Location,
3821 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3822 MemberType.GetSignatureForError (), GetSignatureForError ());
3824 Report.Error (52, Location,
3825 "Inconsistent accessibility: field type `" +
3826 MemberType.GetSignatureForError () + "' is less " +
3827 "accessible than field `" + GetSignatureForError () + "'");
3832 protected void IsTypePermitted ()
3834 if (MemberType.IsSpecialRuntimeType) {
3835 if (Parent is StateMachine) {
3836 Report.Error (4012, Location,
3837 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3838 MemberType.GetSignatureForError ());
3839 } else if (Parent is HoistedStoreyClass) {
3840 Report.Error (4013, Location,
3841 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3842 MemberType.GetSignatureForError ());
3844 Report.Error (610, Location,
3845 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3850 protected virtual bool CheckBase ()
3852 CheckProtectedModifier ();
3857 public override string GetSignatureForDocumentation ()
3859 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3862 protected virtual bool ResolveMemberType ()
3864 if (member_type != null)
3865 throw new InternalErrorException ("Multi-resolve");
3867 member_type = type_expr.ResolveAsType (this);
3868 return member_type != null;