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;
48 protected List<TypeContainer> containers;
50 TypeDefinition main_container;
52 protected Dictionary<string, MemberCore> defined_names;
54 protected bool is_defined;
56 public int CounterAnonymousMethods { get; set; }
57 public int CounterAnonymousContainers { get; set; }
58 public int CounterSwitchTypes { get; set; }
60 protected TypeContainer (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
61 : base (parent, name, attrs)
64 defined_names = new Dictionary<string, MemberCore> ();
67 public override TypeSpec CurrentType {
73 public Dictionary<string, MemberCore> DefinedNames {
79 public TypeDefinition PartialContainer {
81 return main_container;
84 main_container = value;
88 public IList<TypeContainer> Containers {
95 // Any unattached attributes during parsing get added here. Used
98 public Attributes UnattachedAttributes {
102 public void AddCompilerGeneratedClass (CompilerGeneratedContainer c)
104 AddTypeContainerMember (c);
107 public virtual void AddPartial (TypeDefinition next_part)
110 (PartialContainer ?? this).defined_names.TryGetValue (next_part.MemberName.Basename, out mc);
112 AddPartial (next_part, mc as TypeDefinition);
115 protected void AddPartial (TypeDefinition next_part, TypeDefinition existing)
117 next_part.ModFlags |= Modifiers.PARTIAL;
119 if (existing == null) {
120 AddTypeContainer (next_part);
124 if ((existing.ModFlags & Modifiers.PARTIAL) == 0) {
125 if (existing.Kind != next_part.Kind) {
126 AddTypeContainer (next_part);
128 Report.SymbolRelatedToPreviousError (next_part);
129 Error_MissingPartialModifier (existing);
135 if (existing.Kind != next_part.Kind) {
136 Report.SymbolRelatedToPreviousError (existing);
137 Report.Error (261, next_part.Location,
138 "Partial declarations of `{0}' must be all classes, all structs or all interfaces",
139 next_part.GetSignatureForError ());
142 if ((existing.ModFlags & Modifiers.AccessibilityMask) != (next_part.ModFlags & Modifiers.AccessibilityMask) &&
143 ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0 &&
144 (next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) == 0)) {
145 Report.SymbolRelatedToPreviousError (existing);
146 Report.Error (262, next_part.Location,
147 "Partial declarations of `{0}' have conflicting accessibility modifiers",
148 next_part.GetSignatureForError ());
151 var tc_names = existing.CurrentTypeParameters;
152 if (tc_names != null) {
153 for (int i = 0; i < tc_names.Count; ++i) {
154 var tp = next_part.MemberName.TypeParameters[i];
155 if (tc_names[i].MemberName.Name != tp.MemberName.Name) {
156 Report.SymbolRelatedToPreviousError (existing.Location, "");
157 Report.Error (264, next_part.Location, "Partial declarations of `{0}' must have the same type parameter names in the same order",
158 next_part.GetSignatureForError ());
162 if (tc_names[i].Variance != tp.Variance) {
163 Report.SymbolRelatedToPreviousError (existing.Location, "");
164 Report.Error (1067, next_part.Location, "Partial declarations of `{0}' must have the same type parameter variance modifiers",
165 next_part.GetSignatureForError ());
171 if ((next_part.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
172 existing.ModFlags |= next_part.ModFlags & ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
173 } else if ((existing.ModFlags & Modifiers.DEFAULT_ACCESS_MODIFIER) != 0) {
174 existing.ModFlags &= ~(Modifiers.DEFAULT_ACCESS_MODIFIER | Modifiers.AccessibilityMask);
175 existing.ModFlags |= next_part.ModFlags;
177 existing.ModFlags |= next_part.ModFlags;
180 existing.Definition.Modifiers = existing.ModFlags;
182 if (next_part.attributes != null) {
183 if (existing.attributes == null)
184 existing.attributes = next_part.attributes;
186 existing.attributes.AddAttributes (next_part.attributes.Attrs);
189 next_part.PartialContainer = existing;
191 existing.AddPartialPart (next_part);
193 AddTypeContainerMember (next_part);
196 public virtual void AddTypeContainer (TypeContainer tc)
198 AddTypeContainerMember (tc);
200 var tparams = tc.MemberName.TypeParameters;
201 if (tparams != null && tc.PartialContainer != null) {
202 var td = (TypeDefinition) tc;
203 for (int i = 0; i < tparams.Count; ++i) {
205 if (tp.MemberName == null)
208 td.AddNameToContainer (tp, tp.Name);
213 protected virtual void AddTypeContainerMember (TypeContainer tc)
218 public virtual void CloseContainer ()
220 if (containers != null) {
221 foreach (TypeContainer tc in containers) {
222 tc.CloseContainer ();
227 public virtual void CreateMetadataName (StringBuilder sb)
229 if (Parent != null && Parent.MemberName != null)
230 Parent.CreateMetadataName (sb);
232 MemberName.CreateMetadataName (sb);
235 public virtual bool CreateContainer ()
237 if (containers != null) {
238 foreach (TypeContainer tc in containers) {
239 tc.CreateContainer ();
246 public override bool Define ()
248 if (containers != null) {
249 foreach (TypeContainer tc in containers) {
254 // Release cache used by parser only
255 if (Module.Evaluator == null) {
256 defined_names = null;
258 defined_names.Clear ();
264 public virtual void PrepareEmit ()
266 if (containers != null) {
267 foreach (var t in containers) {
270 } catch (Exception e) {
271 if (MemberName == MemberName.Null)
274 throw new InternalErrorException (t, e);
280 public virtual bool DefineContainer ()
287 DoDefineContainer ();
289 if (containers != null) {
290 foreach (TypeContainer tc in containers) {
292 tc.DefineContainer ();
293 } catch (Exception e) {
294 if (MemberName == MemberName.Null)
297 throw new InternalErrorException (tc, e);
305 public virtual void ExpandBaseInterfaces ()
307 if (containers != null) {
308 foreach (TypeContainer tc in containers) {
309 tc.ExpandBaseInterfaces ();
314 protected virtual void DefineNamespace ()
316 if (containers != null) {
317 foreach (var tc in containers) {
319 tc.DefineNamespace ();
320 } catch (Exception e) {
321 throw new InternalErrorException (tc, e);
327 protected virtual void DoDefineContainer ()
331 public virtual void EmitContainer ()
333 if (containers != null) {
334 for (int i = 0; i < containers.Count; ++i)
335 containers[i].EmitContainer ();
339 protected void Error_MissingPartialModifier (MemberCore type)
341 Report.Error (260, type.Location,
342 "Missing partial modifier on declaration of type `{0}'. Another partial declaration of this type exists",
343 type.GetSignatureForError ());
346 public override string GetSignatureForDocumentation ()
348 if (Parent != null && Parent.MemberName != null)
349 return Parent.GetSignatureForDocumentation () + "." + MemberName.GetSignatureForDocumentation ();
351 return MemberName.GetSignatureForDocumentation ();
354 public override string GetSignatureForError ()
356 if (Parent != null && Parent.MemberName != null)
357 return Parent.GetSignatureForError () + "." + MemberName.GetSignatureForError ();
359 return MemberName.GetSignatureForError ();
362 public virtual string GetSignatureForMetadata ()
364 var sb = new StringBuilder ();
365 CreateMetadataName (sb);
366 return sb.ToString ();
369 public virtual void RemoveContainer (TypeContainer cont)
371 if (containers != null)
372 containers.Remove (cont);
374 var tc = Parent == Module ? Module : this;
375 tc.defined_names.Remove (cont.MemberName.Basename);
378 public virtual void VerifyMembers ()
380 if (containers != null) {
381 foreach (TypeContainer tc in containers)
386 public override void WriteDebugSymbol (MonoSymbolFile file)
388 if (containers != null) {
389 foreach (TypeContainer tc in containers) {
390 tc.WriteDebugSymbol (file);
396 public abstract class TypeDefinition : TypeContainer, ITypeDefinition
399 // Different context is needed when resolving type container base
400 // types. Type names come from the parent scope but type parameter
401 // names from the container scope.
403 public struct BaseContext : IMemberContext
407 public BaseContext (TypeContainer tc)
412 #region IMemberContext Members
414 public CompilerContext Compiler {
415 get { return tc.Compiler; }
418 public TypeSpec CurrentType {
419 get { return tc.PartialContainer.CurrentType; }
422 public TypeParameters CurrentTypeParameters {
423 get { return tc.PartialContainer.CurrentTypeParameters; }
426 public MemberCore CurrentMemberDefinition {
430 public bool IsObsolete {
431 get { return tc.IsObsolete; }
434 public bool IsUnsafe {
435 get { return tc.IsUnsafe; }
438 public bool IsStatic {
439 get { return tc.IsStatic; }
442 public ModuleContainer Module {
443 get { return tc.Module; }
446 public string GetSignatureForError ()
448 return tc.GetSignatureForError ();
451 public ExtensionMethodCandidates LookupExtensionMethod (string name, int arity)
456 public FullNamedExpression LookupNamespaceAlias (string name)
458 return tc.Parent.LookupNamespaceAlias (name);
461 public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
464 var tp = CurrentTypeParameters;
466 TypeParameter t = tp.Find (name);
468 return new TypeParameterExpr (t, loc);
472 return tc.Parent.LookupNamespaceOrType (name, arity, mode, loc);
482 GetHashCode = 1 << 1,
483 HasStaticFieldInitializer = 1 << 2
486 readonly List<MemberCore> members;
488 // Holds a list of fields that have initializers
489 protected List<FieldInitializer> initialized_fields;
491 // Holds a list of static fields that have initializers
492 protected List<FieldInitializer> initialized_static_fields;
494 Dictionary<MethodSpec, Method> hoisted_base_call_proxies;
496 Dictionary<string, FullNamedExpression> Cache = new Dictionary<string, FullNamedExpression> ();
499 // Points to the first non-static field added to the container.
501 // This is an arbitrary choice. We are interested in looking at _some_ non-static field,
502 // and the first one's as good as any.
504 protected FieldBase first_nonstatic_field;
507 // This one is computed after we can distinguish interfaces
508 // from classes from the arraylist `type_bases'
510 protected TypeSpec base_type;
511 FullNamedExpression base_type_expr; // TODO: It's temporary variable
512 protected TypeSpec[] iface_exprs;
514 protected List<FullNamedExpression> type_bases;
516 // Partial parts for classes only
517 List<TypeDefinition> class_partial_parts;
519 TypeDefinition InTransit;
521 public TypeBuilder TypeBuilder;
522 GenericTypeParameterBuilder[] all_tp_builders;
524 // All recursive type parameters put together sharing same
525 // TypeParameter instances
527 TypeParameters all_type_parameters;
529 public const string DefaultIndexerName = "Item";
531 bool has_normal_indexers;
534 bool members_defined;
535 bool members_defined_ok;
536 protected bool has_static_constructor;
538 private CachedMethods cached_method;
540 protected TypeSpec spec;
541 TypeSpec current_type;
543 public int DynamicSitesCounter;
544 public int AnonymousMethodsCounter;
545 public int MethodGroupsCounter;
547 static readonly string[] attribute_targets = new [] { "type" };
548 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
551 /// The pending methods that need to be implemented
552 // (interfaces or abstract methods)
554 PendingImplementation pending;
556 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
557 : base (parent, name, attrs, kind)
559 PartialContainer = this;
560 members = new List<MemberCore> ();
565 public List<FullNamedExpression> BaseTypeExpressions {
571 public override TypeSpec CurrentType {
573 if (current_type == null) {
574 if (IsGenericOrParentIsGeneric) {
576 // Switch to inflated version as it's used by all expressions
578 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
579 current_type = spec.MakeGenericType (this, targs);
589 public override TypeParameters CurrentTypeParameters {
591 return PartialContainer.MemberName.TypeParameters;
595 int CurrentTypeParametersStartIndex {
597 int total = all_tp_builders.Length;
598 if (CurrentTypeParameters != null) {
599 return total - CurrentTypeParameters.Count;
605 public virtual AssemblyDefinition DeclaringAssembly {
607 return Module.DeclaringAssembly;
611 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
613 return Module.DeclaringAssembly;
617 public TypeSpec Definition {
623 public bool HasMembersDefined {
625 return members_defined;
629 public bool HasInstanceConstructor {
631 return (caching_flags & Flags.HasInstanceConstructor) != 0;
634 caching_flags |= Flags.HasInstanceConstructor;
638 // Indicated whether container has StructLayout attribute set Explicit
639 public bool HasExplicitLayout {
640 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
641 set { caching_flags |= Flags.HasExplicitLayout; }
644 public bool HasOperators {
646 return (caching_flags & Flags.HasUserOperators) != 0;
649 caching_flags |= Flags.HasUserOperators;
653 public bool HasStructLayout {
654 get { return (caching_flags & Flags.HasStructLayout) != 0; }
655 set { caching_flags |= Flags.HasStructLayout; }
658 public TypeSpec[] Interfaces {
664 public bool IsGenericOrParentIsGeneric {
666 return all_type_parameters != null;
670 public bool IsTopLevel {
672 return !(Parent is TypeDefinition);
676 public bool IsPartial {
678 return (ModFlags & Modifiers.PARTIAL) != 0;
682 bool ITypeDefinition.IsTypeForwarder {
688 bool ITypeDefinition.IsCyclicTypeForwarder {
695 // Returns true for secondary partial containers
699 return PartialContainer != this;
703 public MemberCache MemberCache {
705 return spec.MemberCache;
709 public List<MemberCore> Members {
715 string ITypeDefinition.Namespace {
718 while (p.Kind != MemberKind.Namespace)
721 return p.MemberName == null ? null : p.GetSignatureForError ();
725 public ParametersCompiled PrimaryConstructorParameters { get; set; }
727 public Arguments PrimaryConstructorBaseArguments { get; set; }
729 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
731 public TypeParameters TypeParametersAll {
733 return all_type_parameters;
737 public override string[] ValidAttributeTargets {
739 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
745 public override void Accept (StructuralVisitor visitor)
747 visitor.Visit (this);
750 public void AddMember (MemberCore symbol)
752 if (symbol.MemberName.ExplicitInterface != null) {
753 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
754 Report.Error (541, symbol.Location,
755 "`{0}': explicit interface declaration can only be declared in a class or struct",
756 symbol.GetSignatureForError ());
760 AddNameToContainer (symbol, symbol.MemberName.Name);
761 members.Add (symbol);
764 public override void AddTypeContainer (TypeContainer tc)
766 AddNameToContainer (tc, tc.MemberName.Basename);
768 base.AddTypeContainer (tc);
771 protected override void AddTypeContainerMember (TypeContainer tc)
775 if (containers == null)
776 containers = new List<TypeContainer> ();
778 base.AddTypeContainerMember (tc);
782 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
784 public virtual void AddNameToContainer (MemberCore symbol, string name)
786 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
790 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
791 PartialContainer.defined_names.Add (name, symbol);
795 if (symbol.EnableOverloadChecks (mc))
798 InterfaceMemberBase im = mc as InterfaceMemberBase;
799 if (im != null && im.IsExplicitImpl)
802 Report.SymbolRelatedToPreviousError (mc);
803 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
804 Error_MissingPartialModifier (symbol);
808 if (symbol is TypeParameter) {
809 Report.Error (692, symbol.Location,
810 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
812 Report.Error (102, symbol.Location,
813 "The type `{0}' already contains a definition for `{1}'",
814 GetSignatureForError (), name);
820 public void AddConstructor (Constructor c)
822 AddConstructor (c, false);
825 public void AddConstructor (Constructor c, bool isDefault)
827 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
829 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
831 if (is_static && c.ParameterInfo.IsEmpty) {
832 PartialContainer.has_static_constructor = true;
834 PartialContainer.HasInstanceConstructor = true;
840 public bool AddField (FieldBase field)
844 if ((field.ModFlags & Modifiers.STATIC) != 0)
847 var first_field = PartialContainer.first_nonstatic_field;
848 if (first_field == null) {
849 PartialContainer.first_nonstatic_field = field;
853 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
854 Report.SymbolRelatedToPreviousError (first_field.Parent);
855 Report.Warning (282, 3, field.Location,
856 "struct instance field `{0}' found in different declaration from instance field `{1}'",
857 field.GetSignatureForError (), first_field.GetSignatureForError ());
863 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
865 public void AddIndexer (Indexer i)
870 public void AddOperator (Operator op)
872 PartialContainer.HasOperators = true;
876 public void AddPartialPart (TypeDefinition part)
878 if (Kind != MemberKind.Class)
881 if (class_partial_parts == null)
882 class_partial_parts = new List<TypeDefinition> ();
884 class_partial_parts.Add (part);
887 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
889 if (a.Target == AttributeTargets.Method) {
890 foreach (var m in members) {
891 var c = m as Constructor;
895 if (c.IsPrimaryConstructor) {
896 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
901 throw new InternalErrorException ();
904 if (has_normal_indexers && a.Type == pa.DefaultMember) {
905 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
909 if (a.Type == pa.Required) {
910 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
914 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
917 public override AttributeTargets AttributeTargets {
919 throw new NotSupportedException ();
923 public TypeSpec BaseType {
925 return spec.BaseType;
929 protected virtual TypeAttributes TypeAttr {
931 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
935 public int TypeParametersCount {
937 return MemberName.Arity;
941 TypeParameterSpec[] ITypeDefinition.TypeParameters {
943 var ctp = PartialContainer.CurrentTypeParameters;
944 return ctp == null ? TypeParameterSpec.EmptyTypes : ctp.Types;
948 public string GetAttributeDefaultMember ()
950 return indexer_name ?? DefaultIndexerName;
953 public bool IsComImport {
955 if (OptAttributes == null)
958 return OptAttributes.Contains (Module.PredefinedAttributes.ComImport);
962 public void RegisterFieldForInitialization (MemberCore field, FieldInitializer expression)
965 PartialContainer.RegisterFieldForInitialization (field, expression);
967 if ((field.ModFlags & Modifiers.STATIC) != 0){
968 if (initialized_static_fields == null) {
969 HasStaticFieldInitializer = true;
970 initialized_static_fields = new List<FieldInitializer> (4);
973 initialized_static_fields.Add (expression);
975 if (Kind == MemberKind.Struct) {
976 if (Compiler.Settings.Version != LanguageVersion.Experimental) {
977 Report.Error (573, expression.Location, "'{0}': Structs cannot have instance property or field initializers",
978 GetSignatureForError ());
982 if (initialized_fields == null)
983 initialized_fields = new List<FieldInitializer> (4);
985 initialized_fields.Add (expression);
989 public void ResolveFieldInitializers (BlockContext ec)
991 Debug.Assert (!IsPartialPart);
994 if (initialized_static_fields == null)
997 bool has_complex_initializer = !ec.Module.Compiler.Settings.Optimize;
999 ExpressionStatement [] init = new ExpressionStatement [initialized_static_fields.Count];
1000 for (i = 0; i < initialized_static_fields.Count; ++i) {
1001 FieldInitializer fi = initialized_static_fields [i];
1002 ExpressionStatement s = fi.ResolveStatement (ec);
1004 s = EmptyExpressionStatement.Instance;
1005 } else if (!fi.IsSideEffectFree) {
1006 has_complex_initializer = true;
1012 for (i = 0; i < initialized_static_fields.Count; ++i) {
1013 FieldInitializer fi = initialized_static_fields [i];
1015 // Need special check to not optimize code like this
1016 // static int a = b = 5;
1017 // static int b = 0;
1019 if (!has_complex_initializer && fi.IsDefaultInitializer)
1022 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1023 ec.CurrentBlock.AddScopeStatement (new StatementExpression (init [i]));
1029 if (initialized_fields == null)
1032 for (int i = 0; i < initialized_fields.Count; ++i) {
1033 FieldInitializer fi = initialized_fields [i];
1036 // Clone before resolving otherwise when field initializer is needed
1037 // in more than 1 constructor any resolve after the initial one would
1038 // only took the resolved expression which is problem for expressions
1039 // that generate extra expressions or code during Resolve phase
1041 var cloned = fi.Clone (new CloneContext ());
1043 ExpressionStatement s = fi.ResolveStatement (ec);
1045 initialized_fields [i] = new FieldInitializer (fi.Field, ErrorExpression.Instance, Location.Null);
1050 // Field is re-initialized to its default value => removed
1052 if (fi.IsDefaultInitializer && Kind != MemberKind.Struct && ec.Module.Compiler.Settings.Optimize)
1055 ec.AssignmentInfoOffset += fi.AssignmentOffset;
1056 ec.CurrentBlock.AddScopeStatement (new StatementExpression (s));
1057 initialized_fields [i] = (FieldInitializer) cloned;
1061 public override string DocComment {
1073 public PendingImplementation PendingImplementations {
1074 get { return pending; }
1077 internal override void GenerateDocComment (DocumentationBuilder builder)
1082 base.GenerateDocComment (builder);
1084 foreach (var member in members)
1085 member.GenerateDocComment (builder);
1088 public TypeSpec GetAttributeCoClass ()
1090 if (OptAttributes == null)
1093 Attribute a = OptAttributes.Search (Module.PredefinedAttributes.CoClass);
1097 return a.GetCoClassAttributeValue ();
1100 public AttributeUsageAttribute GetAttributeUsage (PredefinedAttribute pa)
1103 if (OptAttributes != null) {
1104 a = OptAttributes.Search (pa);
1110 return a.GetAttributeUsageAttribute ();
1113 public virtual CompilationSourceFile GetCompilationSourceFile ()
1115 TypeContainer ns = Parent;
1117 var sf = ns as CompilationSourceFile;
1125 public override string GetSignatureForMetadata ()
1127 if (Parent is TypeDefinition) {
1128 return Parent.GetSignatureForMetadata () + "+" + TypeNameParser.Escape (FilterNestedName (MemberName.Basename));
1131 return base.GetSignatureForMetadata ();
1134 public virtual void SetBaseTypes (List<FullNamedExpression> baseTypes)
1136 type_bases = baseTypes;
1140 /// This function computes the Base class and also the
1141 /// list of interfaces that the class or struct @c implements.
1143 /// The return value is an array (might be null) of
1144 /// interfaces implemented (as Types).
1146 /// The @base_class argument is set to the base object or null
1147 /// if this is `System.Object'.
1149 protected virtual TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
1152 if (type_bases == null)
1155 int count = type_bases.Count;
1156 TypeSpec[] ifaces = null;
1157 var base_context = new BaseContext (this);
1158 for (int i = 0, j = 0; i < count; i++){
1159 FullNamedExpression fne = type_bases [i];
1161 var fne_resolved = fne.ResolveAsType (base_context);
1162 if (fne_resolved == null)
1165 if (i == 0 && Kind == MemberKind.Class && !fne_resolved.IsInterface) {
1166 if (fne_resolved.BuiltinType == BuiltinTypeSpec.Type.Dynamic) {
1167 Report.Error (1965, Location, "Class `{0}' cannot derive from the dynamic type",
1168 GetSignatureForError ());
1173 base_type = fne_resolved;
1179 ifaces = new TypeSpec [count - i];
1181 if (fne_resolved.IsInterface) {
1182 for (int ii = 0; ii < j; ++ii) {
1183 if (fne_resolved == ifaces [ii]) {
1184 Report.Error (528, Location, "`{0}' is already listed in interface list",
1185 fne_resolved.GetSignatureForError ());
1190 if (Kind == MemberKind.Interface && !IsAccessibleAs (fne_resolved)) {
1191 Report.Error (61, fne.Location,
1192 "Inconsistent accessibility: base interface `{0}' is less accessible than interface `{1}'",
1193 fne_resolved.GetSignatureForError (), GetSignatureForError ());
1196 Report.SymbolRelatedToPreviousError (fne_resolved);
1197 if (Kind != MemberKind.Class) {
1198 Report.Error (527, fne.Location, "Type `{0}' in interface list is not an interface", fne_resolved.GetSignatureForError ());
1199 } else if (base_class != null)
1200 Report.Error (1721, fne.Location, "`{0}': Classes cannot have multiple base classes (`{1}' and `{2}')",
1201 GetSignatureForError (), base_class.GetSignatureForError (), fne_resolved.GetSignatureForError ());
1203 Report.Error (1722, fne.Location, "`{0}': Base class `{1}' must be specified as first",
1204 GetSignatureForError (), fne_resolved.GetSignatureForError ());
1208 ifaces [j++] = fne_resolved;
1215 // Checks that some operators come in pairs:
1221 // They are matched based on the return type and the argument types
1223 void CheckPairedOperators ()
1225 bool has_equality_or_inequality = false;
1226 List<Operator.OpType> found_matched = new List<Operator.OpType> ();
1228 for (int i = 0; i < members.Count; ++i) {
1229 var o_a = members[i] as Operator;
1233 var o_type = o_a.OperatorType;
1234 if (o_type == Operator.OpType.Equality || o_type == Operator.OpType.Inequality)
1235 has_equality_or_inequality = true;
1237 if (found_matched.Contains (o_type))
1240 var matching_type = o_a.GetMatchingOperator ();
1241 if (matching_type == Operator.OpType.TOP) {
1245 bool pair_found = false;
1246 for (int ii = 0; ii < members.Count; ++ii) {
1247 var o_b = members[ii] as Operator;
1248 if (o_b == null || o_b.OperatorType != matching_type)
1251 if (!TypeSpecComparer.IsEqual (o_a.ReturnType, o_b.ReturnType))
1254 if (!TypeSpecComparer.Equals (o_a.ParameterTypes, o_b.ParameterTypes))
1257 found_matched.Add (matching_type);
1263 Report.Error (216, o_a.Location,
1264 "The operator `{0}' requires a matching operator `{1}' to also be defined",
1265 o_a.GetSignatureForError (), Operator.GetName (matching_type));
1269 if (has_equality_or_inequality) {
1271 Report.Warning (660, 2, Location, "`{0}' defines operator == or operator != but does not override Object.Equals(object o)",
1272 GetSignatureForError ());
1274 if (!HasGetHashCode)
1275 Report.Warning (661, 2, Location, "`{0}' defines operator == or operator != but does not override Object.GetHashCode()",
1276 GetSignatureForError ());
1280 public override void CreateMetadataName (StringBuilder sb)
1282 if (Parent.MemberName != null) {
1283 Parent.CreateMetadataName (sb);
1285 if (sb.Length != 0) {
1290 sb.Append (MemberName.Basename);
1293 bool CreateTypeBuilder ()
1296 // Sets .size to 1 for structs with no instance fields
1298 int type_size = Kind == MemberKind.Struct && first_nonstatic_field == null && !(this is StateMachine) ? 1 : 0;
1300 var parent_def = Parent as TypeDefinition;
1301 if (parent_def == null) {
1302 var sb = new StringBuilder ();
1303 CreateMetadataName (sb);
1304 TypeBuilder = Module.CreateBuilder (sb.ToString (), TypeAttr, type_size);
1306 TypeBuilder = parent_def.TypeBuilder.DefineNestedType (FilterNestedName (MemberName.Basename), TypeAttr, null, type_size);
1309 if (DeclaringAssembly.Importer != null)
1310 DeclaringAssembly.Importer.AddCompiledType (TypeBuilder, spec);
1312 spec.SetMetaInfo (TypeBuilder);
1313 spec.MemberCache = new MemberCache (this);
1315 TypeParameters parentAllTypeParameters = null;
1316 if (parent_def != null) {
1317 spec.DeclaringType = Parent.CurrentType;
1318 parent_def.MemberCache.AddMember (spec);
1319 parentAllTypeParameters = parent_def.all_type_parameters;
1322 if (MemberName.TypeParameters != null || parentAllTypeParameters != null) {
1323 var tparam_names = CreateTypeParameters (parentAllTypeParameters);
1325 all_tp_builders = TypeBuilder.DefineGenericParameters (tparam_names);
1327 if (CurrentTypeParameters != null) {
1328 CurrentTypeParameters.Create (spec, CurrentTypeParametersStartIndex, this);
1329 CurrentTypeParameters.Define (all_tp_builders);
1336 public static string FilterNestedName (string name)
1339 // SRE API does not handle namespaces and types separately but
1340 // determine that from '.' in name. That's problematic because
1341 // dot is valid character for type name. By replacing any '.'
1342 // in name we avoid any ambiguities and never emit metadata
1343 // namespace for nested types
1345 return name.Replace ('.', '_');
1348 string[] CreateTypeParameters (TypeParameters parentAllTypeParameters)
1351 int parent_offset = 0;
1352 if (parentAllTypeParameters != null) {
1353 if (CurrentTypeParameters == null) {
1354 all_type_parameters = parentAllTypeParameters;
1355 return parentAllTypeParameters.GetAllNames ();
1358 names = new string[parentAllTypeParameters.Count + CurrentTypeParameters.Count];
1359 all_type_parameters = new TypeParameters (names.Length);
1360 all_type_parameters.Add (parentAllTypeParameters);
1362 parent_offset = all_type_parameters.Count;
1363 for (int i = 0; i < parent_offset; ++i)
1364 names[i] = all_type_parameters[i].MemberName.Name;
1367 names = new string[CurrentTypeParameters.Count];
1370 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
1371 if (all_type_parameters != null)
1372 all_type_parameters.Add (MemberName.TypeParameters[i]);
1374 var name = CurrentTypeParameters[i].MemberName.Name;
1375 names[parent_offset + i] = name;
1376 for (int ii = 0; ii < parent_offset + i; ++ii) {
1377 if (names[ii] != name)
1380 var tp = CurrentTypeParameters[i];
1381 var conflict = all_type_parameters[ii];
1383 tp.WarningParentNameConflict (conflict);
1387 if (all_type_parameters == null)
1388 all_type_parameters = CurrentTypeParameters;
1394 public SourceMethodBuilder CreateMethodSymbolEntry ()
1396 if (Module.DeclaringAssembly.SymbolWriter == null || (ModFlags & Modifiers.DEBUGGER_HIDDEN) != 0)
1399 var source_file = GetCompilationSourceFile ();
1400 if (source_file == null)
1403 return new SourceMethodBuilder (source_file.SymbolUnitEntry);
1407 // Creates a proxy base method call inside this container for hoisted base member calls
1409 public MethodSpec CreateHoistedBaseCallProxy (ResolveContext rc, MethodSpec method)
1411 Method proxy_method;
1414 // One proxy per base method is enough
1416 if (hoisted_base_call_proxies == null) {
1417 hoisted_base_call_proxies = new Dictionary<MethodSpec, Method> ();
1418 proxy_method = null;
1420 hoisted_base_call_proxies.TryGetValue (method, out proxy_method);
1423 if (proxy_method == null) {
1424 string name = CompilerGeneratedContainer.MakeName (method.Name, null, "BaseCallProxy", hoisted_base_call_proxies.Count);
1426 MemberName member_name;
1427 TypeArguments targs = null;
1428 TypeSpec return_type = method.ReturnType;
1429 var local_param_types = method.Parameters.Types;
1431 if (method.IsGeneric) {
1433 // Copy all base generic method type parameters info
1435 var hoisted_tparams = method.GenericDefinition.TypeParameters;
1436 var tparams = new TypeParameters ();
1438 targs = new TypeArguments ();
1439 targs.Arguments = new TypeSpec[hoisted_tparams.Length];
1440 for (int i = 0; i < hoisted_tparams.Length; ++i) {
1441 var tp = hoisted_tparams[i];
1442 var local_tp = new TypeParameter (tp, null, new MemberName (tp.Name, Location), null);
1443 tparams.Add (local_tp);
1445 targs.Add (new SimpleName (tp.Name, Location));
1446 targs.Arguments[i] = local_tp.Type;
1449 member_name = new MemberName (name, tparams, Location);
1452 // Mutate any method type parameters from original
1453 // to newly created hoisted version
1455 var mutator = new TypeParameterMutator (hoisted_tparams, tparams);
1456 return_type = mutator.Mutate (return_type);
1457 local_param_types = mutator.Mutate (local_param_types);
1459 member_name = new MemberName (name);
1462 var base_parameters = new Parameter[method.Parameters.Count];
1463 for (int i = 0; i < base_parameters.Length; ++i) {
1464 var base_param = method.Parameters.FixedParameters[i];
1465 base_parameters[i] = new Parameter (new TypeExpression (local_param_types [i], Location),
1466 base_param.Name, base_param.ModFlags, null, Location);
1467 base_parameters[i].Resolve (this, i);
1470 var cloned_params = ParametersCompiled.CreateFullyResolved (base_parameters, method.Parameters.Types);
1471 if (method.Parameters.HasArglist) {
1472 cloned_params.FixedParameters[0] = new Parameter (null, "__arglist", Parameter.Modifier.NONE, null, Location);
1473 cloned_params.Types[0] = Module.PredefinedTypes.RuntimeArgumentHandle.Resolve ();
1476 // Compiler generated proxy
1477 proxy_method = new Method (this, new TypeExpression (return_type, Location),
1478 Modifiers.PRIVATE | Modifiers.COMPILER_GENERATED | Modifiers.DEBUGGER_HIDDEN,
1479 member_name, cloned_params, null);
1481 var block = new ToplevelBlock (Compiler, proxy_method.ParameterInfo, Location) {
1482 IsCompilerGenerated = true
1485 var mg = MethodGroupExpr.CreatePredefined (method, method.DeclaringType, Location);
1486 mg.InstanceExpression = new BaseThis (method.DeclaringType, Location);
1488 mg.SetTypeArguments (rc, targs);
1490 // Get all the method parameters and pass them as arguments
1491 var real_base_call = new Invocation (mg, block.GetAllParametersArguments ());
1492 Statement statement;
1493 if (method.ReturnType.Kind == MemberKind.Void)
1494 statement = new StatementExpression (real_base_call);
1496 statement = new Return (real_base_call, Location);
1498 block.AddStatement (statement);
1499 proxy_method.Block = block;
1501 members.Add (proxy_method);
1502 proxy_method.Define ();
1503 proxy_method.PrepareEmit ();
1505 hoisted_base_call_proxies.Add (method, proxy_method);
1508 return proxy_method.Spec;
1511 protected bool DefineBaseTypes ()
1513 if (IsPartialPart && Kind == MemberKind.Class)
1516 return DoDefineBaseType ();
1519 bool DoDefineBaseType ()
1521 iface_exprs = ResolveBaseTypes (out base_type_expr);
1524 if (IsPartialPart) {
1525 set_base_type = false;
1527 if (base_type_expr != null) {
1528 if (PartialContainer.base_type_expr != null && PartialContainer.base_type != base_type) {
1529 Report.SymbolRelatedToPreviousError (base_type_expr.Location, "");
1530 Report.Error (263, Location,
1531 "Partial declarations of `{0}' must not specify different base classes",
1532 GetSignatureForError ());
1534 PartialContainer.base_type_expr = base_type_expr;
1535 PartialContainer.base_type = base_type;
1536 set_base_type = true;
1540 if (iface_exprs != null) {
1541 if (PartialContainer.iface_exprs == null)
1542 PartialContainer.iface_exprs = iface_exprs;
1544 var ifaces = new List<TypeSpec> (PartialContainer.iface_exprs);
1545 foreach (var iface_partial in iface_exprs) {
1546 if (ifaces.Contains (iface_partial))
1549 ifaces.Add (iface_partial);
1552 PartialContainer.iface_exprs = ifaces.ToArray ();
1556 PartialContainer.members.AddRange (members);
1557 if (containers != null) {
1558 if (PartialContainer.containers == null)
1559 PartialContainer.containers = new List<TypeContainer> ();
1561 PartialContainer.containers.AddRange (containers);
1564 if (PrimaryConstructorParameters != null) {
1565 if (PartialContainer.PrimaryConstructorParameters != null) {
1566 Report.Error (8036, Location, "Only one part of a partial type can declare primary constructor parameters");
1568 PartialContainer.PrimaryConstructorParameters = PrimaryConstructorParameters;
1572 members_defined = members_defined_ok = true;
1573 caching_flags |= Flags.CloseTypeCreated;
1575 set_base_type = true;
1578 var cycle = CheckRecursiveDefinition (this);
1579 if (cycle != null) {
1580 Report.SymbolRelatedToPreviousError (cycle);
1581 if (this is Interface) {
1582 Report.Error (529, Location,
1583 "Inherited interface `{0}' causes a cycle in the interface hierarchy of `{1}'",
1584 GetSignatureForError (), cycle.GetSignatureForError ());
1587 PartialContainer.iface_exprs = null;
1589 Report.Error (146, Location,
1590 "Circular base class dependency involving `{0}' and `{1}'",
1591 GetSignatureForError (), cycle.GetSignatureForError ());
1594 PartialContainer.base_type = null;
1598 if (iface_exprs != null) {
1599 if (!PrimaryConstructorBaseArgumentsStart.IsNull) {
1600 Report.Error (8049, PrimaryConstructorBaseArgumentsStart, "Implemented interfaces cannot have arguments");
1603 foreach (var iface_type in iface_exprs) {
1604 // Prevents a crash, the interface might not have been resolved: 442144
1605 if (iface_type == null)
1608 if (!spec.AddInterfaceDefined (iface_type))
1611 TypeBuilder.AddInterfaceImplementation (iface_type.GetMetaInfo ());
1615 if (Kind == MemberKind.Interface) {
1616 spec.BaseType = Compiler.BuiltinTypes.Object;
1620 if (set_base_type) {
1625 // Base type of partial container has to be resolved before we
1626 // resolve any nested types of the container. We need to know
1627 // partial parts because the base type can be specified in file
1628 // defined after current container
1630 if (class_partial_parts != null) {
1631 foreach (var pp in class_partial_parts) {
1632 if (pp.PrimaryConstructorBaseArguments != null)
1633 PrimaryConstructorBaseArguments = pp.PrimaryConstructorBaseArguments;
1635 pp.DoDefineBaseType ();
1645 if (base_type == null) {
1646 TypeBuilder.SetParent (null);
1650 if (spec.BaseType == base_type)
1653 spec.BaseType = base_type;
1656 spec.UpdateInflatedInstancesBaseType ();
1658 // Set base type after type creation
1659 TypeBuilder.SetParent (base_type.GetMetaInfo ());
1662 public override void ExpandBaseInterfaces ()
1665 DoExpandBaseInterfaces ();
1667 base.ExpandBaseInterfaces ();
1670 public void DoExpandBaseInterfaces ()
1672 if ((caching_flags & Flags.InterfacesExpanded) != 0)
1675 caching_flags |= Flags.InterfacesExpanded;
1678 // Expand base interfaces. It cannot be done earlier because all partial
1679 // interface parts need to be defined before the type they are used from
1681 if (iface_exprs != null) {
1682 foreach (var iface in iface_exprs) {
1686 var td = iface.MemberDefinition as TypeDefinition;
1688 td.DoExpandBaseInterfaces ();
1690 if (iface.Interfaces == null)
1693 foreach (var biface in iface.Interfaces) {
1694 if (spec.AddInterfaceDefined (biface)) {
1695 TypeBuilder.AddInterfaceImplementation (biface.GetMetaInfo ());
1702 // Include all base type interfaces too, see ImportTypeBase for details
1704 if (base_type != null) {
1705 var td = base_type.MemberDefinition as TypeDefinition;
1707 td.DoExpandBaseInterfaces ();
1710 // Simply use base interfaces only, they are all expanded which makes
1711 // it easy to handle generic type argument propagation with single
1714 // interface IA<T> : IB<T>
1715 // interface IB<U> : IC<U>
1718 if (base_type.Interfaces != null) {
1719 foreach (var iface in base_type.Interfaces) {
1720 spec.AddInterfaceDefined (iface);
1726 public override void PrepareEmit ()
1728 if ((caching_flags & Flags.CloseTypeCreated) != 0)
1731 foreach (var member in members) {
1732 var pbm = member as MemberBase;
1737 base.PrepareEmit ();
1741 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1743 public override bool CreateContainer ()
1745 if (TypeBuilder != null)
1751 if (IsPartialPart) {
1752 spec = PartialContainer.spec;
1753 TypeBuilder = PartialContainer.TypeBuilder;
1754 all_tp_builders = PartialContainer.all_tp_builders;
1755 all_type_parameters = PartialContainer.all_type_parameters;
1757 if (!CreateTypeBuilder ()) {
1763 return base.CreateContainer ();
1766 protected override void DoDefineContainer ()
1770 DoResolveTypeParameters ();
1774 // Replaces normal spec with predefined one when compiling corlib
1775 // and this type container defines predefined type
1777 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1779 // When compiling build-in types we start with two
1780 // version of same type. One is of BuiltinTypeSpec and
1781 // second one is ordinary TypeSpec. The unification
1782 // happens at later stage when we know which type
1783 // really matches the builtin type signature. However
1784 // that means TypeSpec create during CreateType of this
1785 // type has to be replaced with builtin one
1787 spec.SetMetaInfo (TypeBuilder);
1788 spec.MemberCache = this.spec.MemberCache;
1789 spec.DeclaringType = this.spec.DeclaringType;
1792 current_type = null;
1793 if (class_partial_parts != null) {
1794 foreach (var part in class_partial_parts)
1799 public override void RemoveContainer (TypeContainer cont)
1801 base.RemoveContainer (cont);
1802 Members.Remove (cont);
1803 Cache.Remove (cont.MemberName.Basename);
1806 protected virtual bool DoResolveTypeParameters ()
1808 var tparams = MemberName.TypeParameters;
1809 if (tparams == null)
1812 var base_context = new BaseContext (this);
1813 for (int i = 0; i < tparams.Count; ++i) {
1814 var tp = tparams[i];
1816 if (!tp.ResolveConstraints (base_context)) {
1821 if (IsPartialPart) {
1822 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1824 tp.Create (spec, this);
1827 if (tp.OptAttributes != null) {
1828 if (pc_tp.OptAttributes == null)
1829 pc_tp.OptAttributes = tp.OptAttributes;
1831 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1836 if (IsPartialPart) {
1837 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1843 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1845 if (InTransit != null)
1850 if (base_type != null) {
1851 var ptc = base_type.MemberDefinition as TypeDefinition;
1852 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1856 if (iface_exprs != null && this is Interface) {
1857 foreach (var iface in iface_exprs) {
1858 // the interface might not have been resolved, prevents a crash, see #442144
1861 var ptc = iface.MemberDefinition as Interface;
1862 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1867 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1875 /// Populates our TypeBuilder with fields and methods
1877 public sealed override bool Define ()
1879 if (members_defined)
1880 return members_defined_ok;
1882 members_defined_ok = DoDefineMembers ();
1883 members_defined = true;
1887 return members_defined_ok;
1890 protected virtual bool DoDefineMembers ()
1892 Debug.Assert (!IsPartialPart);
1894 if (iface_exprs != null) {
1895 foreach (var iface_type in iface_exprs) {
1896 if (iface_type == null)
1899 // Ensure the base is always setup
1900 var compiled_iface = iface_type.MemberDefinition as Interface;
1901 if (compiled_iface != null)
1902 compiled_iface.Define ();
1904 iface_type.CheckObsoleteness (this, Location);
1906 if (iface_type.Arity > 0) {
1907 // TODO: passing `this' is wrong, should be base type iface instead
1908 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1910 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1911 Report.Error (1966, Location,
1912 "`{0}': cannot implement a dynamic interface `{1}'",
1913 GetSignatureForError (), iface_type.GetSignatureForError ());
1918 if (iface_type.IsGenericOrParentIsGeneric) {
1919 foreach (var prev_iface in iface_exprs) {
1920 if (prev_iface == iface_type || prev_iface == null)
1923 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1926 Report.Error (695, Location,
1927 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1928 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1933 if (Kind == MemberKind.Interface) {
1934 foreach (var iface in spec.Interfaces) {
1935 MemberCache.AddInterface (iface);
1940 if (base_type != null) {
1942 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1944 if (base_type_expr != null) {
1945 base_type.CheckObsoleteness (this, base_type_expr.Location);
1947 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1948 Report.Error (698, base_type_expr.Location,
1949 "A generic type cannot derive from `{0}' because it is an attribute class",
1950 base_type.GetSignatureForError ());
1954 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1955 if (baseContainer != null) {
1956 baseContainer.Define ();
1959 // It can trigger define of this type (for generic types only)
1961 if (HasMembersDefined)
1966 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1967 pending = PendingImplementation.GetPendingImplementations (this);
1970 var count = members.Count;
1971 for (int i = 0; i < count; ++i) {
1972 var mc = members[i] as InterfaceMemberBase;
1973 if (mc == null || !mc.IsExplicitImpl)
1978 } catch (Exception e) {
1979 throw new InternalErrorException (mc, e);
1983 for (int i = 0; i < count; ++i) {
1984 var mc = members[i] as InterfaceMemberBase;
1985 if (mc != null && mc.IsExplicitImpl)
1988 if (members[i] is TypeContainer)
1992 members[i].Define ();
1993 } catch (Exception e) {
1994 throw new InternalErrorException (members[i], e);
1999 CheckPairedOperators ();
2002 ComputeIndexerName();
2004 if (HasEquals && !HasGetHashCode) {
2005 Report.Warning (659, 3, Location,
2006 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2009 if (Kind == MemberKind.Interface && iface_exprs != null) {
2010 MemberCache.RemoveHiddenMembers (spec);
2016 void ComputeIndexerName ()
2018 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2019 if (indexers == null)
2022 string class_indexer_name = null;
2025 // Check normal indexers for consistent name, explicit interface implementation
2026 // indexers are ignored
2028 foreach (var indexer in indexers) {
2030 // FindMembers can return unfiltered full hierarchy names
2032 if (indexer.DeclaringType != spec)
2035 has_normal_indexers = true;
2037 if (class_indexer_name == null) {
2038 indexer_name = class_indexer_name = indexer.Name;
2042 if (indexer.Name != class_indexer_name)
2043 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2044 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2048 void EmitIndexerName ()
2050 if (!has_normal_indexers)
2053 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2057 var encoder = new AttributeEncoder ();
2058 encoder.Encode (GetAttributeDefaultMember ());
2059 encoder.EncodeEmptyNamedArguments ();
2061 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2064 public override void VerifyMembers ()
2067 // Check for internal or private fields that were never assigned
2069 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2070 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2071 foreach (var member in members) {
2072 if (member is Event) {
2074 // An event can be assigned from same class only, report
2075 // this warning for all accessibility modes
2077 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2078 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2083 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2084 if (is_type_exposed)
2087 member.SetIsUsed ();
2090 var f = member as Field;
2094 if (!member.IsUsed) {
2095 if (!PartialContainer.HasStructLayout) {
2096 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2097 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2099 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2100 member.GetSignatureForError ());
2107 if ((f.caching_flags & Flags.IsAssigned) != 0)
2111 // Only report 649 on level 4
2113 if (Compiler.Settings.WarningLevel < 4)
2117 // Don't be pedantic when type requires specific layout
2119 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2122 Constant c = New.Constantify (f.MemberType, f.Location);
2125 value = c.GetValueAsLiteral ();
2126 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2133 value = " `" + value + "'";
2135 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2136 f.GetSignatureForError (), value);
2140 base.VerifyMembers ();
2143 public override void Emit ()
2145 if (OptAttributes != null)
2146 OptAttributes.Emit ();
2148 if (!IsCompilerGenerated) {
2150 MemberSpec candidate;
2151 bool overrides = false;
2152 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2153 if (conflict_symbol == null && candidate == null) {
2154 if ((ModFlags & Modifiers.NEW) != 0)
2155 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2156 GetSignatureForError ());
2158 if ((ModFlags & Modifiers.NEW) == 0) {
2159 if (candidate == null)
2160 candidate = conflict_symbol;
2162 Report.SymbolRelatedToPreviousError (candidate);
2163 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2164 GetSignatureForError (), candidate.GetSignatureForError ());
2169 // Run constraints check on all possible generic types
2170 if (base_type != null && base_type_expr != null) {
2171 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2174 if (iface_exprs != null) {
2175 foreach (var iface_type in iface_exprs) {
2176 if (iface_type == null)
2179 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2184 if (all_tp_builders != null) {
2185 int current_starts_index = CurrentTypeParametersStartIndex;
2186 for (int i = 0; i < all_tp_builders.Length; i++) {
2187 if (i < current_starts_index) {
2188 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2190 var tp = CurrentTypeParameters [i - current_starts_index];
2191 tp.CheckGenericConstraints (!IsObsolete);
2197 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2198 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2201 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2202 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2207 for (int i = 0; i < members.Count; i++) {
2209 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2216 CheckAttributeClsCompliance ();
2218 if (pending != null)
2219 pending.VerifyPendingMethods ();
2223 void CheckAttributeClsCompliance ()
2225 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2228 foreach (var m in members) {
2229 var c = m as Constructor;
2233 if (c.HasCompliantArgs)
2237 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2240 public sealed override void EmitContainer ()
2242 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2248 public override void CloseContainer ()
2250 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2253 // Close base type container first to avoid TypeLoadException
2254 if (spec.BaseType != null) {
2255 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2256 if (btype != null) {
2257 btype.CloseContainer ();
2259 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2265 caching_flags |= Flags.CloseTypeCreated;
2266 TypeBuilder.CreateType ();
2267 } catch (TypeLoadException) {
2269 // This is fine, the code still created the type
2271 } catch (Exception e) {
2272 throw new InternalErrorException (this, e);
2275 base.CloseContainer ();
2278 initialized_fields = null;
2279 initialized_static_fields = null;
2281 OptAttributes = null;
2285 // Performs the validation on a Method's modifiers (properties have
2286 // the same properties).
2288 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2290 public bool MethodModifiersValid (MemberCore mc)
2292 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2293 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2295 var flags = mc.ModFlags;
2298 // At most one of static, virtual or override
2300 if ((flags & Modifiers.STATIC) != 0){
2301 if ((flags & vao) != 0){
2302 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2303 mc.GetSignatureForError ());
2308 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2309 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2310 mc.GetSignatureForError ());
2315 // If the declaration includes the abstract modifier, then the
2316 // declaration does not include static, virtual or extern
2318 if ((flags & Modifiers.ABSTRACT) != 0){
2319 if ((flags & Modifiers.EXTERN) != 0){
2321 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2325 if ((flags & Modifiers.SEALED) != 0) {
2326 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2330 if ((flags & Modifiers.VIRTUAL) != 0){
2331 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2335 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2336 Report.SymbolRelatedToPreviousError (this);
2337 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2338 mc.GetSignatureForError (), GetSignatureForError ());
2343 if ((flags & Modifiers.PRIVATE) != 0){
2344 if ((flags & vao) != 0){
2345 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2350 if ((flags & Modifiers.SEALED) != 0){
2351 if ((flags & Modifiers.OVERRIDE) == 0){
2352 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2360 protected override bool VerifyClsCompliance ()
2362 if (!base.VerifyClsCompliance ())
2365 // Check all container names for user classes
2366 if (Kind != MemberKind.Delegate)
2367 MemberCache.VerifyClsCompliance (Definition, Report);
2369 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2370 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2371 GetSignatureForError (), BaseType.GetSignatureForError ());
2377 /// Performs checks for an explicit interface implementation. First it
2378 /// checks whether the `interface_type' is a base inteface implementation.
2379 /// Then it checks whether `name' exists in the interface type.
2381 public bool VerifyImplements (InterfaceMemberBase mb)
2383 var ifaces = PartialContainer.Interfaces;
2384 if (ifaces != null) {
2385 foreach (TypeSpec t in ifaces){
2386 if (t == mb.InterfaceType || t == null)
2389 var expanded_base = t.Interfaces;
2390 if (expanded_base == null)
2393 foreach (var bt in expanded_base) {
2394 if (bt == mb.InterfaceType)
2400 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2401 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2402 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2407 // Used for visiblity checks to tests whether this definition shares
2408 // base type baseType, it does member-definition search
2410 public bool IsBaseTypeDefinition (TypeSpec baseType)
2412 // RootContext check
2413 if (TypeBuilder == null)
2418 if (type.MemberDefinition == baseType.MemberDefinition)
2421 type = type.BaseType;
2422 } while (type != null);
2427 public override bool IsClsComplianceRequired ()
2430 return PartialContainer.IsClsComplianceRequired ();
2432 return base.IsClsComplianceRequired ();
2435 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2437 return Module.DeclaringAssembly == assembly;
2440 public virtual bool IsUnmanagedType ()
2445 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2447 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2451 // Public function used to locate types.
2453 // Returns: Type or null if they type can not be found.
2455 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2457 FullNamedExpression e;
2458 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2464 var tp = CurrentTypeParameters;
2466 TypeParameter tparam = tp.Find (name);
2468 e = new TypeParameterExpr (tparam, Location.Null);
2473 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2475 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2476 e = new TypeExpression (t, Location.Null);
2478 var errors = Compiler.Report.Errors;
2479 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2481 // TODO: LookupNamespaceOrType does more than just lookup. The result
2482 // cannot be cached or the error reporting won't happen
2483 if (errors != Compiler.Report.Errors)
2488 // TODO MemberCache: How to cache arity stuff ?
2489 if (arity == 0 && mode == LookupMode.Normal)
2495 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2497 // Has any nested type
2498 // Does not work, because base type can have
2499 //if (PartialContainer.Types == null)
2502 var container = PartialContainer.CurrentType;
2503 return MemberCache.FindNestedType (container, name, arity, false);
2506 public void Mark_HasEquals ()
2508 cached_method |= CachedMethods.Equals;
2511 public void Mark_HasGetHashCode ()
2513 cached_method |= CachedMethods.GetHashCode;
2516 public override void WriteDebugSymbol (MonoSymbolFile file)
2521 foreach (var m in members) {
2522 m.WriteDebugSymbol (file);
2527 /// Method container contains Equals method
2529 public bool HasEquals {
2531 return (cached_method & CachedMethods.Equals) != 0;
2536 /// Method container contains GetHashCode method
2538 public bool HasGetHashCode {
2540 return (cached_method & CachedMethods.GetHashCode) != 0;
2544 public bool HasStaticFieldInitializer {
2546 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2550 cached_method |= CachedMethods.HasStaticFieldInitializer;
2552 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2556 public override string DocCommentHeader {
2557 get { return "T:"; }
2561 public abstract class ClassOrStruct : TypeDefinition
2563 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2565 SecurityType declarative_security;
2566 protected Constructor generated_primary_constructor;
2568 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2569 : base (parent, name, attrs, kind)
2573 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2575 protected override TypeAttributes TypeAttr {
2577 TypeAttributes ta = base.TypeAttr;
2578 if (!has_static_constructor)
2579 ta |= TypeAttributes.BeforeFieldInit;
2581 if (Kind == MemberKind.Class) {
2582 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2584 ta |= StaticClassAttribute;
2586 ta |= TypeAttributes.SequentialLayout;
2593 public override void AddNameToContainer (MemberCore symbol, string name)
2595 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2596 if (symbol is TypeParameter) {
2597 Report.Error (694, symbol.Location,
2598 "Type parameter `{0}' has same name as containing type, or method",
2599 symbol.GetSignatureForError ());
2603 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2604 if (imb == null || !imb.IsExplicitImpl) {
2605 Report.SymbolRelatedToPreviousError (this);
2606 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2607 symbol.GetSignatureForError ());
2612 base.AddNameToContainer (symbol, name);
2615 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2617 if (a.IsValidSecurityAttribute ()) {
2618 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2622 if (a.Type == pa.StructLayout) {
2623 PartialContainer.HasStructLayout = true;
2624 if (a.IsExplicitLayoutKind ())
2625 PartialContainer.HasExplicitLayout = true;
2628 if (a.Type == pa.Dynamic) {
2629 a.Error_MisusedDynamicAttribute ();
2633 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2637 /// Defines the default constructors
2639 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2641 // The default instance constructor is public
2642 // If the class is abstract, the default constructor is protected
2643 // The default static constructor is private
2646 ParametersCompiled parameters = null;
2648 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2649 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2651 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2652 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2655 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2656 if (Kind == MemberKind.Class)
2657 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2659 if (PrimaryConstructorParameters != null && !is_static) {
2660 c.IsPrimaryConstructor = true;
2661 c.caching_flags |= Flags.MethodOverloadsExist;
2664 AddConstructor (c, true);
2665 if (PrimaryConstructorBlock == null) {
2666 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2667 IsCompilerGenerated = true
2670 c.Block = PrimaryConstructorBlock;
2676 protected override bool DoDefineMembers ()
2678 CheckProtectedModifier ();
2680 if (PrimaryConstructorParameters != null) {
2682 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2683 if (p.Name == MemberName.Name) {
2684 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2685 GetSignatureForError ());
2688 if (CurrentTypeParameters != null) {
2689 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2690 var tp = CurrentTypeParameters [i];
2691 if (p.Name == tp.Name) {
2692 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2693 GetSignatureForError (), p.GetSignatureForError ());
2700 base.DoDefineMembers ();
2705 public override void PrepareEmit ()
2707 var s = this as Struct;
2708 if (s == null || !s.HasUnmanagedCheckDone) {
2709 for (int i = 0; i < Members.Count; ++i) {
2710 var f = Members [i] as Field;
2711 if (f == null || f.MemberType == null || !f.MemberType.IsPointer)
2714 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2718 base.PrepareEmit ();
2721 public override void Emit ()
2723 if (!has_static_constructor && HasStaticFieldInitializer) {
2724 var c = DefineDefaultConstructor (true);
2730 if (declarative_security != null) {
2731 foreach (var de in declarative_security) {
2733 TypeBuilder.__AddDeclarativeSecurity (de);
2735 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2743 public sealed class Class : ClassOrStruct
2745 const Modifiers AllowedModifiers =
2748 Modifiers.PROTECTED |
2749 Modifiers.INTERNAL |
2751 Modifiers.ABSTRACT |
2756 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2757 : base (parent, name, attrs, MemberKind.Class)
2759 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2760 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2761 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2764 public override void Accept (StructuralVisitor visitor)
2766 visitor.Visit (this);
2769 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2771 var pmn = MemberName;
2772 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2773 Report.Error (537, Location,
2774 "The class System.Object cannot have a base class or implement an interface.");
2776 base.SetBaseTypes (baseTypes);
2779 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2781 if (a.Type == pa.AttributeUsage) {
2782 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2783 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2787 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2788 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2792 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2793 a.Error_MissingGuidAttribute ();
2797 if (a.Type == pa.Extension) {
2798 a.Error_MisusedExtensionAttribute ();
2802 if (a.Type.IsConditionallyExcluded (this))
2805 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2808 public override AttributeTargets AttributeTargets {
2810 return AttributeTargets.Class;
2814 protected override bool DoDefineMembers ()
2816 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2817 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2820 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2821 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2825 if (PrimaryConstructorParameters != null) {
2826 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2827 PrimaryConstructorParameters = null;
2830 foreach (var m in Members) {
2831 if (m is Operator) {
2832 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2836 if (m is Destructor) {
2837 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2842 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2846 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2849 if (m is Constructor) {
2850 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2854 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2857 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2858 generated_primary_constructor = DefineDefaultConstructor (false);
2861 return base.DoDefineMembers ();
2864 public override void Emit ()
2868 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2869 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2871 if (base_type != null && base_type.HasDynamicElement) {
2872 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2876 public override void GetCompletionStartingWith (string prefix, List<string> results)
2878 base.GetCompletionStartingWith (prefix, results);
2881 while (bt != null) {
2882 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2887 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2889 var ifaces = base.ResolveBaseTypes (out base_class);
2891 if (base_class == null) {
2892 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2893 base_type = Compiler.BuiltinTypes.Object;
2895 if (base_type.IsGenericParameter){
2896 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2897 GetSignatureForError (), base_type.GetSignatureForError ());
2898 } else if (base_type.IsStatic) {
2899 Report.SymbolRelatedToPreviousError (base_type);
2900 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2901 GetSignatureForError (), base_type.GetSignatureForError ());
2902 } else if (base_type.IsSealed) {
2903 Report.SymbolRelatedToPreviousError (base_type);
2904 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2905 GetSignatureForError (), base_type.GetSignatureForError ());
2906 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2907 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2908 GetSignatureForError (), base_type.GetSignatureForError ());
2911 switch (base_type.BuiltinType) {
2912 case BuiltinTypeSpec.Type.Enum:
2913 case BuiltinTypeSpec.Type.ValueType:
2914 case BuiltinTypeSpec.Type.MulticastDelegate:
2915 case BuiltinTypeSpec.Type.Delegate:
2916 case BuiltinTypeSpec.Type.Array:
2917 if (!(spec is BuiltinTypeSpec)) {
2918 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2919 GetSignatureForError (), base_type.GetSignatureForError ());
2921 base_type = Compiler.BuiltinTypes.Object;
2926 if (!IsAccessibleAs (base_type)) {
2927 Report.SymbolRelatedToPreviousError (base_type);
2928 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2929 base_type.GetSignatureForError (), GetSignatureForError ());
2933 if (PartialContainer.IsStatic && ifaces != null) {
2934 foreach (var t in ifaces)
2935 Report.SymbolRelatedToPreviousError (t);
2936 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2942 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2943 /// Valid only for attribute classes.
2944 public override string[] ConditionalConditions ()
2946 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2949 caching_flags &= ~Flags.Excluded_Undetected;
2951 if (OptAttributes == null)
2954 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2958 string[] conditions = new string[attrs.Length];
2959 for (int i = 0; i < conditions.Length; ++i)
2960 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2962 caching_flags |= Flags.Excluded;
2967 public sealed class Struct : ClassOrStruct
2969 bool is_unmanaged, has_unmanaged_check_done, requires_delayed_unmanagedtype_check;
2973 // Modifiers allowed in a struct declaration
2975 const Modifiers AllowedModifiers =
2978 Modifiers.PROTECTED |
2979 Modifiers.INTERNAL |
2983 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2984 : base (parent, name, attrs, MemberKind.Struct)
2986 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2987 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2988 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2991 public override AttributeTargets AttributeTargets {
2993 return AttributeTargets.Struct;
2997 public override void Accept (StructuralVisitor visitor)
2999 visitor.Visit (this);
3002 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3004 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3007 // When struct constains fixed fixed and struct layout has explicitly
3008 // set CharSet, its value has to be propagated to compiler generated
3011 if (a.Type == pa.StructLayout) {
3012 var value = a.GetNamedValue ("CharSet");
3016 for (int i = 0; i < Members.Count; ++i) {
3017 FixedField ff = Members [i] as FixedField;
3021 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3026 bool CheckStructCycles ()
3032 foreach (var member in Members) {
3033 var field = member as Field;
3037 TypeSpec ftype = field.Spec.MemberType;
3038 if (!ftype.IsStruct)
3041 if (ftype is BuiltinTypeSpec)
3044 foreach (var targ in ftype.TypeArguments) {
3045 if (!CheckFieldTypeCycle (targ)) {
3046 Report.Error (523, field.Location,
3047 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3048 field.GetSignatureForError (), ftype.GetSignatureForError ());
3054 // Static fields of exactly same type are allowed
3056 if (field.IsStatic && ftype == CurrentType)
3059 if (!CheckFieldTypeCycle (ftype)) {
3060 Report.Error (523, field.Location,
3061 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3062 field.GetSignatureForError (), ftype.GetSignatureForError ());
3071 static bool CheckFieldTypeCycle (TypeSpec ts)
3073 var fts = ts.MemberDefinition as Struct;
3077 return fts.CheckStructCycles ();
3080 protected override bool DoDefineMembers ()
3082 var res = base.DoDefineMembers ();
3084 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3085 generated_primary_constructor = DefineDefaultConstructor (false);
3086 generated_primary_constructor.Define ();
3092 public override void Emit ()
3094 CheckStructCycles ();
3099 public bool HasUnmanagedCheckDone {
3101 return has_unmanaged_check_done;
3105 bool HasUserDefaultConstructor ()
3107 foreach (var m in PartialContainer.Members) {
3108 var c = m as Constructor;
3112 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3119 public override bool IsUnmanagedType ()
3121 if (has_unmanaged_check_done)
3122 return is_unmanaged;
3124 if (requires_delayed_unmanagedtype_check)
3127 var parent_def = Parent.PartialContainer;
3128 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3129 has_unmanaged_check_done = true;
3133 if (first_nonstatic_field != null) {
3134 requires_delayed_unmanagedtype_check = true;
3136 foreach (var member in Members) {
3137 var f = member as Field;
3144 // It can happen when recursive unmanaged types are defined
3145 // struct S { S* s; }
3146 TypeSpec mt = f.MemberType;
3154 has_unmanaged_check_done = true;
3158 has_unmanaged_check_done = true;
3161 is_unmanaged = true;
3165 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3167 var ifaces = base.ResolveBaseTypes (out base_class);
3168 base_type = Compiler.BuiltinTypes.ValueType;
3176 public sealed class Interface : TypeDefinition {
3179 /// Modifiers allowed in a class declaration
3181 const Modifiers AllowedModifiers =
3184 Modifiers.PROTECTED |
3185 Modifiers.INTERNAL |
3189 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3190 : base (parent, name, attrs, MemberKind.Interface)
3192 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3194 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3195 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3200 public override AttributeTargets AttributeTargets {
3202 return AttributeTargets.Interface;
3206 protected override TypeAttributes TypeAttr {
3208 const TypeAttributes DefaultTypeAttributes =
3209 TypeAttributes.AutoLayout |
3210 TypeAttributes.Abstract |
3211 TypeAttributes.Interface;
3213 return base.TypeAttr | DefaultTypeAttributes;
3219 public override void Accept (StructuralVisitor visitor)
3221 visitor.Visit (this);
3224 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3226 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3227 a.Error_MissingGuidAttribute ();
3231 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3234 protected override bool VerifyClsCompliance ()
3236 if (!base.VerifyClsCompliance ())
3239 if (iface_exprs != null) {
3240 foreach (var iface in iface_exprs) {
3241 if (iface.IsCLSCompliant ())
3244 Report.SymbolRelatedToPreviousError (iface);
3245 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3246 GetSignatureForError (), iface.GetSignatureForError ());
3254 public abstract class InterfaceMemberBase : MemberBase
3257 // Common modifiers allowed in a class declaration
3259 protected const Modifiers AllowedModifiersClass =
3262 Modifiers.PROTECTED |
3263 Modifiers.INTERNAL |
3268 Modifiers.OVERRIDE |
3269 Modifiers.ABSTRACT |
3274 // Common modifiers allowed in a struct declaration
3276 protected const Modifiers AllowedModifiersStruct =
3279 Modifiers.PROTECTED |
3280 Modifiers.INTERNAL |
3283 Modifiers.OVERRIDE |
3288 // Common modifiers allowed in a interface declaration
3290 protected const Modifiers AllowedModifiersInterface =
3295 // Whether this is an interface member.
3297 public bool IsInterface;
3300 // If true, this is an explicit interface implementation
3302 public readonly bool IsExplicitImpl;
3304 protected bool is_external_implementation;
3307 // The interface type we are explicitly implementing
3309 public TypeSpec InterfaceType;
3312 // The method we're overriding if this is an override method.
3314 protected MethodSpec base_method;
3316 readonly Modifiers explicit_mod_flags;
3317 public MethodAttributes flags;
3319 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3320 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3322 IsInterface = parent.Kind == MemberKind.Interface;
3323 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3324 explicit_mod_flags = mod;
3327 public abstract Variance ExpectedMemberTypeVariance { get; }
3329 protected override bool CheckBase ()
3331 if (!base.CheckBase ())
3334 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3335 CheckForDuplications ();
3340 // For System.Object only
3341 if (Parent.BaseType == null)
3344 MemberSpec candidate;
3345 bool overrides = false;
3346 var base_member = FindBaseMember (out candidate, ref overrides);
3348 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3349 if (base_member == null) {
3350 if (candidate == null) {
3351 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3352 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3353 "object.Finalize()");
3355 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3356 GetSignatureForError (), SimpleName.GetMemberType (this));
3359 Report.SymbolRelatedToPreviousError (candidate);
3361 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3362 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3363 else if (this is PropertyBase)
3364 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3365 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3367 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3368 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3375 // Handles ambiguous overrides
3377 if (candidate != null) {
3378 Report.SymbolRelatedToPreviousError (candidate);
3379 Report.SymbolRelatedToPreviousError (base_member);
3381 // Get member definition for error reporting
3382 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3383 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3385 Report.Error (462, Location,
3386 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3387 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3390 if (!CheckOverrideAgainstBase (base_member))
3393 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3395 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3396 Report.SymbolRelatedToPreviousError (base_member);
3397 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3398 GetSignatureForError (), base_member.GetSignatureForError ());
3401 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3402 Report.SymbolRelatedToPreviousError (base_member);
3403 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3404 GetSignatureForError (), base_member.GetSignatureForError ());
3408 base_method = base_member as MethodSpec;
3412 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3413 base_member = candidate;
3415 if (base_member == null) {
3416 if ((ModFlags & Modifiers.NEW) != 0) {
3417 if (base_member == null) {
3418 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3419 GetSignatureForError ());
3423 if ((ModFlags & Modifiers.NEW) == 0) {
3424 ModFlags |= Modifiers.NEW;
3425 if (!IsCompilerGenerated) {
3426 Report.SymbolRelatedToPreviousError (base_member);
3427 if ((base_member.Kind & MemberKind.NestedMask) == 0 && !IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3428 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",
3429 GetSignatureForError (), base_member.GetSignatureForError ());
3431 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3432 GetSignatureForError (), base_member.GetSignatureForError ());
3437 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3438 switch (base_member.Kind) {
3439 case MemberKind.Event:
3440 case MemberKind.Indexer:
3441 case MemberKind.Method:
3442 case MemberKind.Property:
3443 Report.SymbolRelatedToPreviousError (base_member);
3444 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3445 GetSignatureForError (), base_member.GetSignatureForError ());
3454 protected virtual bool CheckForDuplications ()
3456 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3460 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3461 // that have been defined.
3463 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3467 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3468 Report.SymbolRelatedToPreviousError (base_member);
3469 Report.Error (506, Location,
3470 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3471 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3475 // Now we check that the overriden method is not final
3476 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3477 Report.SymbolRelatedToPreviousError (base_member);
3478 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3479 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3483 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3484 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3485 Report.SymbolRelatedToPreviousError (base_member);
3486 if (this is PropertyBasedMember) {
3487 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3488 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3490 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3491 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3499 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3501 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3502 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3504 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3506 // It must be at least "protected"
3508 if ((thisp & Modifiers.PROTECTED) == 0) {
3513 // when overriding protected internal, the method can be declared
3514 // protected internal only within the same assembly or assembly
3515 // which has InternalsVisibleTo
3517 if ((thisp & Modifiers.INTERNAL) != 0) {
3518 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3522 // protected overriding protected internal inside same assembly
3523 // requires internal modifier as well
3525 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3532 return thisp == base_classp;
3535 public override bool Define ()
3538 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3539 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3541 flags = MethodAttributes.Public |
3542 MethodAttributes.Abstract |
3543 MethodAttributes.HideBySig |
3544 MethodAttributes.NewSlot |
3545 MethodAttributes.Virtual;
3547 Parent.PartialContainer.MethodModifiersValid (this);
3549 flags = ModifiersExtensions.MethodAttr (ModFlags);
3552 if (IsExplicitImpl) {
3553 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3554 if (InterfaceType == null)
3557 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3558 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3559 GetSignatureForError ());
3562 if (!InterfaceType.IsInterface) {
3563 Report.SymbolRelatedToPreviousError (InterfaceType);
3564 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3565 InterfaceType.GetSignatureForError ());
3567 Parent.PartialContainer.VerifyImplements (this);
3570 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3572 allowed_explicit |= Modifiers.ASYNC;
3574 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3577 return base.Define ();
3580 protected bool DefineParameters (ParametersCompiled parameters)
3582 if (!parameters.Resolve (this))
3586 for (int i = 0; i < parameters.Count; ++i) {
3587 Parameter p = parameters [i];
3589 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3590 p.Warning_UselessOptionalParameter (Report);
3592 if (p.CheckAccessibility (this))
3595 TypeSpec t = parameters.Types [i];
3596 Report.SymbolRelatedToPreviousError (t);
3597 if (this is Indexer)
3598 Report.Error (55, Location,
3599 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3600 t.GetSignatureForError (), GetSignatureForError ());
3601 else if (this is Operator)
3602 Report.Error (57, Location,
3603 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3604 t.GetSignatureForError (), GetSignatureForError ());
3606 Report.Error (51, Location,
3607 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3608 t.GetSignatureForError (), GetSignatureForError ());
3614 protected override void DoMemberTypeDependentChecks ()
3616 base.DoMemberTypeDependentChecks ();
3618 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3621 public override void Emit()
3623 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3624 // We are more strict than csc and report this as an error because SRE does not allow emit that
3625 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3626 if (this is Constructor) {
3627 Report.Warning (824, 1, Location,
3628 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3630 Report.Warning (626, 1, Location,
3631 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3632 GetSignatureForError ());
3639 public override bool EnableOverloadChecks (MemberCore overload)
3642 // Two members can differ in their explicit interface
3643 // type parameter only
3645 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3646 if (imb != null && imb.IsExplicitImpl) {
3647 if (IsExplicitImpl) {
3648 caching_flags |= Flags.MethodOverloadsExist;
3653 return IsExplicitImpl;
3656 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3658 var base_modifiers = base_member.Modifiers;
3660 // Remove internal modifier from types which are not internally accessible
3661 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3662 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3663 base_modifiers = Modifiers.PROTECTED;
3665 Report.SymbolRelatedToPreviousError (base_member);
3666 Report.Error (507, member.Location,
3667 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3668 member.GetSignatureForError (),
3669 ModifiersExtensions.AccessibilityName (base_modifiers),
3670 base_member.GetSignatureForError ());
3673 protected void Error_StaticReturnType ()
3675 Report.Error (722, Location,
3676 "`{0}': static types cannot be used as return types",
3677 MemberType.GetSignatureForError ());
3681 /// Gets base method and its return type
3683 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3685 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3689 // The "short" name of this property / indexer / event. This is the
3690 // name without the explicit interface.
3692 public string ShortName {
3693 get { return MemberName.Name; }
3697 // Returns full metadata method name
3699 public string GetFullName (MemberName name)
3701 return GetFullName (name.Name);
3704 public string GetFullName (string name)
3706 if (!IsExplicitImpl)
3710 // When dealing with explicit members a full interface type
3711 // name is added to member name to avoid possible name conflicts
3713 // We use CSharpName which gets us full name with benefit of
3714 // replacing predefined names which saves some space and name
3717 return InterfaceType.GetSignatureForError () + "." + name;
3720 public override string GetSignatureForDocumentation ()
3723 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3725 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3728 public override bool IsUsed
3730 get { return IsExplicitImpl || base.IsUsed; }
3733 public override void SetConstraints (List<Constraints> constraints_list)
3735 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3736 Report.Error (460, Location,
3737 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3738 GetSignatureForError ());
3741 base.SetConstraints (constraints_list);
3745 public abstract class MemberBase : MemberCore
3747 protected FullNamedExpression type_expr;
3748 protected TypeSpec member_type;
3749 public new TypeDefinition Parent;
3751 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3752 : base (parent, name, attrs)
3754 this.Parent = parent;
3755 this.type_expr = type;
3757 if (name != MemberName.Null)
3758 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3763 public TypeSpec MemberType {
3769 public FullNamedExpression TypeExpression {
3781 // Main member define entry
3783 public override bool Define ()
3785 DoMemberTypeIndependentChecks ();
3788 // Returns false only when type resolution failed
3790 if (!ResolveMemberType ())
3793 DoMemberTypeDependentChecks ();
3798 // Any type_name independent checks
3800 protected virtual void DoMemberTypeIndependentChecks ()
3802 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3803 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3804 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3805 GetSignatureForError (), Parent.GetSignatureForError ());
3810 // Any type_name dependent checks
3812 protected virtual void DoMemberTypeDependentChecks ()
3814 // verify accessibility
3815 if (!IsAccessibleAs (MemberType)) {
3816 Report.SymbolRelatedToPreviousError (MemberType);
3817 if (this is Property)
3818 Report.Error (53, Location,
3819 "Inconsistent accessibility: property type `" +
3820 MemberType.GetSignatureForError () + "' is less " +
3821 "accessible than property `" + GetSignatureForError () + "'");
3822 else if (this is Indexer)
3823 Report.Error (54, Location,
3824 "Inconsistent accessibility: indexer return type `" +
3825 MemberType.GetSignatureForError () + "' is less " +
3826 "accessible than indexer `" + GetSignatureForError () + "'");
3827 else if (this is MethodCore) {
3828 if (this is Operator)
3829 Report.Error (56, Location,
3830 "Inconsistent accessibility: return type `" +
3831 MemberType.GetSignatureForError () + "' is less " +
3832 "accessible than operator `" + GetSignatureForError () + "'");
3834 Report.Error (50, Location,
3835 "Inconsistent accessibility: return type `" +
3836 MemberType.GetSignatureForError () + "' is less " +
3837 "accessible than method `" + GetSignatureForError () + "'");
3838 } else if (this is Event) {
3839 Report.Error (7025, Location,
3840 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3841 MemberType.GetSignatureForError (), GetSignatureForError ());
3843 Report.Error (52, Location,
3844 "Inconsistent accessibility: field type `" +
3845 MemberType.GetSignatureForError () + "' is less " +
3846 "accessible than field `" + GetSignatureForError () + "'");
3851 protected void IsTypePermitted ()
3853 if (MemberType.IsSpecialRuntimeType) {
3854 if (Parent is StateMachine) {
3855 Report.Error (4012, Location,
3856 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3857 MemberType.GetSignatureForError ());
3858 } else if (Parent is HoistedStoreyClass) {
3859 Report.Error (4013, Location,
3860 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3861 MemberType.GetSignatureForError ());
3863 Report.Error (610, Location,
3864 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3869 protected virtual bool CheckBase ()
3871 CheckProtectedModifier ();
3876 public override string GetSignatureForDocumentation ()
3878 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3881 public virtual void PrepareEmit ()
3883 if (member_type != null && type_expr != null)
3884 member_type.CheckObsoleteness (this, type_expr.Location);
3887 protected virtual bool ResolveMemberType ()
3889 if (member_type != null)
3890 throw new InternalErrorException ("Multi-resolve");
3892 member_type = type_expr.ResolveAsType (this);
3893 return member_type != null;