2 // decl.cs: Declaration base class for structs, classes, enums and interfaces.
4 // Author: Miguel de Icaza (miguel@gnu.org)
6 // Licensed under the terms of the GNU GPL
8 // (C) 2001 Ximian, Inc (http://www.ximian.com)
10 // TODO: Move the method verification stuff from the class.cs and interface.cs here
14 using System.Collections;
15 using System.Reflection.Emit;
16 using System.Reflection;
18 namespace Mono.CSharp {
21 /// Base representation for members. This is only used to keep track
22 /// of Name, Location and Modifier flags.
24 public abstract class MemberCore {
31 /// Modifier flags that the user specified in the source code
36 /// Location where this declaration happens
38 public readonly Location Location;
40 public MemberCore (string name, Location loc)
46 protected void WarningNotHiding (TypeContainer parent)
50 "The member `" + parent.Name + "." + Name + "' does not hide an " +
51 "inherited member. The keyword new is not required");
55 static string MethodBaseName (MethodBase mb)
57 return "`" + mb.ReflectedType.Name + "." + mb.Name + "'";
61 // Performs various checks on the MethodInfo `mb' regarding the modifier flags
62 // that have been defined.
64 // `name' is the user visible name for reporting errors (this is used to
65 // provide the right name regarding method names and properties)
67 protected bool CheckMethodAgainstBase (TypeContainer parent, MethodInfo mb)
71 if ((ModFlags & Modifiers.OVERRIDE) != 0){
72 if (!(mb.IsAbstract || mb.IsVirtual)){
74 506, Location, parent.MakeName (Name) +
75 ": cannot override inherited member " +
76 MethodBaseName (mb) + " because it is not " +
77 "virtual, abstract or override");
81 // Now we check that the overriden method is not final
84 Report.Error (239, Location, parent.MakeName (Name) + " : cannot " +
85 "override inherited member " + MethodBaseName (mb) +
86 " because it is sealed.");
91 if (mb.IsVirtual || mb.IsAbstract){
92 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
94 114, Location, parent.MakeName (Name) +
95 " hides inherited member " + MethodBaseName (mb) +
96 ". To make the current member override that " +
97 "implementation, add the override keyword, " +
98 "otherwise use the new keyword");
105 public abstract bool Define (TypeContainer parent);
108 // Whehter is it ok to use an unsafe pointer in this type container
110 public bool UnsafeOK (DeclSpace parent)
113 // First check if this MemberCore modifier flags has unsafe set
115 if ((ModFlags & Modifiers.UNSAFE) != 0)
118 if (parent.UnsafeContext)
121 Expression.UnsafeError (Location);
127 // FIXME: This is temporary outside DeclSpace, because I have to fix a bug
128 // in MCS that makes it fail the lookup for the enum
132 /// The result value from adding an declaration into
133 /// a struct or a class
135 public enum AdditionResult {
137 /// The declaration has been successfully
138 /// added to the declation space.
143 /// The symbol has already been defined.
148 /// Returned if the declation being added to the
149 /// name space clashes with its container name.
151 /// The only exceptions for this are constructors
152 /// and static constructors
157 /// Returned if a constructor was created (because syntactically
158 /// it looked like a constructor) but was not (because the name
159 /// of the method is not the same as the container class
164 /// This is only used by static constructors to emit the
165 /// error 111, but this error for other things really
166 /// happens at another level for other functions.
172 /// Base class for structs, classes, enumerations and interfaces.
175 /// They all create new declaration spaces. This
176 /// provides the common foundation for managing those name
179 public abstract class DeclSpace : MemberCore {
181 /// this points to the actual definition that is being
182 /// created with System.Reflection.Emit
184 TypeBuilder definition;
185 public bool Created = false;
188 // This is the namespace in which this typecontainer
189 // was declared. We use this to resolve names.
191 public Namespace Namespace;
193 public string Basename;
196 /// defined_names is used for toplevel objects
198 protected Hashtable defined_names;
200 TypeContainer parent;
202 public DeclSpace (TypeContainer parent, string name, Location l)
205 Basename = name.Substring (1 + name.LastIndexOf ('.'));
206 defined_names = new Hashtable ();
207 this.parent = parent;
211 /// Returns a status code based purely on the name
212 /// of the member being added
214 protected AdditionResult IsValid (string name)
216 if (name == Basename)
217 return AdditionResult.EnclosingClash;
219 if (defined_names.Contains (name))
220 return AdditionResult.NameExists;
222 return AdditionResult.Success;
226 /// Introduce @name into this declaration space and
227 /// associates it with the object @o. Note that for
228 /// methods this will just point to the first method. o
230 protected void DefineName (string name, object o)
232 defined_names.Add (name, o);
235 bool in_transit = false;
238 /// This function is used to catch recursive definitions
241 public bool InTransit {
251 public TypeBuilder TypeBuilder {
261 public TypeContainer Parent {
267 public virtual void CloseType ()
271 definition.CreateType ();
274 // The try/catch is needed because
275 // nested enumerations fail to load when they
278 // Even if this is the right order (enumerations
279 // declared after types).
281 // Note that this still creates the type and
282 // it is possible to save it
289 // Whether this is an `unsafe context'
291 public bool UnsafeContext {
293 if ((ModFlags & Modifiers.UNSAFE) != 0)
296 return parent.UnsafeContext;