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 mb.ReflectedType.Name + "' because it is not " +
77 "virtual, abstract or override");
82 if (mb.IsVirtual || mb.IsAbstract){
83 if ((ModFlags & (Modifiers.NEW | Modifiers.OVERRIDE)) == 0){
85 114, Location, parent.MakeName (Name) +
86 " hides inherited member " + MethodBaseName (mb) +
87 ". To make the current member override that " +
88 "implementation, add the override keyword, " +
89 "otherwise use the new keyword");
96 public abstract bool Define (TypeContainer parent);
99 // Whehter is it ok to use an unsafe pointer in this type container
101 public bool UnsafeOK (DeclSpace parent)
104 // First check if this MemberCore modifier flags has unsafe set
106 if ((ModFlags & Modifiers.UNSAFE) != 0)
109 if (parent.UnsafeContext)
112 Expression.UnsafeError (Location);
118 // FIXME: This is temporary outside DeclSpace, because I have to fix a bug
119 // in MCS that makes it fail the lookup for the enum
123 /// The result value from adding an declaration into
124 /// a struct or a class
126 public enum AdditionResult {
128 /// The declaration has been successfully
129 /// added to the declation space.
134 /// The symbol has already been defined.
139 /// Returned if the declation being added to the
140 /// name space clashes with its container name.
142 /// The only exceptions for this are constructors
143 /// and static constructors
148 /// Returned if a constructor was created (because syntactically
149 /// it looked like a constructor) but was not (because the name
150 /// of the method is not the same as the container class
155 /// This is only used by static constructors to emit the
156 /// error 111, but this error for other things really
157 /// happens at another level for other functions.
163 /// Base class for structs, classes, enumerations and interfaces.
166 /// They all create new declaration spaces. This
167 /// provides the common foundation for managing those name
170 public abstract class DeclSpace : MemberCore {
172 /// this points to the actual definition that is being
173 /// created with System.Reflection.Emit
175 TypeBuilder definition;
176 public bool Created = false;
179 // This is the namespace in which this typecontainer
180 // was declared. We use this to resolve names.
182 public Namespace Namespace;
184 public string Basename;
187 /// defined_names is used for toplevel objects
189 protected Hashtable defined_names;
191 TypeContainer parent;
193 public DeclSpace (TypeContainer parent, string name, Location l)
196 Basename = name.Substring (1 + name.LastIndexOf ('.'));
197 defined_names = new Hashtable ();
198 this.parent = parent;
202 /// Returns a status code based purely on the name
203 /// of the member being added
205 protected AdditionResult IsValid (string name)
207 if (name == Basename)
208 return AdditionResult.EnclosingClash;
210 if (defined_names.Contains (name))
211 return AdditionResult.NameExists;
213 return AdditionResult.Success;
217 /// Introduce @name into this declaration space and
218 /// associates it with the object @o. Note that for
219 /// methods this will just point to the first method. o
221 protected void DefineName (string name, object o)
223 defined_names.Add (name, o);
226 bool in_transit = false;
229 /// This function is used to catch recursive definitions
232 public bool InTransit {
242 public TypeBuilder TypeBuilder {
252 public TypeContainer Parent {
258 public virtual void CloseType ()
262 definition.CreateType ();
265 // The try/catch is needed because
266 // nested enumerations fail to load when they
269 // Even if this is the right order (enumerations
270 // declared after types).
272 // Note that this still creates the type and
273 // it is possible to save it
280 // Whether this is an `unsafe context'
282 public bool UnsafeContext {
284 if ((ModFlags & Modifiers.UNSAFE) != 0)
287 return parent.UnsafeContext;