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. User
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;
533 protected bool requires_delayed_unmanagedtype_check;
535 bool members_defined;
536 bool members_defined_ok;
537 protected bool has_static_constructor;
539 private CachedMethods cached_method;
541 protected TypeSpec spec;
542 TypeSpec current_type;
544 public int DynamicSitesCounter;
545 public int AnonymousMethodsCounter;
546 public int MethodGroupsCounter;
548 static readonly string[] attribute_targets = new [] { "type" };
549 static readonly string[] attribute_targets_primary = new [] { "type", "method" };
552 /// The pending methods that need to be implemented
553 // (interfaces or abstract methods)
555 PendingImplementation pending;
557 protected TypeDefinition (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
558 : base (parent, name, attrs, kind)
560 PartialContainer = this;
561 members = new List<MemberCore> ();
566 public List<FullNamedExpression> BaseTypeExpressions {
572 public override TypeSpec CurrentType {
574 if (current_type == null) {
575 if (IsGenericOrParentIsGeneric) {
577 // Switch to inflated version as it's used by all expressions
579 var targs = CurrentTypeParameters == null ? TypeSpec.EmptyTypes : CurrentTypeParameters.Types;
580 current_type = spec.MakeGenericType (this, targs);
590 public override TypeParameters CurrentTypeParameters {
592 return PartialContainer.MemberName.TypeParameters;
596 int CurrentTypeParametersStartIndex {
598 int total = all_tp_builders.Length;
599 if (CurrentTypeParameters != null) {
600 return total - CurrentTypeParameters.Count;
606 public virtual AssemblyDefinition DeclaringAssembly {
608 return Module.DeclaringAssembly;
612 IAssemblyDefinition ITypeDefinition.DeclaringAssembly {
614 return Module.DeclaringAssembly;
618 public TypeSpec Definition {
624 public bool HasMembersDefined {
626 return members_defined;
630 public bool HasInstanceConstructor {
632 return (caching_flags & Flags.HasInstanceConstructor) != 0;
635 caching_flags |= Flags.HasInstanceConstructor;
639 // Indicated whether container has StructLayout attribute set Explicit
640 public bool HasExplicitLayout {
641 get { return (caching_flags & Flags.HasExplicitLayout) != 0; }
642 set { caching_flags |= Flags.HasExplicitLayout; }
645 public bool HasOperators {
647 return (caching_flags & Flags.HasUserOperators) != 0;
650 caching_flags |= Flags.HasUserOperators;
654 public bool HasStructLayout {
655 get { return (caching_flags & Flags.HasStructLayout) != 0; }
656 set { caching_flags |= Flags.HasStructLayout; }
659 public TypeSpec[] Interfaces {
665 public bool IsGenericOrParentIsGeneric {
667 return all_type_parameters != null;
671 public bool IsTopLevel {
673 return !(Parent is TypeDefinition);
677 public bool IsPartial {
679 return (ModFlags & Modifiers.PARTIAL) != 0;
683 bool ITypeDefinition.IsTypeForwarder {
689 bool ITypeDefinition.IsCyclicTypeForwarder {
696 // Returns true for secondary partial containers
700 return PartialContainer != this;
704 public MemberCache MemberCache {
706 return spec.MemberCache;
710 public List<MemberCore> Members {
716 string ITypeDefinition.Namespace {
719 while (p.Kind != MemberKind.Namespace)
722 return p.MemberName == null ? null : p.GetSignatureForError ();
726 public ParametersCompiled PrimaryConstructorParameters { get; set; }
728 public Arguments PrimaryConstructorBaseArguments { get; set; }
730 public Location PrimaryConstructorBaseArgumentsStart { get; set; }
732 public TypeParameters TypeParametersAll {
734 return all_type_parameters;
738 public override string[] ValidAttributeTargets {
740 return PrimaryConstructorParameters != null ? attribute_targets_primary : attribute_targets;
746 public override void Accept (StructuralVisitor visitor)
748 visitor.Visit (this);
751 public void AddMember (MemberCore symbol)
753 if (symbol.MemberName.ExplicitInterface != null) {
754 if (!(Kind == MemberKind.Class || Kind == MemberKind.Struct)) {
755 Report.Error (541, symbol.Location,
756 "`{0}': explicit interface declaration can only be declared in a class or struct",
757 symbol.GetSignatureForError ());
761 AddNameToContainer (symbol, symbol.MemberName.Name);
762 members.Add (symbol);
765 public override void AddTypeContainer (TypeContainer tc)
767 AddNameToContainer (tc, tc.MemberName.Basename);
769 base.AddTypeContainer (tc);
772 protected override void AddTypeContainerMember (TypeContainer tc)
776 if (containers == null)
777 containers = new List<TypeContainer> ();
779 base.AddTypeContainerMember (tc);
783 // Adds the member to defined_names table. It tests for duplications and enclosing name conflicts
785 public virtual void AddNameToContainer (MemberCore symbol, string name)
787 if (((ModFlags | symbol.ModFlags) & Modifiers.COMPILER_GENERATED) != 0)
791 if (!PartialContainer.defined_names.TryGetValue (name, out mc)) {
792 PartialContainer.defined_names.Add (name, symbol);
796 if (symbol.EnableOverloadChecks (mc))
799 InterfaceMemberBase im = mc as InterfaceMemberBase;
800 if (im != null && im.IsExplicitImpl)
803 Report.SymbolRelatedToPreviousError (mc);
804 if ((mc.ModFlags & Modifiers.PARTIAL) != 0 && (symbol is ClassOrStruct || symbol is Interface)) {
805 Error_MissingPartialModifier (symbol);
809 if (symbol is TypeParameter) {
810 Report.Error (692, symbol.Location,
811 "Duplicate type parameter `{0}'", symbol.GetSignatureForError ());
813 Report.Error (102, symbol.Location,
814 "The type `{0}' already contains a definition for `{1}'",
815 GetSignatureForError (), name);
821 public void AddConstructor (Constructor c)
823 AddConstructor (c, false);
826 public void AddConstructor (Constructor c, bool isDefault)
828 bool is_static = (c.ModFlags & Modifiers.STATIC) != 0;
830 AddNameToContainer (c, is_static ? Constructor.TypeConstructorName : Constructor.ConstructorName);
832 if (is_static && c.ParameterInfo.IsEmpty) {
833 PartialContainer.has_static_constructor = true;
835 PartialContainer.HasInstanceConstructor = true;
841 public bool AddField (FieldBase field)
845 if ((field.ModFlags & Modifiers.STATIC) != 0)
848 var first_field = PartialContainer.first_nonstatic_field;
849 if (first_field == null) {
850 PartialContainer.first_nonstatic_field = field;
854 if (Kind == MemberKind.Struct && first_field.Parent != field.Parent) {
855 Report.SymbolRelatedToPreviousError (first_field.Parent);
856 Report.Warning (282, 3, field.Location,
857 "struct instance field `{0}' found in different declaration from instance field `{1}'",
858 field.GetSignatureForError (), first_field.GetSignatureForError ());
864 /// Indexer has special handling in constrast to other AddXXX because the name can be driven by IndexerNameAttribute
866 public void AddIndexer (Indexer i)
871 public void AddOperator (Operator op)
873 PartialContainer.HasOperators = true;
877 public void AddPartialPart (TypeDefinition part)
879 if (Kind != MemberKind.Class)
882 if (class_partial_parts == null)
883 class_partial_parts = new List<TypeDefinition> ();
885 class_partial_parts.Add (part);
888 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
890 if (a.Target == AttributeTargets.Method) {
891 foreach (var m in members) {
892 var c = m as Constructor;
896 if (c.IsPrimaryConstructor) {
897 c.ApplyAttributeBuilder (a, ctor, cdata, pa);
902 throw new InternalErrorException ();
905 if (has_normal_indexers && a.Type == pa.DefaultMember) {
906 Report.Error (646, a.Location, "Cannot specify the `DefaultMember' attribute on type containing an indexer");
910 if (a.Type == pa.Required) {
911 Report.Error (1608, a.Location, "The RequiredAttribute attribute is not permitted on C# types");
915 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), cdata);
918 public override AttributeTargets AttributeTargets {
920 throw new NotSupportedException ();
924 public TypeSpec BaseType {
926 return spec.BaseType;
930 protected virtual TypeAttributes TypeAttr {
932 return ModifiersExtensions.TypeAttr (ModFlags, IsTopLevel);
936 public int TypeParametersCount {
938 return MemberName.Arity;
942 TypeParameterSpec[] ITypeDefinition.TypeParameters {
944 return PartialContainer.CurrentTypeParameters.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 PropertyBasedMember;
1738 var mc = member as MethodCore;
1744 var c = member as Const;
1749 base.PrepareEmit ();
1753 // Defines the type in the appropriate ModuleBuilder or TypeBuilder.
1755 public override bool CreateContainer ()
1757 if (TypeBuilder != null)
1763 if (IsPartialPart) {
1764 spec = PartialContainer.spec;
1765 TypeBuilder = PartialContainer.TypeBuilder;
1766 all_tp_builders = PartialContainer.all_tp_builders;
1767 all_type_parameters = PartialContainer.all_type_parameters;
1769 if (!CreateTypeBuilder ()) {
1775 return base.CreateContainer ();
1778 protected override void DoDefineContainer ()
1782 DoResolveTypeParameters ();
1786 // Replaces normal spec with predefined one when compiling corlib
1787 // and this type container defines predefined type
1789 public void SetPredefinedSpec (BuiltinTypeSpec spec)
1791 // When compiling build-in types we start with two
1792 // version of same type. One is of BuiltinTypeSpec and
1793 // second one is ordinary TypeSpec. The unification
1794 // happens at later stage when we know which type
1795 // really matches the builtin type signature. However
1796 // that means TypeSpec create during CreateType of this
1797 // type has to be replaced with builtin one
1799 spec.SetMetaInfo (TypeBuilder);
1800 spec.MemberCache = this.spec.MemberCache;
1801 spec.DeclaringType = this.spec.DeclaringType;
1804 current_type = null;
1807 public override void RemoveContainer (TypeContainer cont)
1809 base.RemoveContainer (cont);
1810 Members.Remove (cont);
1811 Cache.Remove (cont.MemberName.Basename);
1814 protected virtual bool DoResolveTypeParameters ()
1816 var tparams = MemberName.TypeParameters;
1817 if (tparams == null)
1820 var base_context = new BaseContext (this);
1821 for (int i = 0; i < tparams.Count; ++i) {
1822 var tp = tparams[i];
1824 if (!tp.ResolveConstraints (base_context)) {
1829 if (IsPartialPart) {
1830 var pc_tp = PartialContainer.CurrentTypeParameters [i];
1832 tp.Create (spec, this);
1835 if (tp.OptAttributes != null) {
1836 if (pc_tp.OptAttributes == null)
1837 pc_tp.OptAttributes = tp.OptAttributes;
1839 pc_tp.OptAttributes.Attrs.AddRange (tp.OptAttributes.Attrs);
1844 if (IsPartialPart) {
1845 PartialContainer.CurrentTypeParameters.UpdateConstraints (this);
1851 TypeSpec CheckRecursiveDefinition (TypeDefinition tc)
1853 if (InTransit != null)
1858 if (base_type != null) {
1859 var ptc = base_type.MemberDefinition as TypeDefinition;
1860 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1864 if (iface_exprs != null) {
1865 foreach (var iface in iface_exprs) {
1866 // the interface might not have been resolved, prevents a crash, see #442144
1869 var ptc = iface.MemberDefinition as Interface;
1870 if (ptc != null && ptc.CheckRecursiveDefinition (this) != null)
1875 if (!IsTopLevel && Parent.PartialContainer.CheckRecursiveDefinition (this) != null)
1883 /// Populates our TypeBuilder with fields and methods
1885 public sealed override bool Define ()
1887 if (members_defined)
1888 return members_defined_ok;
1890 members_defined_ok = DoDefineMembers ();
1891 members_defined = true;
1895 return members_defined_ok;
1898 protected virtual bool DoDefineMembers ()
1900 Debug.Assert (!IsPartialPart);
1902 if (iface_exprs != null) {
1903 foreach (var iface_type in iface_exprs) {
1904 if (iface_type == null)
1907 // Ensure the base is always setup
1908 var compiled_iface = iface_type.MemberDefinition as Interface;
1909 if (compiled_iface != null)
1910 compiled_iface.Define ();
1912 ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
1913 if (oa != null && !IsObsolete)
1914 AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);
1916 if (iface_type.Arity > 0) {
1917 // TODO: passing `this' is wrong, should be base type iface instead
1918 VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);
1920 if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
1921 Report.Error (1966, Location,
1922 "`{0}': cannot implement a dynamic interface `{1}'",
1923 GetSignatureForError (), iface_type.GetSignatureForError ());
1928 if (iface_type.IsGenericOrParentIsGeneric) {
1929 foreach (var prev_iface in iface_exprs) {
1930 if (prev_iface == iface_type || prev_iface == null)
1933 if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
1936 Report.Error (695, Location,
1937 "`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
1938 GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
1943 if (Kind == MemberKind.Interface) {
1944 foreach (var iface in spec.Interfaces) {
1945 MemberCache.AddInterface (iface);
1950 if (base_type != null) {
1952 // Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
1954 if (base_type_expr != null) {
1955 ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
1956 if (obsolete_attr != null && !IsObsolete)
1957 AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);
1959 if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
1960 Report.Error (698, base_type_expr.Location,
1961 "A generic type cannot derive from `{0}' because it is an attribute class",
1962 base_type.GetSignatureForError ());
1966 var baseContainer = base_type.MemberDefinition as ClassOrStruct;
1967 if (baseContainer != null) {
1968 baseContainer.Define ();
1971 // It can trigger define of this type (for generic types only)
1973 if (HasMembersDefined)
1978 if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
1979 pending = PendingImplementation.GetPendingImplementations (this);
1982 var count = members.Count;
1983 for (int i = 0; i < count; ++i) {
1984 var mc = members[i] as InterfaceMemberBase;
1985 if (mc == null || !mc.IsExplicitImpl)
1990 } catch (Exception e) {
1991 throw new InternalErrorException (mc, e);
1995 for (int i = 0; i < count; ++i) {
1996 var mc = members[i] as InterfaceMemberBase;
1997 if (mc != null && mc.IsExplicitImpl)
2000 if (members[i] is TypeContainer)
2004 members[i].Define ();
2005 } catch (Exception e) {
2006 throw new InternalErrorException (members[i], e);
2011 CheckPairedOperators ();
2014 if (requires_delayed_unmanagedtype_check) {
2015 requires_delayed_unmanagedtype_check = false;
2016 foreach (var member in members) {
2017 var f = member as Field;
2018 if (f != null && f.MemberType != null && f.MemberType.IsPointer)
2019 TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
2023 ComputeIndexerName();
2025 if (HasEquals && !HasGetHashCode) {
2026 Report.Warning (659, 3, Location,
2027 "`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
2030 if (Kind == MemberKind.Interface && iface_exprs != null) {
2031 MemberCache.RemoveHiddenMembers (spec);
2037 void ComputeIndexerName ()
2039 var indexers = MemberCache.FindMembers (spec, MemberCache.IndexerNameAlias, true);
2040 if (indexers == null)
2043 string class_indexer_name = null;
2046 // Check normal indexers for consistent name, explicit interface implementation
2047 // indexers are ignored
2049 foreach (var indexer in indexers) {
2051 // FindMembers can return unfiltered full hierarchy names
2053 if (indexer.DeclaringType != spec)
2056 has_normal_indexers = true;
2058 if (class_indexer_name == null) {
2059 indexer_name = class_indexer_name = indexer.Name;
2063 if (indexer.Name != class_indexer_name)
2064 Report.Error (668, ((Indexer)indexer.MemberDefinition).Location,
2065 "Two indexers have different names; the IndexerName attribute must be used with the same name on every indexer within a type");
2069 void EmitIndexerName ()
2071 if (!has_normal_indexers)
2074 var ctor = Module.PredefinedMembers.DefaultMemberAttributeCtor.Get ();
2078 var encoder = new AttributeEncoder ();
2079 encoder.Encode (GetAttributeDefaultMember ());
2080 encoder.EncodeEmptyNamedArguments ();
2082 TypeBuilder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2085 public override void VerifyMembers ()
2088 // Check for internal or private fields that were never assigned
2090 if (!IsCompilerGenerated && Compiler.Settings.WarningLevel >= 3 && this == PartialContainer) {
2091 bool is_type_exposed = Kind == MemberKind.Struct || IsExposedFromAssembly ();
2092 foreach (var member in members) {
2093 if (member is Event) {
2095 // An event can be assigned from same class only, report
2096 // this warning for all accessibility modes
2098 if (!member.IsUsed && !PartialContainer.HasStructLayout)
2099 Report.Warning (67, 3, member.Location, "The event `{0}' is never used", member.GetSignatureForError ());
2104 if ((member.ModFlags & Modifiers.AccessibilityMask) != Modifiers.PRIVATE) {
2105 if (is_type_exposed)
2108 member.SetIsUsed ();
2111 var f = member as Field;
2115 if (!member.IsUsed) {
2116 if (!PartialContainer.HasStructLayout) {
2117 if ((member.caching_flags & Flags.IsAssigned) == 0) {
2118 Report.Warning (169, 3, member.Location, "The private field `{0}' is never used", member.GetSignatureForError ());
2120 Report.Warning (414, 3, member.Location, "The private field `{0}' is assigned but its value is never used",
2121 member.GetSignatureForError ());
2128 if ((f.caching_flags & Flags.IsAssigned) != 0)
2132 // Only report 649 on level 4
2134 if (Compiler.Settings.WarningLevel < 4)
2138 // Don't be pedantic when type requires specific layout
2140 if (f.OptAttributes != null || PartialContainer.HasStructLayout)
2143 Constant c = New.Constantify (f.MemberType, f.Location);
2146 value = c.GetValueAsLiteral ();
2147 } else if (TypeSpec.IsReferenceType (f.MemberType)) {
2154 value = " `" + value + "'";
2156 Report.Warning (649, 4, f.Location, "Field `{0}' is never assigned to, and will always have its default value{1}",
2157 f.GetSignatureForError (), value);
2161 base.VerifyMembers ();
2164 public override void Emit ()
2166 if (OptAttributes != null)
2167 OptAttributes.Emit ();
2169 if (!IsCompilerGenerated) {
2171 MemberSpec candidate;
2172 bool overrides = false;
2173 var conflict_symbol = MemberCache.FindBaseMember (this, out candidate, ref overrides);
2174 if (conflict_symbol == null && candidate == null) {
2175 if ((ModFlags & Modifiers.NEW) != 0)
2176 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
2177 GetSignatureForError ());
2179 if ((ModFlags & Modifiers.NEW) == 0) {
2180 if (candidate == null)
2181 candidate = conflict_symbol;
2183 Report.SymbolRelatedToPreviousError (candidate);
2184 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
2185 GetSignatureForError (), candidate.GetSignatureForError ());
2190 // Run constraints check on all possible generic types
2191 if (base_type != null && base_type_expr != null) {
2192 ConstraintChecker.Check (this, base_type, base_type_expr.Location);
2195 if (iface_exprs != null) {
2196 foreach (var iface_type in iface_exprs) {
2197 if (iface_type == null)
2200 ConstraintChecker.Check (this, iface_type, Location); // TODO: Location is wrong
2205 if (all_tp_builders != null) {
2206 int current_starts_index = CurrentTypeParametersStartIndex;
2207 for (int i = 0; i < all_tp_builders.Length; i++) {
2208 if (i < current_starts_index) {
2209 all_type_parameters[i].EmitConstraints (all_tp_builders [i]);
2211 var tp = CurrentTypeParameters [i - current_starts_index];
2212 tp.CheckGenericConstraints (!IsObsolete);
2218 if ((ModFlags & Modifiers.COMPILER_GENERATED) != 0 && !Parent.IsCompilerGenerated)
2219 Module.PredefinedAttributes.CompilerGenerated.EmitAttribute (TypeBuilder);
2222 if ((TypeBuilder.Attributes & TypeAttributes.StringFormatMask) == 0 && Module.HasDefaultCharSet)
2223 TypeBuilder.__SetAttributes (TypeBuilder.Attributes | Module.DefaultCharSetType);
2228 for (int i = 0; i < members.Count; i++) {
2230 if ((m.caching_flags & Flags.CloseTypeCreated) != 0)
2237 CheckAttributeClsCompliance ();
2239 if (pending != null)
2240 pending.VerifyPendingMethods ();
2244 void CheckAttributeClsCompliance ()
2246 if (!spec.IsAttribute || !IsExposedFromAssembly () || !Compiler.Settings.VerifyClsCompliance || !IsClsComplianceRequired ())
2249 foreach (var m in members) {
2250 var c = m as Constructor;
2254 if (c.HasCompliantArgs)
2258 Report.Warning (3015, 1, Location, "`{0}' has no accessible constructors which use only CLS-compliant types", GetSignatureForError ());
2261 public sealed override void EmitContainer ()
2263 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2269 public override void CloseContainer ()
2271 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2274 // Close base type container first to avoid TypeLoadException
2275 if (spec.BaseType != null) {
2276 var btype = spec.BaseType.MemberDefinition as TypeContainer;
2277 if (btype != null) {
2278 btype.CloseContainer ();
2280 if ((caching_flags & Flags.CloseTypeCreated) != 0)
2286 caching_flags |= Flags.CloseTypeCreated;
2287 TypeBuilder.CreateType ();
2288 } catch (TypeLoadException) {
2290 // This is fine, the code still created the type
2292 } catch (Exception e) {
2293 throw new InternalErrorException (this, e);
2296 base.CloseContainer ();
2299 initialized_fields = null;
2300 initialized_static_fields = null;
2302 OptAttributes = null;
2306 // Performs the validation on a Method's modifiers (properties have
2307 // the same properties).
2309 // TODO: Why is it not done at parse stage, move to Modifiers::Check
2311 public bool MethodModifiersValid (MemberCore mc)
2313 const Modifiers vao = (Modifiers.VIRTUAL | Modifiers.ABSTRACT | Modifiers.OVERRIDE);
2314 const Modifiers nv = (Modifiers.NEW | Modifiers.VIRTUAL);
2316 var flags = mc.ModFlags;
2319 // At most one of static, virtual or override
2321 if ((flags & Modifiers.STATIC) != 0){
2322 if ((flags & vao) != 0){
2323 Report.Error (112, mc.Location, "A static member `{0}' cannot be marked as override, virtual or abstract",
2324 mc.GetSignatureForError ());
2329 if ((flags & Modifiers.OVERRIDE) != 0 && (flags & nv) != 0){
2330 Report.Error (113, mc.Location, "A member `{0}' marked as override cannot be marked as new or virtual",
2331 mc.GetSignatureForError ());
2336 // If the declaration includes the abstract modifier, then the
2337 // declaration does not include static, virtual or extern
2339 if ((flags & Modifiers.ABSTRACT) != 0){
2340 if ((flags & Modifiers.EXTERN) != 0){
2342 180, mc.Location, "`{0}' cannot be both extern and abstract", mc.GetSignatureForError ());
2346 if ((flags & Modifiers.SEALED) != 0) {
2347 Report.Error (502, mc.Location, "`{0}' cannot be both abstract and sealed", mc.GetSignatureForError ());
2351 if ((flags & Modifiers.VIRTUAL) != 0){
2352 Report.Error (503, mc.Location, "The abstract method `{0}' cannot be marked virtual", mc.GetSignatureForError ());
2356 if ((ModFlags & Modifiers.ABSTRACT) == 0){
2357 Report.SymbolRelatedToPreviousError (this);
2358 Report.Error (513, mc.Location, "`{0}' is abstract but it is declared in the non-abstract class `{1}'",
2359 mc.GetSignatureForError (), GetSignatureForError ());
2364 if ((flags & Modifiers.PRIVATE) != 0){
2365 if ((flags & vao) != 0){
2366 Report.Error (621, mc.Location, "`{0}': virtual or abstract members cannot be private", mc.GetSignatureForError ());
2371 if ((flags & Modifiers.SEALED) != 0){
2372 if ((flags & Modifiers.OVERRIDE) == 0){
2373 Report.Error (238, mc.Location, "`{0}' cannot be sealed because it is not an override", mc.GetSignatureForError ());
2381 protected override bool VerifyClsCompliance ()
2383 if (!base.VerifyClsCompliance ())
2386 // Check all container names for user classes
2387 if (Kind != MemberKind.Delegate)
2388 MemberCache.VerifyClsCompliance (Definition, Report);
2390 if (BaseType != null && !BaseType.IsCLSCompliant ()) {
2391 Report.Warning (3009, 1, Location, "`{0}': base type `{1}' is not CLS-compliant",
2392 GetSignatureForError (), BaseType.GetSignatureForError ());
2398 /// Performs checks for an explicit interface implementation. First it
2399 /// checks whether the `interface_type' is a base inteface implementation.
2400 /// Then it checks whether `name' exists in the interface type.
2402 public bool VerifyImplements (InterfaceMemberBase mb)
2404 var ifaces = PartialContainer.Interfaces;
2405 if (ifaces != null) {
2406 foreach (TypeSpec t in ifaces){
2407 if (t == mb.InterfaceType)
2410 var expanded_base = t.Interfaces;
2411 if (expanded_base == null)
2414 foreach (var bt in expanded_base) {
2415 if (bt == mb.InterfaceType)
2421 Report.SymbolRelatedToPreviousError (mb.InterfaceType);
2422 Report.Error (540, mb.Location, "`{0}': containing type does not implement interface `{1}'",
2423 mb.GetSignatureForError (), mb.InterfaceType.GetSignatureForError ());
2428 // Used for visiblity checks to tests whether this definition shares
2429 // base type baseType, it does member-definition search
2431 public bool IsBaseTypeDefinition (TypeSpec baseType)
2433 // RootContext check
2434 if (TypeBuilder == null)
2439 if (type.MemberDefinition == baseType.MemberDefinition)
2442 type = type.BaseType;
2443 } while (type != null);
2448 public override bool IsClsComplianceRequired ()
2451 return PartialContainer.IsClsComplianceRequired ();
2453 return base.IsClsComplianceRequired ();
2456 bool ITypeDefinition.IsInternalAsPublic (IAssemblyDefinition assembly)
2458 return Module.DeclaringAssembly == assembly;
2461 public virtual bool IsUnmanagedType ()
2466 public void LoadMembers (TypeSpec declaringType, bool onlyTypes, ref MemberCache cache)
2468 throw new NotSupportedException ("Not supported for compiled definition " + GetSignatureForError ());
2472 // Public function used to locate types.
2474 // Returns: Type or null if they type can not be found.
2476 public override FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc)
2478 FullNamedExpression e;
2479 if (arity == 0 && Cache.TryGetValue (name, out e) && mode != LookupMode.IgnoreAccessibility)
2485 var tp = CurrentTypeParameters;
2487 TypeParameter tparam = tp.Find (name);
2489 e = new TypeParameterExpr (tparam, Location.Null);
2494 TypeSpec t = LookupNestedTypeInHierarchy (name, arity);
2496 if (t != null && (t.IsAccessible (this) || mode == LookupMode.IgnoreAccessibility))
2497 e = new TypeExpression (t, Location.Null);
2499 var errors = Compiler.Report.Errors;
2500 e = Parent.LookupNamespaceOrType (name, arity, mode, loc);
2502 // TODO: LookupNamespaceOrType does more than just lookup. The result
2503 // cannot be cached or the error reporting won't happen
2504 if (errors != Compiler.Report.Errors)
2509 // TODO MemberCache: How to cache arity stuff ?
2510 if (arity == 0 && mode == LookupMode.Normal)
2516 TypeSpec LookupNestedTypeInHierarchy (string name, int arity)
2518 // Has any nested type
2519 // Does not work, because base type can have
2520 //if (PartialContainer.Types == null)
2523 var container = PartialContainer.CurrentType;
2524 return MemberCache.FindNestedType (container, name, arity);
2527 public void Mark_HasEquals ()
2529 cached_method |= CachedMethods.Equals;
2532 public void Mark_HasGetHashCode ()
2534 cached_method |= CachedMethods.GetHashCode;
2537 public override void WriteDebugSymbol (MonoSymbolFile file)
2542 foreach (var m in members) {
2543 m.WriteDebugSymbol (file);
2548 /// Method container contains Equals method
2550 public bool HasEquals {
2552 return (cached_method & CachedMethods.Equals) != 0;
2557 /// Method container contains GetHashCode method
2559 public bool HasGetHashCode {
2561 return (cached_method & CachedMethods.GetHashCode) != 0;
2565 public bool HasStaticFieldInitializer {
2567 return (cached_method & CachedMethods.HasStaticFieldInitializer) != 0;
2571 cached_method |= CachedMethods.HasStaticFieldInitializer;
2573 cached_method &= ~CachedMethods.HasStaticFieldInitializer;
2577 public override string DocCommentHeader {
2578 get { return "T:"; }
2582 public abstract class ClassOrStruct : TypeDefinition
2584 public const TypeAttributes StaticClassAttribute = TypeAttributes.Abstract | TypeAttributes.Sealed;
2586 SecurityType declarative_security;
2587 protected Constructor generated_primary_constructor;
2589 protected ClassOrStruct (TypeContainer parent, MemberName name, Attributes attrs, MemberKind kind)
2590 : base (parent, name, attrs, kind)
2594 public ToplevelBlock PrimaryConstructorBlock { get; set; }
2596 protected override TypeAttributes TypeAttr {
2598 TypeAttributes ta = base.TypeAttr;
2599 if (!has_static_constructor)
2600 ta |= TypeAttributes.BeforeFieldInit;
2602 if (Kind == MemberKind.Class) {
2603 ta |= TypeAttributes.AutoLayout | TypeAttributes.Class;
2605 ta |= StaticClassAttribute;
2607 ta |= TypeAttributes.SequentialLayout;
2614 public override void AddNameToContainer (MemberCore symbol, string name)
2616 if (!(symbol is Constructor) && symbol.MemberName.Name == MemberName.Name) {
2617 if (symbol is TypeParameter) {
2618 Report.Error (694, symbol.Location,
2619 "Type parameter `{0}' has same name as containing type, or method",
2620 symbol.GetSignatureForError ());
2624 InterfaceMemberBase imb = symbol as InterfaceMemberBase;
2625 if (imb == null || !imb.IsExplicitImpl) {
2626 Report.SymbolRelatedToPreviousError (this);
2627 Report.Error (542, symbol.Location, "`{0}': member names cannot be the same as their enclosing type",
2628 symbol.GetSignatureForError ());
2633 base.AddNameToContainer (symbol, name);
2636 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2638 if (a.IsValidSecurityAttribute ()) {
2639 a.ExtractSecurityPermissionSet (ctor, ref declarative_security);
2643 if (a.Type == pa.StructLayout) {
2644 PartialContainer.HasStructLayout = true;
2645 if (a.IsExplicitLayoutKind ())
2646 PartialContainer.HasExplicitLayout = true;
2649 if (a.Type == pa.Dynamic) {
2650 a.Error_MisusedDynamicAttribute ();
2654 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2658 /// Defines the default constructors
2660 protected virtual Constructor DefineDefaultConstructor (bool is_static)
2662 // The default instance constructor is public
2663 // If the class is abstract, the default constructor is protected
2664 // The default static constructor is private
2667 ParametersCompiled parameters = null;
2669 mods = Modifiers.STATIC | Modifiers.PRIVATE;
2670 parameters = ParametersCompiled.EmptyReadOnlyParameters;
2672 mods = ((ModFlags & Modifiers.ABSTRACT) != 0) ? Modifiers.PROTECTED : Modifiers.PUBLIC;
2673 parameters = PrimaryConstructorParameters ?? ParametersCompiled.EmptyReadOnlyParameters;
2676 var c = new Constructor (this, MemberName.Name, mods, null, parameters, Location);
2677 if (Kind == MemberKind.Class)
2678 c.Initializer = new GeneratedBaseInitializer (Location, PrimaryConstructorBaseArguments);
2680 if (PrimaryConstructorParameters != null && !is_static) {
2681 c.IsPrimaryConstructor = true;
2682 c.caching_flags |= Flags.MethodOverloadsExist;
2685 AddConstructor (c, true);
2686 if (PrimaryConstructorBlock == null) {
2687 c.Block = new ToplevelBlock (Compiler, parameters, Location) {
2688 IsCompilerGenerated = true
2691 c.Block = PrimaryConstructorBlock;
2697 protected override bool DoDefineMembers ()
2699 CheckProtectedModifier ();
2701 if (PrimaryConstructorParameters != null) {
2703 foreach (Parameter p in PrimaryConstructorParameters.FixedParameters) {
2704 if (p.Name == MemberName.Name) {
2705 Report.Error (8039, p.Location, "Primary constructor of type `{0}' has parameter of same name as containing type",
2706 GetSignatureForError ());
2709 if (CurrentTypeParameters != null) {
2710 for (int i = 0; i < CurrentTypeParameters.Count; ++i) {
2711 var tp = CurrentTypeParameters [i];
2712 if (p.Name == tp.Name) {
2713 Report.Error (8038, p.Location, "Primary constructor of type `{0}' has parameter of same name as type parameter `{1}'",
2714 GetSignatureForError (), p.GetSignatureForError ());
2721 base.DoDefineMembers ();
2726 public override void Emit ()
2728 if (!has_static_constructor && HasStaticFieldInitializer) {
2729 var c = DefineDefaultConstructor (true);
2735 if (declarative_security != null) {
2736 foreach (var de in declarative_security) {
2738 TypeBuilder.__AddDeclarativeSecurity (de);
2740 TypeBuilder.AddDeclarativeSecurity (de.Key, de.Value);
2748 public sealed class Class : ClassOrStruct
2750 const Modifiers AllowedModifiers =
2753 Modifiers.PROTECTED |
2754 Modifiers.INTERNAL |
2756 Modifiers.ABSTRACT |
2761 public Class (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2762 : base (parent, name, attrs, MemberKind.Class)
2764 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2765 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report);
2766 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2769 public override void Accept (StructuralVisitor visitor)
2771 visitor.Visit (this);
2774 public override void SetBaseTypes (List<FullNamedExpression> baseTypes)
2776 var pmn = MemberName;
2777 if (pmn.Name == "Object" && !pmn.IsGeneric && Parent.MemberName.Name == "System" && Parent.MemberName.Left == null)
2778 Report.Error (537, Location,
2779 "The class System.Object cannot have a base class or implement an interface.");
2781 base.SetBaseTypes (baseTypes);
2784 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
2786 if (a.Type == pa.AttributeUsage) {
2787 if (!BaseType.IsAttribute && spec.BuiltinType != BuiltinTypeSpec.Type.Attribute) {
2788 Report.Error (641, a.Location, "Attribute `{0}' is only valid on classes derived from System.Attribute", a.GetSignatureForError ());
2792 if (a.Type == pa.Conditional && !BaseType.IsAttribute) {
2793 Report.Error (1689, a.Location, "Attribute `System.Diagnostics.ConditionalAttribute' is only valid on methods or attribute classes");
2797 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
2798 a.Error_MissingGuidAttribute ();
2802 if (a.Type == pa.Extension) {
2803 a.Error_MisusedExtensionAttribute ();
2807 if (a.Type.IsConditionallyExcluded (this))
2810 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
2813 public override AttributeTargets AttributeTargets {
2815 return AttributeTargets.Class;
2819 protected override bool DoDefineMembers ()
2821 if ((ModFlags & Modifiers.ABSTRACT) == Modifiers.ABSTRACT && (ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) != 0) {
2822 Report.Error (418, Location, "`{0}': an abstract class cannot be sealed or static", GetSignatureForError ());
2825 if ((ModFlags & (Modifiers.SEALED | Modifiers.STATIC)) == (Modifiers.SEALED | Modifiers.STATIC)) {
2826 Report.Error (441, Location, "`{0}': a class cannot be both static and sealed", GetSignatureForError ());
2830 if (PrimaryConstructorParameters != null) {
2831 Report.Error (-800, Location, "`{0}': Static classes cannot have primary constructor", GetSignatureForError ());
2832 PrimaryConstructorParameters = null;
2835 foreach (var m in Members) {
2836 if (m is Operator) {
2837 Report.Error (715, m.Location, "`{0}': Static classes cannot contain user-defined operators", m.GetSignatureForError ());
2841 if (m is Destructor) {
2842 Report.Error (711, m.Location, "`{0}': Static classes cannot contain destructor", GetSignatureForError ());
2847 Report.Error (720, m.Location, "`{0}': cannot declare indexers in a static class", m.GetSignatureForError ());
2851 if ((m.ModFlags & Modifiers.STATIC) != 0 || m is TypeContainer)
2854 if (m is Constructor) {
2855 Report.Error (710, m.Location, "`{0}': Static classes cannot have instance constructors", GetSignatureForError ());
2859 Report.Error (708, m.Location, "`{0}': cannot declare instance members in a static class", m.GetSignatureForError ());
2862 if (!PartialContainer.HasInstanceConstructor || PrimaryConstructorParameters != null)
2863 generated_primary_constructor = DefineDefaultConstructor (false);
2866 return base.DoDefineMembers ();
2869 public override void Emit ()
2873 if ((ModFlags & Modifiers.METHOD_EXTENSION) != 0)
2874 Module.PredefinedAttributes.Extension.EmitAttribute (TypeBuilder);
2876 if (base_type != null && base_type.HasDynamicElement) {
2877 Module.PredefinedAttributes.Dynamic.EmitAttribute (TypeBuilder, base_type, Location);
2881 public override void GetCompletionStartingWith (string prefix, List<string> results)
2883 base.GetCompletionStartingWith (prefix, results);
2886 while (bt != null) {
2887 results.AddRange (MemberCache.GetCompletitionMembers (this, bt, prefix).Where (l => l.IsStatic).Select (l => l.Name));
2892 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
2894 var ifaces = base.ResolveBaseTypes (out base_class);
2896 if (base_class == null) {
2897 if (spec.BuiltinType != BuiltinTypeSpec.Type.Object)
2898 base_type = Compiler.BuiltinTypes.Object;
2900 if (base_type.IsGenericParameter){
2901 Report.Error (689, base_class.Location, "`{0}': Cannot derive from type parameter `{1}'",
2902 GetSignatureForError (), base_type.GetSignatureForError ());
2903 } else if (base_type.IsStatic) {
2904 Report.SymbolRelatedToPreviousError (base_type);
2905 Report.Error (709, Location, "`{0}': Cannot derive from static class `{1}'",
2906 GetSignatureForError (), base_type.GetSignatureForError ());
2907 } else if (base_type.IsSealed) {
2908 Report.SymbolRelatedToPreviousError (base_type);
2909 Report.Error (509, Location, "`{0}': cannot derive from sealed type `{1}'",
2910 GetSignatureForError (), base_type.GetSignatureForError ());
2911 } else if (PartialContainer.IsStatic && base_type.BuiltinType != BuiltinTypeSpec.Type.Object) {
2912 Report.Error (713, Location, "Static class `{0}' cannot derive from type `{1}'. Static classes must derive from object",
2913 GetSignatureForError (), base_type.GetSignatureForError ());
2916 switch (base_type.BuiltinType) {
2917 case BuiltinTypeSpec.Type.Enum:
2918 case BuiltinTypeSpec.Type.ValueType:
2919 case BuiltinTypeSpec.Type.MulticastDelegate:
2920 case BuiltinTypeSpec.Type.Delegate:
2921 case BuiltinTypeSpec.Type.Array:
2922 if (!(spec is BuiltinTypeSpec)) {
2923 Report.Error (644, Location, "`{0}' cannot derive from special class `{1}'",
2924 GetSignatureForError (), base_type.GetSignatureForError ());
2926 base_type = Compiler.BuiltinTypes.Object;
2931 if (!IsAccessibleAs (base_type)) {
2932 Report.SymbolRelatedToPreviousError (base_type);
2933 Report.Error (60, Location, "Inconsistent accessibility: base class `{0}' is less accessible than class `{1}'",
2934 base_type.GetSignatureForError (), GetSignatureForError ());
2938 if (PartialContainer.IsStatic && ifaces != null) {
2939 foreach (var t in ifaces)
2940 Report.SymbolRelatedToPreviousError (t);
2941 Report.Error (714, Location, "Static class `{0}' cannot implement interfaces", GetSignatureForError ());
2947 /// Search for at least one defined condition in ConditionalAttribute of attribute class
2948 /// Valid only for attribute classes.
2949 public override string[] ConditionalConditions ()
2951 if ((caching_flags & (Flags.Excluded_Undetected | Flags.Excluded)) == 0)
2954 caching_flags &= ~Flags.Excluded_Undetected;
2956 if (OptAttributes == null)
2959 Attribute[] attrs = OptAttributes.SearchMulti (Module.PredefinedAttributes.Conditional);
2963 string[] conditions = new string[attrs.Length];
2964 for (int i = 0; i < conditions.Length; ++i)
2965 conditions[i] = attrs[i].GetConditionalAttributeValue ();
2967 caching_flags |= Flags.Excluded;
2972 public sealed class Struct : ClassOrStruct
2974 bool is_unmanaged, has_unmanaged_check_done;
2978 // Modifiers allowed in a struct declaration
2980 const Modifiers AllowedModifiers =
2983 Modifiers.PROTECTED |
2984 Modifiers.INTERNAL |
2988 public Struct (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
2989 : base (parent, name, attrs, MemberKind.Struct)
2991 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
2992 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, Location, Report) | Modifiers.SEALED ;
2993 spec = new TypeSpec (Kind, null, this, null, ModFlags);
2996 public override AttributeTargets AttributeTargets {
2998 return AttributeTargets.Struct;
3002 public override void Accept (StructuralVisitor visitor)
3004 visitor.Visit (this);
3007 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3009 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3012 // When struct constains fixed fixed and struct layout has explicitly
3013 // set CharSet, its value has to be propagated to compiler generated
3016 if (a.Type == pa.StructLayout) {
3017 var value = a.GetNamedValue ("CharSet");
3021 for (int i = 0; i < Members.Count; ++i) {
3022 FixedField ff = Members [i] as FixedField;
3026 ff.CharSetValue = (CharSet) System.Enum.Parse (typeof (CharSet), value.GetValue ().ToString ());
3031 bool CheckStructCycles ()
3037 foreach (var member in Members) {
3038 var field = member as Field;
3042 TypeSpec ftype = field.Spec.MemberType;
3043 if (!ftype.IsStruct)
3046 if (ftype is BuiltinTypeSpec)
3049 foreach (var targ in ftype.TypeArguments) {
3050 if (!CheckFieldTypeCycle (targ)) {
3051 Report.Error (523, field.Location,
3052 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3053 field.GetSignatureForError (), ftype.GetSignatureForError ());
3059 // Static fields of exactly same type are allowed
3061 if (field.IsStatic && ftype == CurrentType)
3064 if (!CheckFieldTypeCycle (ftype)) {
3065 Report.Error (523, field.Location,
3066 "Struct member `{0}' of type `{1}' causes a cycle in the struct layout",
3067 field.GetSignatureForError (), ftype.GetSignatureForError ());
3076 static bool CheckFieldTypeCycle (TypeSpec ts)
3078 var fts = ts.MemberDefinition as Struct;
3082 return fts.CheckStructCycles ();
3085 protected override bool DoDefineMembers ()
3087 var res = base.DoDefineMembers ();
3089 if (PrimaryConstructorParameters != null || (initialized_fields != null && !HasUserDefaultConstructor ())) {
3090 generated_primary_constructor = DefineDefaultConstructor (false);
3091 generated_primary_constructor.Define ();
3097 public override void Emit ()
3099 CheckStructCycles ();
3104 bool HasUserDefaultConstructor ()
3106 foreach (var m in PartialContainer.Members) {
3107 var c = m as Constructor;
3111 if (!c.IsStatic && c.ParameterInfo.IsEmpty)
3118 public override bool IsUnmanagedType ()
3120 if (has_unmanaged_check_done)
3121 return is_unmanaged;
3123 if (requires_delayed_unmanagedtype_check)
3126 var parent_def = Parent.PartialContainer;
3127 if (parent_def != null && parent_def.IsGenericOrParentIsGeneric) {
3128 has_unmanaged_check_done = true;
3132 if (first_nonstatic_field != null) {
3133 requires_delayed_unmanagedtype_check = true;
3135 foreach (var member in Members) {
3136 var f = member as Field;
3143 // It can happen when recursive unmanaged types are defined
3144 // struct S { S* s; }
3145 TypeSpec mt = f.MemberType;
3153 has_unmanaged_check_done = true;
3157 has_unmanaged_check_done = true;
3160 is_unmanaged = true;
3164 protected override TypeSpec[] ResolveBaseTypes (out FullNamedExpression base_class)
3166 var ifaces = base.ResolveBaseTypes (out base_class);
3167 base_type = Compiler.BuiltinTypes.ValueType;
3175 public sealed class Interface : TypeDefinition {
3178 /// Modifiers allowed in a class declaration
3180 const Modifiers AllowedModifiers =
3183 Modifiers.PROTECTED |
3184 Modifiers.INTERNAL |
3188 public Interface (TypeContainer parent, MemberName name, Modifiers mod, Attributes attrs)
3189 : base (parent, name, attrs, MemberKind.Interface)
3191 var accmods = IsTopLevel ? Modifiers.INTERNAL : Modifiers.PRIVATE;
3193 this.ModFlags = ModifiersExtensions.Check (AllowedModifiers, mod, accmods, name.Location, Report);
3194 spec = new TypeSpec (Kind, null, this, null, ModFlags);
3199 public override AttributeTargets AttributeTargets {
3201 return AttributeTargets.Interface;
3205 protected override TypeAttributes TypeAttr {
3207 const TypeAttributes DefaultTypeAttributes =
3208 TypeAttributes.AutoLayout |
3209 TypeAttributes.Abstract |
3210 TypeAttributes.Interface;
3212 return base.TypeAttr | DefaultTypeAttributes;
3218 public override void Accept (StructuralVisitor visitor)
3220 visitor.Visit (this);
3223 public override void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa)
3225 if (a.Type == pa.ComImport && !attributes.Contains (pa.Guid)) {
3226 a.Error_MissingGuidAttribute ();
3230 base.ApplyAttributeBuilder (a, ctor, cdata, pa);
3233 protected override bool VerifyClsCompliance ()
3235 if (!base.VerifyClsCompliance ())
3238 if (iface_exprs != null) {
3239 foreach (var iface in iface_exprs) {
3240 if (iface.IsCLSCompliant ())
3243 Report.SymbolRelatedToPreviousError (iface);
3244 Report.Warning (3027, 1, Location, "`{0}' is not CLS-compliant because base interface `{1}' is not CLS-compliant",
3245 GetSignatureForError (), iface.GetSignatureForError ());
3253 public abstract class InterfaceMemberBase : MemberBase
3256 // Common modifiers allowed in a class declaration
3258 protected const Modifiers AllowedModifiersClass =
3261 Modifiers.PROTECTED |
3262 Modifiers.INTERNAL |
3267 Modifiers.OVERRIDE |
3268 Modifiers.ABSTRACT |
3273 // Common modifiers allowed in a struct declaration
3275 protected const Modifiers AllowedModifiersStruct =
3278 Modifiers.PROTECTED |
3279 Modifiers.INTERNAL |
3282 Modifiers.OVERRIDE |
3287 // Common modifiers allowed in a interface declaration
3289 protected const Modifiers AllowedModifiersInterface =
3294 // Whether this is an interface member.
3296 public bool IsInterface;
3299 // If true, this is an explicit interface implementation
3301 public readonly bool IsExplicitImpl;
3303 protected bool is_external_implementation;
3306 // The interface type we are explicitly implementing
3308 public TypeSpec InterfaceType;
3311 // The method we're overriding if this is an override method.
3313 protected MethodSpec base_method;
3315 readonly Modifiers explicit_mod_flags;
3316 public MethodAttributes flags;
3318 protected InterfaceMemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, MemberName name, Attributes attrs)
3319 : base (parent, type, mod, allowed_mod, Modifiers.PRIVATE, name, attrs)
3321 IsInterface = parent.Kind == MemberKind.Interface;
3322 IsExplicitImpl = (MemberName.ExplicitInterface != null);
3323 explicit_mod_flags = mod;
3326 public abstract Variance ExpectedMemberTypeVariance { get; }
3328 protected override bool CheckBase ()
3330 if (!base.CheckBase ())
3333 if ((caching_flags & Flags.MethodOverloadsExist) != 0)
3334 CheckForDuplications ();
3339 // For System.Object only
3340 if (Parent.BaseType == null)
3343 MemberSpec candidate;
3344 bool overrides = false;
3345 var base_member = FindBaseMember (out candidate, ref overrides);
3347 if ((ModFlags & Modifiers.OVERRIDE) != 0) {
3348 if (base_member == null) {
3349 if (candidate == null) {
3350 if (this is Method && ((Method)this).ParameterInfo.IsEmpty && MemberName.Name == Destructor.MetadataName && MemberName.Arity == 0) {
3351 Report.Error (249, Location, "Do not override `{0}'. Use destructor syntax instead",
3352 "object.Finalize()");
3354 Report.Error (115, Location, "`{0}' is marked as an override but no suitable {1} found to override",
3355 GetSignatureForError (), SimpleName.GetMemberType (this));
3358 Report.SymbolRelatedToPreviousError (candidate);
3360 Report.Error (72, Location, "`{0}': cannot override because `{1}' is not an event",
3361 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3362 else if (this is PropertyBase)
3363 Report.Error (544, Location, "`{0}': cannot override because `{1}' is not a property",
3364 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3366 Report.Error (505, Location, "`{0}': cannot override because `{1}' is not a method",
3367 GetSignatureForError (), TypeManager.GetFullNameSignature (candidate));
3374 // Handles ambiguous overrides
3376 if (candidate != null) {
3377 Report.SymbolRelatedToPreviousError (candidate);
3378 Report.SymbolRelatedToPreviousError (base_member);
3380 // Get member definition for error reporting
3381 var m1 = MemberCache.GetMember (base_member.DeclaringType.GetDefinition (), base_member);
3382 var m2 = MemberCache.GetMember (candidate.DeclaringType.GetDefinition (), candidate);
3384 Report.Error (462, Location,
3385 "`{0}' cannot override inherited members `{1}' and `{2}' because they have the same signature when used in type `{3}'",
3386 GetSignatureForError (), m1.GetSignatureForError (), m2.GetSignatureForError (), Parent.GetSignatureForError ());
3389 if (!CheckOverrideAgainstBase (base_member))
3392 ObsoleteAttribute oa = base_member.GetAttributeObsolete ();
3394 if (OptAttributes == null || !OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3395 Report.SymbolRelatedToPreviousError (base_member);
3396 Report.Warning (672, 1, Location, "Member `{0}' overrides obsolete member `{1}'. Add the Obsolete attribute to `{0}'",
3397 GetSignatureForError (), base_member.GetSignatureForError ());
3400 if (OptAttributes != null && OptAttributes.Contains (Module.PredefinedAttributes.Obsolete)) {
3401 Report.SymbolRelatedToPreviousError (base_member);
3402 Report.Warning (809, 1, Location, "Obsolete member `{0}' overrides non-obsolete member `{1}'",
3403 GetSignatureForError (), base_member.GetSignatureForError ());
3407 base_method = base_member as MethodSpec;
3411 if (base_member == null && candidate != null && (!(candidate is IParametersMember) || !(this is IParametersMember)))
3412 base_member = candidate;
3414 if (base_member == null) {
3415 if ((ModFlags & Modifiers.NEW) != 0) {
3416 if (base_member == null) {
3417 Report.Warning (109, 4, Location, "The member `{0}' does not hide an inherited member. The new keyword is not required",
3418 GetSignatureForError ());
3422 if ((ModFlags & Modifiers.NEW) == 0) {
3423 ModFlags |= Modifiers.NEW;
3424 if (!IsCompilerGenerated) {
3425 Report.SymbolRelatedToPreviousError (base_member);
3426 if (!IsInterface && (base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) != 0) {
3427 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",
3428 GetSignatureForError (), base_member.GetSignatureForError ());
3430 Report.Warning (108, 2, Location, "`{0}' hides inherited member `{1}'. Use the new keyword if hiding was intended",
3431 GetSignatureForError (), base_member.GetSignatureForError ());
3436 if (!IsInterface && base_member.IsAbstract && !overrides && !IsStatic) {
3437 Report.SymbolRelatedToPreviousError (base_member);
3438 Report.Error (533, Location, "`{0}' hides inherited abstract member `{1}'",
3439 GetSignatureForError (), base_member.GetSignatureForError ());
3446 protected virtual bool CheckForDuplications ()
3448 return Parent.MemberCache.CheckExistingMembersOverloads (this, ParametersCompiled.EmptyReadOnlyParameters);
3452 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
3453 // that have been defined.
3455 protected virtual bool CheckOverrideAgainstBase (MemberSpec base_member)
3459 if ((base_member.Modifiers & (Modifiers.ABSTRACT | Modifiers.VIRTUAL | Modifiers.OVERRIDE)) == 0) {
3460 Report.SymbolRelatedToPreviousError (base_member);
3461 Report.Error (506, Location,
3462 "`{0}': cannot override inherited member `{1}' because it is not marked virtual, abstract or override",
3463 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3467 // Now we check that the overriden method is not final
3468 if ((base_member.Modifiers & Modifiers.SEALED) != 0) {
3469 Report.SymbolRelatedToPreviousError (base_member);
3470 Report.Error (239, Location, "`{0}': cannot override inherited member `{1}' because it is sealed",
3471 GetSignatureForError (), TypeManager.CSharpSignature (base_member));
3475 var base_member_type = ((IInterfaceMemberSpec) base_member).MemberType;
3476 if (!TypeSpecComparer.Override.IsEqual (MemberType, base_member_type)) {
3477 Report.SymbolRelatedToPreviousError (base_member);
3478 if (this is PropertyBasedMember) {
3479 Report.Error (1715, Location, "`{0}': type must be `{1}' to match overridden member `{2}'",
3480 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3482 Report.Error (508, Location, "`{0}': return type must be `{1}' to match overridden member `{2}'",
3483 GetSignatureForError (), base_member_type.GetSignatureForError (), base_member.GetSignatureForError ());
3491 protected static bool CheckAccessModifiers (MemberCore this_member, MemberSpec base_member)
3493 var thisp = this_member.ModFlags & Modifiers.AccessibilityMask;
3494 var base_classp = base_member.Modifiers & Modifiers.AccessibilityMask;
3496 if ((base_classp & (Modifiers.PROTECTED | Modifiers.INTERNAL)) == (Modifiers.PROTECTED | Modifiers.INTERNAL)) {
3498 // It must be at least "protected"
3500 if ((thisp & Modifiers.PROTECTED) == 0) {
3505 // when overriding protected internal, the method can be declared
3506 // protected internal only within the same assembly or assembly
3507 // which has InternalsVisibleTo
3509 if ((thisp & Modifiers.INTERNAL) != 0) {
3510 return base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly);
3514 // protected overriding protected internal inside same assembly
3515 // requires internal modifier as well
3517 if (base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (this_member.Module.DeclaringAssembly)) {
3524 return thisp == base_classp;
3527 public override bool Define ()
3530 ModFlags = Modifiers.PUBLIC | Modifiers.ABSTRACT |
3531 Modifiers.VIRTUAL | (ModFlags & (Modifiers.UNSAFE | Modifiers.NEW));
3533 flags = MethodAttributes.Public |
3534 MethodAttributes.Abstract |
3535 MethodAttributes.HideBySig |
3536 MethodAttributes.NewSlot |
3537 MethodAttributes.Virtual;
3539 Parent.PartialContainer.MethodModifiersValid (this);
3541 flags = ModifiersExtensions.MethodAttr (ModFlags);
3544 if (IsExplicitImpl) {
3545 InterfaceType = MemberName.ExplicitInterface.ResolveAsType (Parent);
3546 if (InterfaceType == null)
3549 if ((ModFlags & Modifiers.PARTIAL) != 0) {
3550 Report.Error (754, Location, "A partial method `{0}' cannot explicitly implement an interface",
3551 GetSignatureForError ());
3554 if (!InterfaceType.IsInterface) {
3555 Report.SymbolRelatedToPreviousError (InterfaceType);
3556 Report.Error (538, Location, "The type `{0}' in explicit interface declaration is not an interface",
3557 InterfaceType.GetSignatureForError ());
3559 Parent.PartialContainer.VerifyImplements (this);
3562 Modifiers allowed_explicit = Modifiers.AllowedExplicitImplFlags;
3564 allowed_explicit |= Modifiers.ASYNC;
3566 ModifiersExtensions.Check (allowed_explicit, explicit_mod_flags, 0, Location, Report);
3569 return base.Define ();
3572 protected bool DefineParameters (ParametersCompiled parameters)
3574 if (!parameters.Resolve (this))
3578 for (int i = 0; i < parameters.Count; ++i) {
3579 Parameter p = parameters [i];
3581 if (p.HasDefaultValue && (IsExplicitImpl || this is Operator || (this is Indexer && parameters.Count == 1)))
3582 p.Warning_UselessOptionalParameter (Report);
3584 if (p.CheckAccessibility (this))
3587 TypeSpec t = parameters.Types [i];
3588 Report.SymbolRelatedToPreviousError (t);
3589 if (this is Indexer)
3590 Report.Error (55, Location,
3591 "Inconsistent accessibility: parameter type `{0}' is less accessible than indexer `{1}'",
3592 t.GetSignatureForError (), GetSignatureForError ());
3593 else if (this is Operator)
3594 Report.Error (57, Location,
3595 "Inconsistent accessibility: parameter type `{0}' is less accessible than operator `{1}'",
3596 t.GetSignatureForError (), GetSignatureForError ());
3598 Report.Error (51, Location,
3599 "Inconsistent accessibility: parameter type `{0}' is less accessible than method `{1}'",
3600 t.GetSignatureForError (), GetSignatureForError ());
3606 protected override void DoMemberTypeDependentChecks ()
3608 base.DoMemberTypeDependentChecks ();
3610 VarianceDecl.CheckTypeVariance (MemberType, ExpectedMemberTypeVariance, this);
3613 public override void Emit()
3615 // for extern static method must be specified either DllImport attribute or MethodImplAttribute.
3616 // We are more strict than csc and report this as an error because SRE does not allow emit that
3617 if ((ModFlags & Modifiers.EXTERN) != 0 && !is_external_implementation && (OptAttributes == null || !OptAttributes.HasResolveError ())) {
3618 if (this is Constructor) {
3619 Report.Warning (824, 1, Location,
3620 "Constructor `{0}' is marked `external' but has no external implementation specified", GetSignatureForError ());
3622 Report.Warning (626, 1, Location,
3623 "`{0}' is marked as an external but has no DllImport attribute. Consider adding a DllImport attribute to specify the external implementation",
3624 GetSignatureForError ());
3631 public override bool EnableOverloadChecks (MemberCore overload)
3634 // Two members can differ in their explicit interface
3635 // type parameter only
3637 InterfaceMemberBase imb = overload as InterfaceMemberBase;
3638 if (imb != null && imb.IsExplicitImpl) {
3639 if (IsExplicitImpl) {
3640 caching_flags |= Flags.MethodOverloadsExist;
3645 return IsExplicitImpl;
3648 protected void Error_CannotChangeAccessModifiers (MemberCore member, MemberSpec base_member)
3650 var base_modifiers = base_member.Modifiers;
3652 // Remove internal modifier from types which are not internally accessible
3653 if ((base_modifiers & Modifiers.AccessibilityMask) == (Modifiers.PROTECTED | Modifiers.INTERNAL) &&
3654 !base_member.DeclaringType.MemberDefinition.IsInternalAsPublic (member.Module.DeclaringAssembly))
3655 base_modifiers = Modifiers.PROTECTED;
3657 Report.SymbolRelatedToPreviousError (base_member);
3658 Report.Error (507, member.Location,
3659 "`{0}': cannot change access modifiers when overriding `{1}' inherited member `{2}'",
3660 member.GetSignatureForError (),
3661 ModifiersExtensions.AccessibilityName (base_modifiers),
3662 base_member.GetSignatureForError ());
3665 protected void Error_StaticReturnType ()
3667 Report.Error (722, Location,
3668 "`{0}': static types cannot be used as return types",
3669 MemberType.GetSignatureForError ());
3673 /// Gets base method and its return type
3675 protected virtual MemberSpec FindBaseMember (out MemberSpec bestCandidate, ref bool overrides)
3677 return MemberCache.FindBaseMember (this, out bestCandidate, ref overrides);
3681 // The "short" name of this property / indexer / event. This is the
3682 // name without the explicit interface.
3684 public string ShortName {
3685 get { return MemberName.Name; }
3689 // Returns full metadata method name
3691 public string GetFullName (MemberName name)
3693 return GetFullName (name.Name);
3696 public string GetFullName (string name)
3698 if (!IsExplicitImpl)
3702 // When dealing with explicit members a full interface type
3703 // name is added to member name to avoid possible name conflicts
3705 // We use CSharpName which gets us full name with benefit of
3706 // replacing predefined names which saves some space and name
3709 return InterfaceType.GetSignatureForError () + "." + name;
3712 public override string GetSignatureForDocumentation ()
3715 return Parent.GetSignatureForDocumentation () + "." + InterfaceType.GetSignatureForDocumentation (true) + "#" + ShortName;
3717 return Parent.GetSignatureForDocumentation () + "." + ShortName;
3720 public override bool IsUsed
3722 get { return IsExplicitImpl || base.IsUsed; }
3725 public override void SetConstraints (List<Constraints> constraints_list)
3727 if (((ModFlags & Modifiers.OVERRIDE) != 0 || IsExplicitImpl)) {
3728 Report.Error (460, Location,
3729 "`{0}': Cannot specify constraints for overrides and explicit interface implementation methods",
3730 GetSignatureForError ());
3733 base.SetConstraints (constraints_list);
3737 public abstract class MemberBase : MemberCore
3739 protected FullNamedExpression type_expr;
3740 protected TypeSpec member_type;
3741 public new TypeDefinition Parent;
3743 protected MemberBase (TypeDefinition parent, FullNamedExpression type, Modifiers mod, Modifiers allowed_mod, Modifiers def_mod, MemberName name, Attributes attrs)
3744 : base (parent, name, attrs)
3746 this.Parent = parent;
3747 this.type_expr = type;
3749 if (name != MemberName.Null)
3750 ModFlags = ModifiersExtensions.Check (allowed_mod, mod, def_mod, Location, Report);
3755 public TypeSpec MemberType {
3761 public FullNamedExpression TypeExpression {
3770 // Main member define entry
3772 public override bool Define ()
3774 DoMemberTypeIndependentChecks ();
3777 // Returns false only when type resolution failed
3779 if (!ResolveMemberType ())
3782 DoMemberTypeDependentChecks ();
3787 // Any type_name independent checks
3789 protected virtual void DoMemberTypeIndependentChecks ()
3791 if ((Parent.ModFlags & Modifiers.SEALED) != 0 &&
3792 (ModFlags & (Modifiers.VIRTUAL | Modifiers.ABSTRACT)) != 0) {
3793 Report.Error (549, Location, "New virtual member `{0}' is declared in a sealed class `{1}'",
3794 GetSignatureForError (), Parent.GetSignatureForError ());
3799 // Any type_name dependent checks
3801 protected virtual void DoMemberTypeDependentChecks ()
3803 // verify accessibility
3804 if (!IsAccessibleAs (MemberType)) {
3805 Report.SymbolRelatedToPreviousError (MemberType);
3806 if (this is Property)
3807 Report.Error (53, Location,
3808 "Inconsistent accessibility: property type `" +
3809 MemberType.GetSignatureForError () + "' is less " +
3810 "accessible than property `" + GetSignatureForError () + "'");
3811 else if (this is Indexer)
3812 Report.Error (54, Location,
3813 "Inconsistent accessibility: indexer return type `" +
3814 MemberType.GetSignatureForError () + "' is less " +
3815 "accessible than indexer `" + GetSignatureForError () + "'");
3816 else if (this is MethodCore) {
3817 if (this is Operator)
3818 Report.Error (56, Location,
3819 "Inconsistent accessibility: return type `" +
3820 MemberType.GetSignatureForError () + "' is less " +
3821 "accessible than operator `" + GetSignatureForError () + "'");
3823 Report.Error (50, Location,
3824 "Inconsistent accessibility: return type `" +
3825 MemberType.GetSignatureForError () + "' is less " +
3826 "accessible than method `" + GetSignatureForError () + "'");
3827 } else if (this is Event) {
3828 Report.Error (7025, Location,
3829 "Inconsistent accessibility: event type `{0}' is less accessible than event `{1}'",
3830 MemberType.GetSignatureForError (), GetSignatureForError ());
3832 Report.Error (52, Location,
3833 "Inconsistent accessibility: field type `" +
3834 MemberType.GetSignatureForError () + "' is less " +
3835 "accessible than field `" + GetSignatureForError () + "'");
3840 protected void IsTypePermitted ()
3842 if (MemberType.IsSpecialRuntimeType) {
3843 if (Parent is StateMachine) {
3844 Report.Error (4012, Location,
3845 "Parameters or local variables of type `{0}' cannot be declared in async methods or iterators",
3846 MemberType.GetSignatureForError ());
3847 } else if (Parent is HoistedStoreyClass) {
3848 Report.Error (4013, Location,
3849 "Local variables of type `{0}' cannot be used inside anonymous methods, lambda expressions or query expressions",
3850 MemberType.GetSignatureForError ());
3852 Report.Error (610, Location,
3853 "Field or property cannot be of type `{0}'", MemberType.GetSignatureForError ());
3858 protected virtual bool CheckBase ()
3860 CheckProtectedModifier ();
3865 public override string GetSignatureForDocumentation ()
3867 return Parent.GetSignatureForDocumentation () + "." + MemberName.Basename;
3870 protected virtual bool ResolveMemberType ()
3872 if (member_type != null)
3873 throw new InternalErrorException ("Multi-resolve");
3875 member_type = type_expr.ResolveAsType (this);
3876 return member_type != null;