+
//
// class.cs: Class and Struct handlers
//
-// Author: Miguel de Icaza (miguel@gnu.org)
+// Authors: Miguel de Icaza (miguel@gnu.org)
+// Martin Baulig (martin@gnome.org)
//
// Licensed under the terms of the GNU GPL
//
// (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
//
//
-
+// 2002-10-11 Miguel de Icaza <miguel@ximian.com>
+//
+// * class.cs: Following the comment from 2002-09-26 to AddMethod, I
+// have fixed a remaining problem: not every AddXXXX was adding a
+// fully qualified name.
+//
+// Now everyone registers a fully qualified name in the DeclSpace as
+// being defined instead of the partial name.
+//
+// Downsides: we are slower than we need to be due to the excess
+// copies and the names being registered this way.
+//
+// The reason for this is that we currently depend (on the corlib
+// bootstrap for instance) that types are fully qualified, because
+// we dump all the types in the namespace, and we should really have
+// types inserted into the proper namespace, so we can only store the
+// basenames in the defined_names array.
+//
+//
+#define CACHE
using System;
using System.Collections;
using System.Reflection;
/// <summary>
/// This is the base class for structs and classes.
/// </summary>
- public class TypeContainer : DeclSpace {
+ public class TypeContainer : DeclSpace, IMemberContainer {
// Holds a list of classes and structures
ArrayList types;
// The interfaces we implement.
Type [] ifaces;
+
+ // The parent member container and our member cache
+ IMemberContainer parent_container;
+ MemberCache member_cache;
//
// The indexer name for this class
public AdditionResult AddConstant (Const constant)
{
AdditionResult res;
- string name = constant.Name;
+ string basename = constant.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (constants == null)
constants = new ArrayList ();
constants.Add (constant);
- DefineName (name, constant);
+ DefineName (Name + "." + basename, constant);
return AdditionResult.Success;
}
public AdditionResult AddEnum (Mono.CSharp.Enum e)
{
AdditionResult res;
- string name = e.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (e.Basename)) != AdditionResult.Success)
return res;
if (enums == null)
enums = new ArrayList ();
enums.Add (e);
- DefineName (name, e);
+ DefineName (e.Name, e);
return AdditionResult.Success;
}
public AdditionResult AddClass (Class c)
{
AdditionResult res;
- string name = c.Name;
-
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (c.Basename)) != AdditionResult.Success)
return res;
- DefineName (name, c);
+ DefineName (c.Name, c);
types.Add (c);
return AdditionResult.Success;
public AdditionResult AddStruct (Struct s)
{
AdditionResult res;
- string name = s.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (s.Basename)) != AdditionResult.Success)
return res;
- DefineName (name, s);
+ DefineName (s.Name, s);
types.Add (s);
return AdditionResult.Success;
public AdditionResult AddDelegate (Delegate d)
{
AdditionResult res;
- string name = d.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (d.Basename)) != AdditionResult.Success)
return res;
if (delegates == null)
delegates = new ArrayList ();
- DefineName (name, d);
+ DefineName (d.Name, d);
delegates.Add (d);
return AdditionResult.Success;
public AdditionResult AddMethod (Method method)
{
- string name = method.Name;
- Object value = defined_names [name];
-
+ string basename = method.Name;
+ string fullname = Name + "." + basename;
+
+ Object value = defined_names [fullname];
+
if (value != null && (!(value is Method)))
return AdditionResult.NameExists;
+ if (basename == Basename)
+ return AdditionResult.EnclosingClash;
+
if (methods == null)
methods = new ArrayList ();
else
methods.Add (method);
- if (value != null)
- DefineName (name, method);
+ if (value == null)
+ DefineName (fullname, method);
return AdditionResult.Success;
}
public AdditionResult AddInterface (Interface iface)
{
AdditionResult res;
- string name = iface.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (iface.Basename)) != AdditionResult.Success)
return res;
if (interfaces == null)
interfaces = new ArrayList ();
interfaces.Add (iface);
- DefineName (name, iface);
+ DefineName (iface.Name, iface);
return AdditionResult.Success;
}
public AdditionResult AddField (Field field)
{
AdditionResult res;
- string name = field.Name;
+ string basename = field.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (fields == null)
fields.Add (field);
- if (field.Initializer != null){
+ if (field.HasInitializer){
if ((field.ModFlags & Modifiers.STATIC) != 0){
if (initialized_static_fields == null)
initialized_static_fields = new ArrayList ();
if ((field.ModFlags & Modifiers.STATIC) == 0)
have_nonstatic_fields = true;
- DefineName (name, field);
+ DefineName (Name + "." + basename, field);
return AdditionResult.Success;
}
public AdditionResult AddProperty (Property prop)
{
AdditionResult res;
- string name = prop.Name;
+ string basename = prop.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (properties == null)
properties.Insert (0, prop);
else
properties.Add (prop);
- DefineName (name, prop);
+ DefineName (Name + "." + basename, prop);
return AdditionResult.Success;
}
public AdditionResult AddEvent (Event e)
{
AdditionResult res;
- string name = e.Name;
+ string basename = e.Name;
- if ((res = IsValid (name)) != AdditionResult.Success)
+ if ((res = IsValid (basename)) != AdditionResult.Success)
return res;
if (events == null)
events = new ArrayList ();
events.Add (e);
- DefineName (name, e);
+ DefineName (Name + "." + basename, e);
return AdditionResult.Success;
}
if (fields == null)
return true;
-
- foreach (Field f in fields){
- Object init = f.Initializer;
- Expression e;
- if (init is Expression)
- e = (Expression) init;
- else {
- e = new ArrayCreation (f.Type, "", (ArrayList)init, f.Location);
- }
+ foreach (Field f in fields){
+ Expression e = f.GetInitializerExpression (ec);
+ if (e == null)
+ return false;
Location l = f.Location;
FieldExpr fe = new FieldExpr (f.FieldBuilder, l);
throw new Exception ("Assign.Resolve returned a non ExpressionStatement");
}
}
-
+
return true;
}
Constructor c;
int mods = 0;
- c = new Constructor (Basename, Parameters.GetEmptyReadOnlyParameters (),
- new ConstructorBaseInitializer (null, new Location (-1)),
- new Location (-1));
+ c = new Constructor (Basename, Parameters.EmptyReadOnlyParameters,
+ new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters,
+ Location.Null),
+ Location.Null);
if (is_static)
mods = Modifiers.STATIC;
start = 0;
}
+ if (!AsAccessible (parent, ModFlags))
+ Report.Error (60, Location,
+ "Inconsistent accessibility: base class `" +
+ TypeManager.CSharpName (parent) + "' is less " +
+ "accessible than class `" +
+ Name + "'");
+
} else {
start = 0;
}
return null;
}
}
-
+
ifaces [j] = t;
}
return null;
InTransit = true;
-
+
if (this is Class)
is_class = true;
else
// if (parent_builder is ModuleBuilder) {
if (IsTopLevel){
ModuleBuilder builder = CodeGen.ModuleBuilder;
+ TypeBuilder = builder.DefineType (
+ Name, type_attributes, parent, ifaces);
- //
- // Structs with no fields need to have a ".size 1"
- // appended
- //
-
- if (!is_class && !have_nonstatic_fields)
- TypeBuilder = builder.DefineType (Name,
- type_attributes,
- parent,
- PackingSize.Unspecified, 1);
- else
- //
- // classes or structs with fields
- //
- TypeBuilder = builder.DefineType (Name,
- type_attributes,
- parent,
- ifaces);
} else {
TypeBuilder builder = Parent.TypeBuilder;
+ TypeBuilder = builder.DefineNestedType (
+ Basename, type_attributes, parent, ifaces);
+ }
- //
- // Structs with no fields need to have a ".size 1"
- // appended
- //
- if (!is_class && !have_nonstatic_fields)
- TypeBuilder = builder.DefineNestedType (Basename,
- type_attributes,
- parent,
- PackingSize.Unspecified);
- else {
- //
- // classes or structs with fields
- //
- TypeBuilder = builder.DefineNestedType (Basename,
- type_attributes,
- parent,
- ifaces);
- }
+ //
+ // Structs with no fields need to have at least one byte.
+ // The right thing would be to set the PackingSize in a DefineType
+ // but there are no functions that allow interfaces *and* the size to
+ // be specified.
+ //
+
+ if (!is_class && !have_nonstatic_fields){
+ TypeBuilder.DefineField ("$PRIVATE$", TypeManager.byte_type,
+ FieldAttributes.Private);
}
// add interfaces that were not added at type creation (weird API issue)
class_indexer_name = "Item";
IndexerName = class_indexer_name;
}
-
+
+ static void Error_KeywordNotAllowed (Location loc)
+ {
+ Report.Error (1530, loc, "Keyword new not allowed for namespace elements");
+ }
+
/// <summary>
/// Populates our TypeBuilder with fields and methods
/// </summary>
- public override bool Define (TypeContainer parent)
+ public override bool DefineMembers (TypeContainer parent)
{
MemberInfo [] defined_names = null;
+ if (interface_order != null){
+ foreach (Interface iface in interface_order)
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.DefineMembers (this);
+ else
+ Error_KeywordNotAllowed (iface.Location);
+ }
+
if (RootContext.WarningLevel > 1){
Type ptype;
//
ptype = TypeBuilder.BaseType;
if (ptype != null){
- defined_names = FindMembers (
+ defined_names = (MemberInfo []) FindMembers (
ptype, MemberTypes.All & ~MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance |
BindingFlags.Static, null, null);
} else
IndexerName = "Item";
- if (operators != null)
+ if (operators != null){
DefineMembers (operators, null);
+ CheckPairedOperators ();
+ }
+
if (enums != null)
DefineMembers (enums, defined_names);
if (delegates != null)
DefineMembers (delegates, defined_names);
+#if CACHE
+ if (TypeBuilder.BaseType != null)
+ parent_container = TypeManager.LookupMemberContainer (TypeBuilder.BaseType);
+
+ member_cache = new MemberCache (this);
+#endif
+
+ return true;
+ }
+
+ public override bool Define (TypeContainer parent)
+ {
+ if (interface_order != null){
+ foreach (Interface iface in interface_order)
+ if ((iface.ModFlags & Modifiers.NEW) == 0)
+ iface.Define (this);
+ }
+
return true;
}
//
// Since the whole process is a no-op, it is fine to check for null here.
//
- public MemberInfo [] FindMembers (MemberTypes mt, BindingFlags bf,
- MemberFilter filter, object criteria)
+ public override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
ArrayList members = new ArrayList ();
- bool priv = (bf & BindingFlags.NonPublic) != 0;
+
+ int modflags = 0;
+ if ((bf & BindingFlags.Public) != 0)
+ modflags |= Modifiers.PUBLIC | Modifiers.PROTECTED |
+ Modifiers.INTERNAL;
+ if ((bf & BindingFlags.NonPublic) != 0)
+ modflags |= Modifiers.PRIVATE;
+
+ int static_mask = 0, static_flags = 0;
+ switch (bf & (BindingFlags.Static | BindingFlags.Instance)) {
+ case BindingFlags.Static:
+ static_mask = static_flags = Modifiers.STATIC;
+ break;
+
+ case BindingFlags.Instance:
+ static_mask = Modifiers.STATIC;
+ static_flags = 0;
+ break;
+
+ default:
+ static_mask = static_flags = 0;
+ break;
+ }
+
+ Timer.StartTimer (TimerType.TcFindMembers);
if (filter == null)
filter = accepting_filter;
if ((mt & MemberTypes.Field) != 0) {
if (fields != null) {
foreach (Field f in fields) {
- if ((f.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((f.ModFlags & modflags) == 0)
+ continue;
+ if ((f.ModFlags & static_mask) != static_flags)
+ continue;
FieldBuilder fb = f.FieldBuilder;
if (fb != null && filter (fb, criteria) == true)
if (constants != null) {
foreach (Const con in constants) {
- if ((con.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
-
+ if ((con.ModFlags & modflags) == 0)
+ continue;
+ if ((con.ModFlags & static_mask) != static_flags)
+ continue;
+
FieldBuilder fb = con.FieldBuilder;
if (fb != null && filter (fb, criteria) == true)
members.Add (fb);
if ((mt & MemberTypes.Method) != 0) {
if (methods != null) {
foreach (Method m in methods) {
- if ((m.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((m.ModFlags & modflags) == 0)
+ continue;
+ if ((m.ModFlags & static_mask) != static_flags)
+ continue;
MethodBuilder mb = m.MethodBuilder;
if (operators != null){
foreach (Operator o in operators) {
- if ((o.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((o.ModFlags & modflags) == 0)
+ continue;
+ if ((o.ModFlags & static_mask) != static_flags)
+ continue;
MethodBuilder ob = o.OperatorMethodBuilder;
if (ob != null && filter (ob, criteria) == true)
if (properties != null){
foreach (Property p in properties){
- if ((p.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((p.ModFlags & modflags) == 0)
+ continue;
+ if ((p.ModFlags & static_mask) != static_flags)
+ continue;
MethodBuilder b;
members.Add (b);
}
}
+
+ if (indexers != null){
+ foreach (Indexer ix in indexers){
+ if ((ix.ModFlags & modflags) == 0)
+ continue;
+ if ((ix.ModFlags & static_mask) != static_flags)
+ continue;
+
+ MethodBuilder b;
+
+ b = ix.GetBuilder;
+ if (b != null && filter (b, criteria) == true)
+ members.Add (b);
+
+ b = ix.SetBuilder;
+ if (b != null && filter (b, criteria) == true)
+ members.Add (b);
+ }
+ }
}
if ((mt & MemberTypes.Event) != 0) {
if (events != null)
foreach (Event e in events) {
- if ((e.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((e.ModFlags & modflags) == 0)
+ continue;
+ if ((e.ModFlags & static_mask) != static_flags)
+ continue;
MemberInfo eb = e.EventBuilder;
if (eb != null && filter (eb, criteria) == true)
if ((mt & MemberTypes.Property) != 0){
if (properties != null)
foreach (Property p in properties) {
- if ((p.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((p.ModFlags & modflags) == 0)
+ continue;
+ if ((p.ModFlags & static_mask) != static_flags)
+ continue;
MemberInfo pb = p.PropertyBuilder;
if (pb != null && filter (pb, criteria) == true) {
if (indexers != null)
foreach (Indexer ix in indexers) {
- if ((ix.ModFlags & Modifiers.PRIVATE) != 0)
- if (!priv)
- continue;
+ if ((ix.ModFlags & modflags) == 0)
+ continue;
+ if ((ix.ModFlags & static_mask) != static_flags)
+ continue;
MemberInfo ib = ix.PropertyBuilder;
if (ib != null && filter (ib, criteria) == true) {
if ((mt & MemberTypes.NestedType) != 0) {
if (types != null){
foreach (TypeContainer t in types) {
- TypeBuilder tb = t.TypeBuilder;
+ if ((t.ModFlags & modflags) == 0)
+ continue;
+ TypeBuilder tb = t.TypeBuilder;
if (tb != null && (filter (tb, criteria) == true))
members.Add (tb);
}
if (enums != null){
foreach (Enum en in enums){
- TypeBuilder tb = en.TypeBuilder;
+ if ((en.ModFlags & modflags) == 0)
+ continue;
+ TypeBuilder tb = en.TypeBuilder;
if (tb != null && (filter (tb, criteria) == true))
members.Add (tb);
}
if (delegates != null){
foreach (Delegate d in delegates){
+ if ((d.ModFlags & modflags) == 0)
+ continue;
+
TypeBuilder tb = d.TypeBuilder;
-
+ if (tb != null && (filter (tb, criteria) == true))
+ members.Add (tb);
+ }
+ }
+
+ if (interfaces != null){
+ foreach (Interface iface in interfaces){
+ if ((iface.ModFlags & modflags) == 0)
+ continue;
+
+ TypeBuilder tb = iface.TypeBuilder;
if (tb != null && (filter (tb, criteria) == true))
members.Add (tb);
}
}
if ((mt & MemberTypes.Constructor) != 0){
- if (instance_constructors != null){
+ if (((bf & BindingFlags.Instance) != 0) && (instance_constructors != null)){
foreach (Constructor c in instance_constructors){
ConstructorBuilder cb = c.ConstructorBuilder;
-
if (cb != null)
if (filter (cb, criteria) == true)
members.Add (cb);
}
}
- if (default_static_constructor != null){
+ if (((bf & BindingFlags.Static) != 0) && (default_static_constructor != null)){
ConstructorBuilder cb =
default_static_constructor.ConstructorBuilder;
// Lookup members in parent if requested.
//
if (((bf & BindingFlags.DeclaredOnly) == 0) && (TypeBuilder.BaseType != null)) {
- MemberInfo [] mi;
-
- mi = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
- if (mi != null)
- members.AddRange (mi);
- }
-
- int count = members.Count;
- if (count > 0){
- MemberInfo [] mi = new MemberInfo [count];
- members.CopyTo (mi);
- return mi;
+ MemberList list = FindMembers (TypeBuilder.BaseType, mt, bf, filter, criteria);
+ members.AddRange (list);
}
- return null;
+ Timer.StopTimer (TimerType.TcFindMembers);
+
+ return new MemberList (members);
}
-
+ public override MemberCache MemberCache {
+ get {
+ return member_cache;
+ }
+ }
- public static MemberInfo [] FindMembers (Type t, MemberTypes mt, BindingFlags bf,
- MemberFilter filter, object criteria)
+ public static MemberList FindMembers (Type t, MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
TypeContainer tc = TypeManager.LookupTypeContainer (t);
if (tc != null)
return tc.FindMembers (mt, bf, filter, criteria);
else
- return t.FindMembers (mt, bf, filter, criteria);
+ return new MemberList (t.FindMembers (mt, bf, filter, criteria));
}
//
if (Delegates != null)
foreach (Delegate d in Delegates)
- d.CloseDelegate ();
+ d.CloseType ();
}
public string MakeName (string n)
return ok;
}
+ // Access level of a type.
+ enum AccessLevel {
+ Public = 0,
+ ProtectedInternal = 1,
+ Internal = 2,
+ Protected = 3,
+ Private = 4
+ }
+
+ // Check whether `flags' denotes a more restricted access than `level'
+ // and return the new level.
+ static AccessLevel CheckAccessLevel (AccessLevel level, int flags)
+ {
+ AccessLevel old_level = level;
+
+ if ((flags & Modifiers.INTERNAL) != 0) {
+ if ((flags & Modifiers.PROTECTED) != 0) {
+ if ((int) level < (int) AccessLevel.ProtectedInternal)
+ level = AccessLevel.ProtectedInternal;
+ } else {
+ if ((int) level < (int) AccessLevel.Internal)
+ level = AccessLevel.Internal;
+ }
+ } else if ((flags & Modifiers.PROTECTED) != 0) {
+ if ((int) level < (int) AccessLevel.Protected)
+ level = AccessLevel.Protected;
+ } else if ((flags & Modifiers.PRIVATE) != 0)
+ level = AccessLevel.Private;
+
+ return level;
+ }
+
+ // Return the access level for a new member which is defined in the current
+ // TypeContainer with access modifiers `flags'.
+ AccessLevel GetAccessLevel (int flags)
+ {
+ if ((flags & Modifiers.PRIVATE) != 0)
+ return AccessLevel.Private;
+
+ AccessLevel level;
+ if (!IsTopLevel && (Parent != null))
+ level = Parent.GetAccessLevel (flags);
+ else
+ level = AccessLevel.Public;
+
+ return CheckAccessLevel (CheckAccessLevel (level, flags), ModFlags);
+ }
+
+ // Return the access level for type `t', but don't give more access than `flags'.
+ static AccessLevel GetAccessLevel (Type t, int flags)
+ {
+ if (((flags & Modifiers.PRIVATE) != 0) || t.IsNestedPrivate)
+ return AccessLevel.Private;
+
+ AccessLevel level;
+ if (TypeManager.IsBuiltinType (t))
+ return AccessLevel.Public;
+ else if ((t.DeclaringType != null) && (t != t.DeclaringType))
+ level = GetAccessLevel (t.DeclaringType, flags);
+ else {
+ level = CheckAccessLevel (AccessLevel.Public, flags);
+ }
+
+ if (t.IsNestedPublic)
+ return level;
+
+ if (t.IsNestedAssembly || t.IsNotPublic) {
+ if ((int) level < (int) AccessLevel.Internal)
+ level = AccessLevel.Internal;
+ }
+
+ if (t.IsNestedFamily) {
+ if ((int) level < (int) AccessLevel.Protected)
+ level = AccessLevel.Protected;
+ }
+
+ if (t.IsNestedFamORAssem) {
+ if ((int) level < (int) AccessLevel.ProtectedInternal)
+ level = AccessLevel.ProtectedInternal;
+ }
+
+ return level;
+ }
+
//
- // Returns true if `type' is as accessible as the flags `flags'
- // given for this member
+ // Returns true if `parent' is as accessible as the flags `flags'
+ // given for this member.
//
- static public bool AsAccessible (Type type, int flags)
+ public bool AsAccessible (Type parent, int flags)
{
- return true;
+ while (parent.IsArray || parent.IsPointer || parent.IsByRef)
+ parent = parent.GetElementType ();
+
+ AccessLevel level = GetAccessLevel (flags);
+ AccessLevel level2 = GetAccessLevel (parent, flags);
+
+ return (int) level >= (int) level2;
}
Hashtable builder_and_args;
{
Report.Error (539, loc, "Explicit implementation: `" + name + "' is not a member of the interface");
}
+
+ //
+ // IMemberContainer
+ //
+
+ string IMemberContainer.Name {
+ get {
+ return Name;
+ }
+ }
+
+ Type IMemberContainer.Type {
+ get {
+ return TypeBuilder;
+ }
+ }
+
+ IMemberContainer IMemberContainer.Parent {
+ get {
+ return parent_container;
+ }
+ }
+
+ MemberCache IMemberContainer.MemberCache {
+ get {
+ return member_cache;
+ }
+ }
+
+ bool IMemberContainer.IsInterface {
+ get {
+ return false;
+ }
+ }
+
+ MemberList IMemberContainer.GetMembers (MemberTypes mt, BindingFlags bf)
+ {
+ return FindMembers (mt, bf | BindingFlags.DeclaredOnly, null, null);
+ }
+
+ //
+ // Operator pair checking
+ //
+
+ class OperatorEntry {
+ public int flags;
+ public Type ret_type;
+ public Type type1, type2;
+ public Operator op;
+ public Operator.OpType ot;
+
+ public OperatorEntry (int f, Operator o)
+ {
+ flags = f;
+
+ ret_type = o.OperatorMethod.GetReturnType ();
+ Type [] pt = o.OperatorMethod.ParameterTypes;
+ type1 = pt [0];
+ type2 = pt [1];
+ op = o;
+ ot = o.OperatorType;
+ }
+
+ public override int GetHashCode ()
+ {
+ return ret_type.GetHashCode ();
+ }
+
+ public override bool Equals (object o)
+ {
+ OperatorEntry other = (OperatorEntry) o;
+
+ if (other.ret_type != ret_type)
+ return false;
+ if (other.type1 != type1)
+ return false;
+ if (other.type2 != type2)
+ return false;
+ return true;
+ }
+ }
+
+ //
+ // Checks that some operators come in pairs:
+ // == and !=
+ // > and <
+ // >= and <=
+ //
+ // They are matched based on the return type and the argument types
+ //
+ void CheckPairedOperators ()
+ {
+ Hashtable pairs = new Hashtable (null, null);
+
+ // Register all the operators we care about.
+ foreach (Operator op in operators){
+ int reg = 0;
+
+ switch (op.OperatorType){
+ case Operator.OpType.Equality:
+ reg = 1; break;
+ case Operator.OpType.Inequality:
+ reg = 2; break;
+
+ case Operator.OpType.GreaterThan:
+ reg = 1; break;
+ case Operator.OpType.LessThan:
+ reg = 2; break;
+
+ case Operator.OpType.GreaterThanOrEqual:
+ reg = 1; break;
+ case Operator.OpType.LessThanOrEqual:
+ reg = 2; break;
+ }
+ if (reg == 0)
+ continue;
+
+ OperatorEntry oe = new OperatorEntry (reg, op);
+
+ object o = pairs [oe];
+ if (o == null)
+ pairs [oe] = oe;
+ else {
+ oe = (OperatorEntry) o;
+ oe.flags |= reg;
+ }
+ }
+
+ //
+ // Look for the mistakes.
+ //
+ foreach (DictionaryEntry de in pairs){
+ OperatorEntry oe = (OperatorEntry) de.Key;
+
+ if (oe.flags == 3)
+ continue;
+
+ string s = "";
+ switch (oe.ot){
+ case Operator.OpType.Equality:
+ s = "!=";
+ break;
+ case Operator.OpType.Inequality:
+ s = "==";
+ break;
+ case Operator.OpType.GreaterThan:
+ s = "<";
+ break;
+ case Operator.OpType.LessThan:
+ s = ">";
+ break;
+ case Operator.OpType.GreaterThanOrEqual:
+ s = "<=";
+ break;
+ case Operator.OpType.LessThanOrEqual:
+ s = ">=";
+ break;
+ }
+ Report.Error (216, oe.op.Location,
+ "The operator `" + oe.op + "' requires a matching operator `" + s + "' to also be defined");
+ }
+ }
+
+
}
public class Class : TypeContainer {
}
}
- public abstract class MethodCore : MemberCore {
+ public abstract class MethodCore : MemberBase {
public readonly Parameters Parameters;
Block block;
//
// Parameters, cached for semantic analysis.
//
- InternalParameters parameter_info;
-
- public MethodCore (string name, Parameters parameters, Location l)
- : base (name, l)
+ protected InternalParameters parameter_info;
+ protected Type [] parameter_types;
+
+ public MethodCore (Expression type, int mod, int allowed_mod, string name,
+ Attributes attrs, Parameters parameters, Location loc)
+ : base (type, mod, allowed_mod, name, attrs, loc)
{
- Name = name;
Parameters = parameters;
}
//
// Returns the System.Type array for the parameters of this method
//
- Type [] parameter_types;
- public Type [] ParameterTypes (TypeContainer parent)
- {
- if (Parameters == null)
- return TypeManager.NoTypes;
-
- if (parameter_types == null)
- parameter_types = Parameters.GetParameterInfo (parent);
-
- return parameter_types;
+ public Type [] ParameterTypes {
+ get {
+ return parameter_types;
+ }
}
public InternalParameters ParameterInfo
get {
return parameter_info;
}
-
- set {
- parameter_info = value;
- }
}
public Block Block {
}
}
+ protected virtual bool DoDefineParameters (TypeContainer parent)
+ {
+ // Check if arguments were correct
+ parameter_types = Parameters.GetParameterInfo (parent);
+ if ((parameter_types == null) || !CheckParameters (parent, parameter_types))
+ return false;
+
+ parameter_info = new InternalParameters (parent, Parameters);
+
+ return true;
+ }
+
public CallingConventions GetCallingConvention (bool is_class)
{
CallingConventions cc = 0;
}
public class Method : MethodCore {
- public Expression ReturnType;
public MethodBuilder MethodBuilder;
- public readonly Attributes OptAttributes;
-
- MethodAttributes flags;
+ public MethodData MethodData;
/// <summary>
/// Modifiers allowed in a class declaration
//
public Method (Expression return_type, int mod, string name, Parameters parameters,
Attributes attrs, Location l)
- : base (name, parameters, l)
- {
- ReturnType = return_type;
- ModFlags = Modifiers.Check (AllowedModifiers, mod, Modifiers.PRIVATE, l);
- OptAttributes = attrs;
- }
+ : base (return_type, mod, AllowedModifiers, name, attrs, parameters, l)
+ { }
//
// Returns the `System.Type' for the ReturnType of this
// function. Provides a nice cache. (used between semantic analysis
// and actual code generation
//
- Type type_return_type;
-
- public Type GetReturnType (TypeContainer parent)
+ public Type GetReturnType ()
{
- if (type_return_type == null)
- type_return_type = parent.ResolveType (ReturnType, false, Location);
-
- return type_return_type;
+ return MemberType;
}
+ // Whether this is an operator method.
+ public bool IsOperator;
+
void DuplicateEntryPoint (MethodInfo b, Location location)
{
Report.Error (
return true;
else
return false;
- }
+ }
//
- // Creates the type
+ // Checks our base implementation if any
//
- public override bool Define (TypeContainer parent)
+ protected override bool CheckBase (TypeContainer parent)
{
- Type ret_type = GetReturnType (parent);
- Type [] parameters = ParameterTypes (parent);
- bool error = false;
- MethodInfo implementing = null;
- Type iface_type = null;
- string iface = "", short_name;
- bool explicit_impl = false;
-
- // Check if the return type and arguments were correct
- if (ret_type == null || parameters == null)
- return false;
-
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
+ // Check whether arguments were correct.
+ if (!DoDefineParameters (parent))
return false;
- flags = Modifiers.MethodAttr (ModFlags);
+ MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
+ if (!IsOperator) {
+ MemberList mi_this;
+
+ mi_this = TypeContainer.FindMembers (
+ parent.TypeBuilder, MemberTypes.Method,
+ BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly,
+ MethodSignature.method_signature_filter, ms);
+
+ if (mi_this.Count > 0) {
+ Report.Error (111, Location, "Class `" + parent.Name + "' " +
+ "already defines a member called `" + Name + "' " +
+ "with the same parameter types");
+ return false;
+ }
+ }
//
- // verify accessibility
+ // Verify if the parent has a type with the same name, and then
+ // check whether we have to create a new slot for it or not.
//
- if (!TypeContainer.AsAccessible (ret_type, ModFlags))
- return false;
-
- if (ret_type.IsPointer && !UnsafeOK (parent))
- return false;
-
- foreach (Type partype in parameters){
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- error = true;
- if (partype.IsPointer && !UnsafeOK (parent))
- error = true;
- }
-
- if (error)
- return false;
-
- //
- // Verify if the parent has a type with the same name, and then
- // check whether we have to create a new slot for it or not.
- //
- Type ptype = parent.TypeBuilder.BaseType;
+ Type ptype = parent.TypeBuilder.BaseType;
// ptype is only null for System.Object while compiling corlib.
if (ptype != null){
- MethodSignature ms = new MethodSignature (Name, null, parameters);
- MemberInfo [] mi, mi_static, mi_instance;
+ MemberList mi, mi_static, mi_instance;
mi_static = TypeContainer.FindMembers (
ptype, MemberTypes.Method,
MethodSignature.inheritable_method_signature_filter,
ms);
- if (mi_instance != null && mi_instance.Length > 0){
+ if (mi_instance.Count > 0){
mi = mi_instance;
- } else if (mi_static != null && mi_static.Length > 0)
+ } else if (mi_static.Count > 0)
mi = mi_static;
else
mi = null;
- if (mi != null && mi.Length > 0){
- if (!CheckMethodAgainstBase (parent, flags, (MethodInfo) mi [0])){
+ if (mi != null && mi.Count > 0){
+ parent_method = (MethodInfo) mi [0];
+ string name = parent_method.DeclaringType.Name + "." +
+ parent_method.Name;
+
+ if (!CheckMethodAgainstBase (parent, flags, parent_method, name))
return false;
+
+ if ((ModFlags & Modifiers.NEW) == 0) {
+ Type parent_ret = TypeManager.TypeToCoreType (
+ parent_method.ReturnType);
+
+ if (parent_ret != MemberType) {
+ Report.Error (
+ 508, parent.MakeName (Name) + ": cannot " +
+ "change return type when overriding " +
+ "inherited member " + name);
+ return false;
+ }
}
} else {
if ((ModFlags & Modifiers.NEW) != 0)
} else if ((ModFlags & Modifiers.NEW) != 0)
WarningNotHiding (parent);
- //
- // If we implement an interface, extract the interface name.
- //
- if (Name.IndexOf (".") != -1){
- int pos = Name.LastIndexOf (".");
- iface = Name.Substring (0, pos);
-
- iface_type = RootContext.LookupType (parent, iface, false, Location);
- short_name = Name.Substring (pos + 1);
-
- if (iface_type == null)
- return false;
-
- // Compute the full name that we need to export
- Name = iface_type.FullName + "." + short_name;
-
- if (!parent.VerifyImplements (iface_type, short_name, Name, Location))
- return false;
-
- explicit_impl = true;
- } else
- short_name = Name;
-
- //
- // Check if we are an implementation of an interface method or
- // a method
- //
- if (parent.Pending != null){
- implementing = parent.Pending.IsInterfaceMethod (
- iface_type, short_name, ret_type, parameters);
-
- if (iface_type != null && implementing == null){
- TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, short_name);
- return false;
- }
- }
-
- //
- // For implicit implementations, make sure we are public, for
- // explicit implementations, make sure we are private.
- //
- if (implementing != null){
- //
- // Setting null inside this block will trigger a more
- // verbose error reporting for missing interface implementations
- //
- // The "candidate" function has been flagged already
- // but it wont get cleared
- //
- if (iface_type == null){
- //
- // We already catch different accessibility settings
- // so we just need to check that we are not private
- //
- if ((ModFlags & Modifiers.PRIVATE) != 0)
- implementing = null;
-
- //
- // Static is not allowed
- //
- if ((ModFlags & Modifiers.STATIC) != 0)
- implementing = null;
- } else {
- if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
- Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
- implementing = null;
- }
- }
- }
-
- //
- // If implementing is still valid, set flags
- //
- if (implementing != null){
- // Console.WriteLine ("Implementing for:" + (iface_type != null ? iface_type.FullName : "<null>") + " " + short_name);
-
- if (implementing.DeclaringType.IsInterface)
- flags |= MethodAttributes.NewSlot;
-
- flags |=
- MethodAttributes.Virtual |
- MethodAttributes.HideBySig;
-
- //
- // clear the pending implementation flag
- //
- parent.Pending.ImplementMethod (
- iface_type, short_name, ret_type, parameters, explicit_impl);
- }
-
- Attribute dllimport_attr = null;
- if (OptAttributes != null && OptAttributes.AttributeSections != null) {
- foreach (AttributeSection asec in OptAttributes.AttributeSections) {
- if (asec.Attributes == null)
- continue;
-
- foreach (Attribute a in asec.Attributes)
- if (a.Name.IndexOf ("DllImport") != -1) {
- flags |= MethodAttributes.PinvokeImpl;
- dllimport_attr = a;
- }
- }
- }
+ return true;
+ }
- //
- // Finally, define the method
- //
+ //
+ // Creates the type
+ //
+ public override bool Define (TypeContainer parent)
+ {
+ if (!DoDefine (parent))
+ return false;
- if ((flags & MethodAttributes.PinvokeImpl) != 0) {
+ if (!CheckBase (parent))
+ return false;
- if ((ModFlags & Modifiers.STATIC) == 0) {
- Report.Error (601, Location, "The DllImport attribute must be specified on " +
- "a method marked 'static' and 'extern'.");
- return false;
- }
-
- EmitContext ec = new EmitContext (
- parent, Location, null, GetReturnType (parent), ModFlags);
-
- MethodBuilder = dllimport_attr.DefinePInvokeMethod (
- ec, parent.TypeBuilder,
- Name, flags, ret_type, parameters);
- } else {
- MethodBuilder = parent.TypeBuilder.DefineMethod (
- Name, flags,
- GetCallingConvention (parent is Class),
- ret_type, parameters);
+ CallingConventions cc = GetCallingConvention (parent is Class);
- if (implementing != null && explicit_impl)
- parent.TypeBuilder.DefineMethodOverride (
- MethodBuilder, implementing);
- }
+ MethodData = new MethodData (this, null, MemberType, ParameterTypes,
+ ParameterInfo, cc, OptAttributes,
+ ModFlags, flags, true);
- if (MethodBuilder == null)
+ if (!MethodData.Define (parent))
return false;
- //
- // HACK because System.Reflection.Emit is lame
- //
- ParameterInfo = new InternalParameters (parent, Parameters);
-
- if (!TypeManager.RegisterMethod (MethodBuilder, ParameterInfo,
- parameters)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name + "' already contains a definition with " +
- " the same return value and parameter types for method `" +
- Name + "'");
- return false;
- }
+ MethodBuilder = MethodData.MethodBuilder;
//
// This is used to track the Entry Point,
//
public void Emit (TypeContainer parent)
{
- ILGenerator ig;
- EmitContext ec;
-
- if ((flags & MethodAttributes.PinvokeImpl) == 0)
- ig = MethodBuilder.GetILGenerator ();
- else
- ig = null;
-
- ec = new EmitContext (parent, Location, ig, GetReturnType (parent), ModFlags);
-
- if (OptAttributes != null)
- Attribute.ApplyAttributes (ec, MethodBuilder, this, OptAttributes, Location);
-
-
- LabelParameters (ec, ParameterTypes (parent), MethodBuilder);
-
- //
- // abstract or extern methods have no bodies
- //
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
- if (Block != null){
- if ((ModFlags & Modifiers.ABSTRACT) != 0){
- Report.Error (
- 500, "Abstract method `" +
- TypeManager.CSharpSignature (MethodBuilder) +
- "' can not have a body");
- }
- }
- return;
- }
-
- //
- // Handle destructors specially
- //
- // FIXME: This code generates buggy code
- //
- if (Name == "Finalize" && type_return_type == TypeManager.void_type)
- EmitDestructor (ec);
- else {
- ISymbolWriter sw = CodeGen.SymbolWriter;
-
- if ((sw != null) && (!Location.IsNull (Location))) {
- MethodToken token = MethodBuilder.GetToken ();
- sw.OpenMethod (new SymbolToken (token.Token));
- sw.SetMethodSourceRange (Location.SymbolDocument,
- Location.Row, 0,
- Block.EndLocation.SymbolDocument,
- Block.EndLocation.Row, 0);
-
- ec.EmitTopBlock (Block, Location);
-
- sw.CloseMethod ();
- } else
- ec.EmitTopBlock (Block, Location);
- }
- }
-
- void EmitDestructor (EmitContext ec)
- {
- ILGenerator ig = ec.ig;
-
- Label finish = ig.DefineLabel ();
- bool old_in_try = ec.InTry;
-
- ig.BeginExceptionBlock ();
- ec.InTry = true;
- ec.ReturnLabel = finish;
- ec.HasReturnLabel = true;
- ec.EmitTopBlock (Block, Location);
- ec.InTry = old_in_try;
-
- // ig.MarkLabel (finish);
- bool old_in_finally = ec.InFinally;
- ec.InFinally = true;
- ig.BeginFinallyBlock ();
-
- if (ec.ContainerType.BaseType != null) {
- Expression member_lookup = Expression.MemberLookup (
- ec, ec.ContainerType.BaseType, "Finalize",
- MemberTypes.Method, Expression.AllBindingFlags, Location);
-
- if (member_lookup != null){
- MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
-
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
- }
- }
- ec.InFinally = old_in_finally;
-
- ig.EndExceptionBlock ();
- //ig.MarkLabel (ec.ReturnLabel);
- ig.Emit (OpCodes.Ret);
+ MethodData.Emit (parent, Block, this);
}
}
public abstract class ConstructorInitializer {
ArrayList argument_list;
ConstructorInfo parent_constructor;
- Location location;
+ Parameters parameters;
+ Location loc;
- public ConstructorInitializer (ArrayList argument_list, Location location)
+ public ConstructorInitializer (ArrayList argument_list, Parameters parameters,
+ Location loc)
{
this.argument_list = argument_list;
- this.location = location;
+ this.parameters = parameters;
+ this.loc = loc;
}
public ArrayList Arguments {
{
Expression parent_constructor_group;
Type t;
-
+
+ ec.CurrentBlock = new Block (null, true, parameters);
+
if (argument_list != null){
foreach (Argument a in argument_list){
- if (!a.Resolve (ec, location))
+ if (!a.Resolve (ec, loc))
return false;
}
}
+ ec.CurrentBlock = null;
+
if (this is ConstructorBaseInitializer) {
if (ec.ContainerType.BaseType == null)
return true;
t = ec.ContainerType.BaseType;
if (ec.ContainerType.IsValueType) {
- Report.Error (522, location,
+ Report.Error (522, loc,
"structs cannot call base class constructors");
return false;
}
} else
t = ec.ContainerType;
-
+
parent_constructor_group = Expression.MemberLookup (
- ec, t, ".ctor",
+ ec, t, t, ".ctor",
MemberTypes.Constructor,
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
- location);
+ loc);
if (parent_constructor_group == null){
- Report.Error (1501, location,
+ Report.Error (1501, loc,
"Can not find a constructor for this argument list");
return false;
}
parent_constructor = (ConstructorInfo) Invocation.OverloadResolve (ec,
- (MethodGroupExpr) parent_constructor_group, argument_list, location);
+ (MethodGroupExpr) parent_constructor_group, argument_list, loc);
if (parent_constructor == null){
- Report.Error (1501, location,
+ Report.Error (1501, loc,
"Can not find a constructor for this argument list");
return false;
}
public void Emit (EmitContext ec)
{
- if (parent_constructor != null)
- ec.ig.Emit (OpCodes.Ldarg_0);
- if (argument_list != null)
- Invocation.EmitArguments (ec, null, argument_list);
- if (parent_constructor != null)
- ec.ig.Emit (OpCodes.Call, parent_constructor);
+ if (parent_constructor != null){
+ if (ec.IsStatic)
+ Invocation.EmitCall (ec, true, true, null, parent_constructor, argument_list, loc);
+ else
+ Invocation.EmitCall (ec, true, false, ec.This, parent_constructor, argument_list, loc);
+ }
}
}
public class ConstructorBaseInitializer : ConstructorInitializer {
- public ConstructorBaseInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+ public ConstructorBaseInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
{
}
}
public class ConstructorThisInitializer : ConstructorInitializer {
- public ConstructorThisInitializer (ArrayList argument_list, Location l) : base (argument_list, l)
+ public ConstructorThisInitializer (ArrayList argument_list, Parameters pars, Location l) :
+ base (argument_list, pars, l)
{
}
}
public class Constructor : MethodCore {
public ConstructorBuilder ConstructorBuilder;
public ConstructorInitializer Initializer;
- public Attributes OptAttributes;
+ new public Attributes OptAttributes;
// <summary>
// Modifiers allowed for a constructor.
// </summary>
- const int AllowedModifiers =
+ public const int AllowedModifiers =
Modifiers.PUBLIC |
Modifiers.PROTECTED |
Modifiers.INTERNAL |
Modifiers.STATIC |
Modifiers.UNSAFE |
+ Modifiers.EXTERN |
Modifiers.PRIVATE;
//
// my very own code has static constructors.
//
public Constructor (string name, Parameters args, ConstructorInitializer init, Location l)
- : base (name, args, l)
+ : base (null, 0, AllowedModifiers, name, null, args, l)
{
Initializer = init;
}
MethodAttributes ca = (MethodAttributes.RTSpecialName |
MethodAttributes.SpecialName);
- Type [] parameters = ParameterTypes (parent);
-
- if (parameters == null)
+ // Check if arguments were correct.
+ if (!DoDefineParameters (parent))
return false;
-
+
if ((ModFlags & Modifiers.STATIC) != 0)
ca |= MethodAttributes.Static;
else {
- if (parent is Struct && parameters.Length == 0){
+ if (parent is Struct && ParameterTypes.Length == 0){
Report.Error (
568, Location,
"Structs can not contain explicit parameterless " +
"constructors");
return false;
}
- ca |= MethodAttributes.Public | MethodAttributes.HideBySig;
- }
+ ca |= MethodAttributes.HideBySig;
- foreach (Type partype in parameters)
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- return false;
+ if ((ModFlags & Modifiers.PUBLIC) != 0)
+ ca |= MethodAttributes.Public;
+ else if ((ModFlags & Modifiers.PROTECTED) != 0){
+ if ((ModFlags & Modifiers.INTERNAL) != 0)
+ ca |= MethodAttributes.FamORAssem;
+ else
+ ca |= MethodAttributes.Family;
+ } else if ((ModFlags & Modifiers.INTERNAL) != 0)
+ ca |= MethodAttributes.Assembly;
+ else if (IsDefault ())
+ ca |= MethodAttributes.Public;
+ else
+ ca |= MethodAttributes.Private;
+ }
ConstructorBuilder = parent.TypeBuilder.DefineConstructor (
- ca, GetCallingConvention (parent is Class), parameters);
+ ca, GetCallingConvention (parent is Class), ParameterTypes);
//
// HACK because System.Reflection.Emit is lame
//
- ParameterInfo = new InternalParameters (parent, Parameters);
-
- if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, parameters)) {
+ if (!TypeManager.RegisterMethod (ConstructorBuilder, ParameterInfo, ParameterTypes)) {
Report.Error (
111, Location,
"Class `" +parent.Name+ "' already contains a definition with the " +
if ((ModFlags & Modifiers.STATIC) == 0){
if (parent is Class && Initializer == null)
- Initializer = new ConstructorBaseInitializer (null, parent.Location);
+ Initializer = new ConstructorBaseInitializer (
+ null, Parameters.EmptyReadOnlyParameters, parent.Location);
//
ec.IsStatic = false;
}
- LabelParameters (ec, ParameterTypes (parent), ConstructorBuilder);
+ LabelParameters (ec, ParameterTypes, ConstructorBuilder);
//
// Classes can have base initializers and instance field initializers.
Attribute.ApplyAttributes (ec, ConstructorBuilder, this, OptAttributes, Location);
- ec.EmitTopBlock (Block, Location);
+ // If this is a non-static `struct' constructor and doesn't have any
+ // initializer, it must initialize all of the struct's fields.
+ if ((parent is Struct) && ((ModFlags & Modifiers.STATIC) == 0) &&
+ (Initializer == null))
+ Block.AddThisVariable (parent, Location);
+
+ ec.EmitTopBlock (Block, ParameterInfo, Location);
}
}
- //
- // Fields and Events both generate FieldBuilders, we use this to share
- // their common bits. This is also used to flag usage of the field
- //
- abstract public class FieldBase : MemberCore {
- public Expression Type;
- public readonly Object Initializer;
+ public class MethodData {
+ //
+ // The return type of this method
+ //
+ public readonly Type ReturnType;
+ public readonly Type[] ParameterTypes;
+ public readonly InternalParameters ParameterInfo;
+ public readonly CallingConventions CallingConventions;
public readonly Attributes OptAttributes;
- public FieldBuilder FieldBuilder;
- public Status status;
+ public readonly Location Location;
- [Flags]
- public enum Status : byte { ASSIGNED = 1, USED = 2 }
+ //
+ // Are we implementing an interface ?
+ //
+ public bool IsImplementing = false;
//
- // The constructor is only exposed to our children
+ // Protected data.
//
- protected FieldBase (Expression type, int mod, int allowed_mod, string name,
- object init, Attributes attrs, Location loc)
- : base (name, loc)
- {
- Type = type;
- ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
- Initializer = init;
- OptAttributes = attrs;
+ protected MemberBase member;
+ protected int modifiers;
+ protected MethodAttributes flags;
+ protected bool is_method;
+ protected string accessor_name;
+ ArrayList conditionals;
+
+ MethodBuilder builder = null;
+ public MethodBuilder MethodBuilder {
+ get {
+ return builder;
+ }
}
- }
- //
- // The Field class is used to represents class/struct fields during parsing.
- //
- public class Field : FieldBase {
- // <summary>
- // Modifiers allowed in a class declaration
- // </summary>
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.STATIC |
- Modifiers.VOLATILE |
- Modifiers.UNSAFE |
- Modifiers.READONLY;
+ public MethodData (MemberBase member, string name, Type return_type,
+ Type [] parameter_types, InternalParameters parameters,
+ CallingConventions cc, Attributes opt_attrs,
+ int modifiers, MethodAttributes flags, bool is_method)
+ {
+ this.member = member;
+ this.accessor_name = name;
+ this.ReturnType = return_type;
+ this.ParameterTypes = parameter_types;
+ this.ParameterInfo = parameters;
+ this.CallingConventions = cc;
+ this.OptAttributes = opt_attrs;
+ this.modifiers = modifiers;
+ this.flags = flags;
+ this.is_method = is_method;
+ this.Location = member.Location;
+ this.conditionals = new ArrayList ();
+ }
+
+ //
+ // Attributes.
+ //
+ Attribute dllimport_attribute = null;
+ string obsolete = null;
+ bool obsolete_error = false;
+
+ public virtual bool ApplyAttributes (Attributes opt_attrs, bool is_method)
+ {
+ if ((opt_attrs == null) || (opt_attrs.AttributeSections == null))
+ return true;
+
+ foreach (AttributeSection asec in opt_attrs.AttributeSections) {
+ if (asec.Attributes == null)
+ continue;
+
+ foreach (Attribute a in asec.Attributes) {
+ if (a.Name == "Conditional") {
+ if (!ApplyConditionalAttribute (a))
+ return false;
+ } else if (a.Name == "Obsolete") {
+ if (!ApplyObsoleteAttribute (a))
+ return false;
+ } else if (a.Name.IndexOf ("DllImport") != -1) {
+ if (!is_method) {
+ a.Type = TypeManager.dllimport_type;
+ Attribute.Error_AttributeNotValidForElement (a, Location);
+ return false;
+ }
+ if (!ApplyDllImportAttribute (a))
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ //
+ // Applies the `DllImport' attribute to the method.
+ //
+ protected virtual bool ApplyDllImportAttribute (Attribute a)
+ {
+ const int extern_static = Modifiers.EXTERN | Modifiers.STATIC;
+ if ((modifiers & extern_static) != extern_static) {
+ Report.Error (601, Location,
+ "The DllImport attribute must be specified on a method " +
+ "marked `static' and `extern'.");
+ return false;
+ }
+
+ flags |= MethodAttributes.PinvokeImpl;
+ dllimport_attribute = a;
+ return true;
+ }
+
+ //
+ // Applies the `Obsolete' attribute to the method.
+ //
+ protected virtual bool ApplyObsoleteAttribute (Attribute a)
+ {
+ if (obsolete != null) {
+ Report.Error (579, Location, "Duplicate `Obsolete' attribute");
+ return false;
+ }
+
+ obsolete = a.Obsolete_GetObsoleteMessage (out obsolete_error);
+ return obsolete != null;
+ }
+
+ //
+ // Applies the `Conditional' attribute to the method.
+ //
+ protected virtual bool ApplyConditionalAttribute (Attribute a)
+ {
+ // The Conditional attribute is only valid on methods.
+ if (!is_method) {
+ Attribute.Error_AttributeNotValidForElement (a, Location);
+ return false;
+ }
+
+ string condition = a.Conditional_GetConditionName ();
+
+ if (condition == null)
+ return false;
+
+ if (ReturnType != TypeManager.void_type) {
+ Report.Error (578, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because its return type is not void");
+ return false;
+ }
+
+ if ((modifiers & Modifiers.OVERRIDE) != 0) {
+ Report.Error (243, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an override method");
+ return false;
+ }
+
+ if (member.IsExplicitImpl) {
+ Report.Error (577, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an explicit interface implementation");
+ return false;
+ }
+
+ if (IsImplementing) {
+ Report.Error (623, Location,
+ "Conditional not valid on `" + member.Name + "' " +
+ "because it is an interface method");
+ return false;
+ }
+
+ conditionals.Add (condition);
+
+ return true;
+ }
+
+ //
+ // Checks whether this method should be ignored due to its Conditional attributes.
+ //
+ bool ShouldIgnore (Location loc)
+ {
+ // When we're overriding a virtual method, we implicitly inherit the
+ // Conditional attributes from our parent.
+ if (member.ParentMethod != null) {
+ TypeManager.MethodFlags flags = TypeManager.GetMethodFlags (
+ member.ParentMethod, loc);
+
+ if ((flags & TypeManager.MethodFlags.ShouldIgnore) != 0)
+ return true;
+ }
+
+ foreach (string condition in conditionals)
+ if (RootContext.AllDefines [condition] == null)
+ return true;
+
+ return false;
+ }
+
+ //
+ // Returns the TypeManager.MethodFlags for this method.
+ // This emits an error 619 / warning 618 if the method is obsolete.
+ // In the former case, TypeManager.MethodFlags.IsObsoleteError is returned.
+ //
+ public virtual TypeManager.MethodFlags GetMethodFlags (Location loc)
+ {
+ TypeManager.MethodFlags flags = 0;
+
+ if (obsolete != null) {
+ if (obsolete_error) {
+ Report.Error (619, loc, "Method `" + member.Name +
+ "' is obsolete: `" + obsolete + "'");
+ return TypeManager.MethodFlags.IsObsoleteError;
+ } else
+ Report.Warning (618, loc, "Method `" + member.Name +
+ "' is obsolete: `" + obsolete + "'");
+
+ flags |= TypeManager.MethodFlags.IsObsolete;
+ }
+
+ if (ShouldIgnore (loc))
+ flags |= TypeManager.MethodFlags.ShouldIgnore;
+
+ return flags;
+ }
+
+ public virtual bool Define (TypeContainer parent)
+ {
+ MethodInfo implementing = null;
+ string method_name, name, prefix;
+
+ if (OptAttributes != null)
+ if (!ApplyAttributes (OptAttributes, is_method))
+ return false;
+
+ if (member.IsExplicitImpl)
+ prefix = member.InterfaceType.FullName + ".";
+ else
+ prefix = "";
+
+ if (accessor_name != null)
+ name = accessor_name + "_" + member.ShortName;
+ else
+ name = member.ShortName;
+ method_name = prefix + name;
+
+ if (parent.Pending != null){
+ if (member is Indexer)
+ implementing = parent.Pending.IsInterfaceIndexer (
+ member.InterfaceType, ReturnType, ParameterTypes);
+ else
+ implementing = parent.Pending.IsInterfaceMethod (
+ member.InterfaceType, name, ReturnType, ParameterTypes);
+
+ if (member.InterfaceType != null && implementing == null){
+ TypeContainer.Error_ExplicitInterfaceNotMemberInterface (
+ Location, name);
+ return false;
+ }
+ }
+
+ //
+ // For implicit implementations, make sure we are public, for
+ // explicit implementations, make sure we are private.
+ //
+ if (implementing != null){
+ //
+ // Setting null inside this block will trigger a more
+ // verbose error reporting for missing interface implementations
+ //
+ // The "candidate" function has been flagged already
+ // but it wont get cleared
+ //
+ if (!member.IsExplicitImpl){
+ //
+ // We already catch different accessibility settings
+ // so we just need to check that we are not private
+ //
+ if ((modifiers & Modifiers.PRIVATE) != 0)
+ implementing = null;
+
+ //
+ // Static is not allowed
+ //
+ if ((modifiers & Modifiers.STATIC) != 0)
+ implementing = null;
+ } else {
+ if ((modifiers & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
+ Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
+ implementing = null;
+ }
+ }
+ }
+
+ //
+ // If implementing is still valid, set flags
+ //
+ if (implementing != null){
+ //
+ // When implementing interface methods, set NewSlot.
+ //
+ if (implementing.DeclaringType.IsInterface)
+ flags |= MethodAttributes.NewSlot;
+
+ flags |=
+ MethodAttributes.Virtual |
+ MethodAttributes.HideBySig;
+
+ // Get the method name from the explicit interface.
+ if (member.InterfaceType != null) {
+ name = implementing.Name;
+ method_name = prefix + name;
+ }
+
+ IsImplementing = true;
+ }
+
+ //
+ // Create the MethodBuilder for the method
+ //
+ if ((flags & MethodAttributes.PinvokeImpl) != 0) {
+ if ((modifiers & Modifiers.STATIC) == 0) {
+ Report.Error (601, Location,
+ "The DllImport attribute must be specified on " +
+ "a method marked 'static' and 'extern'.");
+ return false;
+ }
+
+ EmitContext ec = new EmitContext (
+ parent, Location, null, ReturnType, modifiers);
+
+ builder = dllimport_attribute.DefinePInvokeMethod (
+ ec, parent.TypeBuilder, method_name, flags,
+ ReturnType, ParameterTypes);
+ } else
+ builder = parent.TypeBuilder.DefineMethod (
+ method_name, flags, CallingConventions,
+ ReturnType, ParameterTypes);
+
+ if (builder == null)
+ return false;
+
+ if (IsImplementing) {
+ //
+ // clear the pending implemntation flag
+ //
+ if (member is Indexer) {
+ parent.Pending.ImplementIndexer (
+ member.InterfaceType, builder, ReturnType,
+ ParameterTypes, true);
+ } else
+ parent.Pending.ImplementMethod (
+ member.InterfaceType, name, ReturnType,
+ ParameterTypes, member.IsExplicitImpl);
+
+ if (member.IsExplicitImpl)
+ parent.TypeBuilder.DefineMethodOverride (
+ builder, implementing);
+ }
+
+ if (!TypeManager.RegisterMethod (builder, ParameterInfo, ParameterTypes)) {
+ Report.Error (111, Location,
+ "Class `" + parent.Name +
+ "' already contains a definition with the " +
+ "same return value and parameter types as the " +
+ "'get' method of property `" + member.Name + "'");
+ return false;
+ }
+
+ TypeManager.AddMethod (builder, this);
+
+ return true;
+ }
+
+ //
+ // Emits the code
+ //
+ public virtual void Emit (TypeContainer parent, Block block, object kind)
+ {
+ ILGenerator ig;
+ EmitContext ec;
+
+ if ((flags & MethodAttributes.PinvokeImpl) == 0)
+ ig = builder.GetILGenerator ();
+ else
+ ig = null;
+
+ ec = new EmitContext (parent, Location, ig, ReturnType, modifiers);
+
+ if (OptAttributes != null)
+ Attribute.ApplyAttributes (ec, builder, kind, OptAttributes, Location);
+
+ if (member is MethodCore)
+ ((MethodCore) member).LabelParameters (ec, ParameterTypes, MethodBuilder);
+
+ //
+ // abstract or extern methods have no bodies
+ //
+ if ((modifiers & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0){
+ if (block == null)
+ return;
+
+ //
+ // abstract or extern methods have no bodies.
+ //
+ if ((modifiers & Modifiers.ABSTRACT) != 0)
+ Report.Error (
+ 500, Location, "Abstract method `" +
+ TypeManager.CSharpSignature (builder) +
+ "' can not have a body");
+
+ if ((modifiers & Modifiers.EXTERN) != 0)
+ Report.Error (
+ 179, Location, "External method `" +
+ TypeManager.CSharpSignature (builder) +
+ "' can not have a body");
+
+ return;
+ }
+
+ //
+ // Methods must have a body unless they're extern or abstract
+ //
+ if (block == null) {
+ Report.Error (
+ 501, Location, "Method `" +
+ TypeManager.CSharpSignature (builder) +
+ "' must declare a body since it is not marked " +
+ "abstract or extern");
+ return;
+ }
+
+ //
+ // Handle destructors specially
+ //
+ // FIXME: This code generates buggy code
+ //
+ if (member.Name == "Finalize" && ReturnType == TypeManager.void_type)
+ EmitDestructor (ec, block);
+ else {
+ ISymbolWriter sw = CodeGen.SymbolWriter;
+
+ if ((sw != null) && !Location.IsNull (Location) &&
+ !Location.IsNull (block.EndLocation)) {
+ Location end = block.EndLocation;
+ MethodToken token = MethodBuilder.GetToken ();
+ sw.OpenMethod (new SymbolToken (token.Token));
+ sw.SetMethodSourceRange (Location.SymbolDocument,
+ Location.Row, 0,
+ end.SymbolDocument,
+ end.Row, 0);
+
+ ec.EmitTopBlock (block, ParameterInfo, Location);
+
+ sw.CloseMethod ();
+ } else
+ ec.EmitTopBlock (block, ParameterInfo, Location);
+ }
+ }
+
+ void EmitDestructor (EmitContext ec, Block block)
+ {
+ ILGenerator ig = ec.ig;
+
+ Label finish = ig.DefineLabel ();
+ bool old_in_try = ec.InTry;
+
+ ig.BeginExceptionBlock ();
+ ec.InTry = true;
+ ec.ReturnLabel = finish;
+ ec.HasReturnLabel = true;
+ ec.EmitTopBlock (block, null, Location);
+ ec.InTry = old_in_try;
+
+ // ig.MarkLabel (finish);
+ bool old_in_finally = ec.InFinally;
+ ec.InFinally = true;
+ ig.BeginFinallyBlock ();
+
+ if (ec.ContainerType.BaseType != null) {
+ Expression member_lookup = Expression.MemberLookup (
+ ec, ec.ContainerType.BaseType, ec.ContainerType.BaseType, "Finalize",
+ MemberTypes.Method, Expression.AllBindingFlags, Location);
+
+ if (member_lookup != null){
+ MethodGroupExpr parent_destructor = ((MethodGroupExpr) member_lookup);
+
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, (MethodInfo) parent_destructor.Methods [0]);
+ }
+ }
+ ec.InFinally = old_in_finally;
+
+ ig.EndExceptionBlock ();
+ //ig.MarkLabel (ec.ReturnLabel);
+ ig.Emit (OpCodes.Ret);
+ }
+ }
+
+ abstract public class MemberBase : MemberCore {
+ public Expression Type;
+ public readonly Attributes OptAttributes;
+
+ protected MethodAttributes flags;
+
+ //
+ // The "short" name of this property / indexer / event. This is the
+ // name without the explicit interface.
+ //
+ public string ShortName;
+
+ //
+ // The type of this property / indexer / event
+ //
+ public Type MemberType;
+
+ //
+ // If true, this is an explicit interface implementation
+ //
+ public bool IsExplicitImpl = false;
+
+ //
+ // The name of the interface we are explicitly implementing
+ //
+ public string ExplicitInterfaceName = null;
+
+ //
+ // If true, the interface type we are explicitly implementing
+ //
+ public Type InterfaceType = null;
+
+ //
+ // The method we're overriding if this is an override method.
+ //
+ protected MethodInfo parent_method = null;
+ public MethodInfo ParentMethod {
+ get {
+ return parent_method;
+ }
+ }
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected MemberBase (Expression type, int mod, int allowed_mod, string name,
+ Attributes attrs, Location loc)
+ : base (name, loc)
+ {
+ Type = type;
+ ModFlags = Modifiers.Check (allowed_mod, mod, Modifiers.PRIVATE, loc);
+ OptAttributes = attrs;
+ }
+
+ protected virtual bool CheckBase (TypeContainer parent)
+ {
+ return true;
+ }
+
+ protected virtual bool CheckParameters (TypeContainer parent, Type [] parameters)
+ {
+ bool error = false;
+
+ foreach (Type partype in parameters){
+ if (partype.IsPointer && !UnsafeOK (parent))
+ error = true;
+
+ if (parent.AsAccessible (partype, ModFlags))
+ continue;
+
+ if (this is Indexer)
+ Report.Error (55, Location,
+ "Inconsistent accessibility: parameter type `" +
+ TypeManager.CSharpName (partype) + "' is less " +
+ "accessible than indexer `" + Name + "'");
+ else
+ Report.Error (51, Location,
+ "Inconsistent accessibility: parameter type `" +
+ TypeManager.CSharpName (partype) + "' is less " +
+ "accessible than method `" + Name + "'");
+ error = true;
+ }
+
+ return !error;
+ }
+
+ protected virtual bool DoDefine (TypeContainer parent)
+ {
+ if (Name == null)
+ Name = "this";
+
+ if (!parent.MethodModifiersValid (ModFlags, Name, Location))
+ return false;
+
+ flags = Modifiers.MethodAttr (ModFlags);
+
+ // Lookup Type, verify validity
+ MemberType = parent.ResolveType (Type, false, Location);
+ if (MemberType == null)
+ return false;
+
+ // verify accessibility
+ if (!parent.AsAccessible (MemberType, ModFlags)) {
+ if (this is Property)
+ Report.Error (53, Location,
+ "Inconsistent accessibility: property type `" +
+ TypeManager.CSharpName (MemberType) + "' is less " +
+ "accessible than property `" + Name + "'");
+ else if (this is Indexer)
+ Report.Error (54, Location,
+ "Inconsistent accessibility: indexer return type `" +
+ TypeManager.CSharpName (MemberType) + "' is less " +
+ "accessible than indexer `" + Name + "'");
+ else if (this is Method)
+ Report.Error (50, Location,
+ "Inconsistent accessibility: return type `" +
+ TypeManager.CSharpName (MemberType) + "' is less " +
+ "accessible than method `" + Name + "'");
+ else
+ Report.Error (52, Location,
+ "Inconsistent accessibility: field type `" +
+ TypeManager.CSharpName (MemberType) + "' is less " +
+ "accessible than field `" + Name + "'");
+ return false;
+ }
+
+ if (MemberType.IsPointer && !UnsafeOK (parent))
+ return false;
+
+ //
+ // Check for explicit interface implementation
+ //
+ if ((ExplicitInterfaceName == null) && (Name.IndexOf (".") != -1)){
+ int pos = Name.LastIndexOf (".");
+
+ ExplicitInterfaceName = Name.Substring (0, pos);
+ ShortName = Name.Substring (pos + 1);
+ } else
+ ShortName = Name;
+
+ if (ExplicitInterfaceName != null) {
+ InterfaceType = RootContext.LookupType (
+ parent, ExplicitInterfaceName, false, Location);
+ if (InterfaceType == null)
+ return false;
+
+ // Compute the full name that we need to export.
+ Name = InterfaceType.FullName + "." + ShortName;
+
+ if (!parent.VerifyImplements (InterfaceType, ShortName, Name, Location))
+ return false;
+
+ IsExplicitImpl = true;
+ } else
+ IsExplicitImpl = false;
+
+ return true;
+ }
+ }
+
+ //
+ // Fields and Events both generate FieldBuilders, we use this to share
+ // their common bits. This is also used to flag usage of the field
+ //
+ abstract public class FieldBase : MemberBase {
+ public FieldBuilder FieldBuilder;
+ public Status status;
+
+ [Flags]
+ public enum Status : byte { ASSIGNED = 1, USED = 2 }
+
+ //
+ // The constructor is only exposed to our children
+ //
+ protected FieldBase (Expression type, int mod, int allowed_mod, string name,
+ object init, Attributes attrs, Location loc)
+ : base (type, mod, allowed_mod, name, attrs, loc)
+ {
+ this.init = init;
+ }
+
+ //
+ // Whether this field has an initializer.
+ //
+ public bool HasInitializer {
+ get {
+ return init != null;
+ }
+ }
+
+ // Private.
+ readonly Object init;
+ Expression init_expr;
+ bool init_expr_initialized = false;
+
+ //
+ // Resolves and returns the field initializer.
+ //
+ public Expression GetInitializerExpression (EmitContext ec)
+ {
+ if (init_expr_initialized)
+ return init_expr;
+
+ Expression e;
+ if (init is Expression)
+ e = (Expression) init;
+ else
+ e = new ArrayCreation (Type, "", (ArrayList)init, Location);
+
+ ec.IsFieldInitializer = true;
+ e = e.DoResolve (ec);
+ ec.IsFieldInitializer = false;
+
+ init_expr = e;
+ init_expr_initialized = true;
+
+ return init_expr;
+ }
+ }
+
+ //
+ // The Field class is used to represents class/struct fields during parsing.
+ //
+ public class Field : FieldBase {
+ // <summary>
+ // Modifiers allowed in a class declaration
+ // </summary>
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.STATIC |
+ Modifiers.VOLATILE |
+ Modifiers.UNSAFE |
+ Modifiers.READONLY;
public Field (Expression type, int mod, string name, Object expr_or_array_init,
Attributes attrs, Location loc)
if (t == null)
return false;
- if (!TypeContainer.AsAccessible (t, ModFlags))
+ if (!parent.AsAccessible (t, ModFlags)) {
+ Report.Error (52, Location,
+ "Inconsistent accessibility: field type `" +
+ TypeManager.CSharpName (t) + "' is less " +
+ "accessible than field `" + Name + "'");
return false;
+ }
if (t.IsPointer && !UnsafeOK (parent))
return false;
// ptype is only null for System.Object while compiling corlib.
if (ptype != null){
- MemberInfo [] mi;
-
- mi = TypeContainer.FindMembers (
+ TypeContainer.FindMembers (
ptype, MemberTypes.Method,
BindingFlags.Public |
BindingFlags.Static | BindingFlags.Instance,
}
}
}
-
+
+ FieldAttributes fa = Modifiers.FieldAttr (ModFlags);
+
+ if (parent is Struct &&
+ ((fa & FieldAttributes.Static) == 0) &&
+ t == parent.TypeBuilder &&
+ !TypeManager.IsBuiltinType (t)){
+ Report.Error (523, Location, "Struct member `" + parent.Name + "." + Name +
+ "' causes a cycle in the structure layout");
+ return false;
+ }
FieldBuilder = parent.TypeBuilder.DefineField (
Name, t, Modifiers.FieldAttr (ModFlags));
Block = b;
OptAttributes = attrs;
}
- }
-
- public class Property : MemberCore {
- public Expression Type;
- public Accessor Get, Set;
- public PropertyBuilder PropertyBuilder;
- public Attributes OptAttributes;
- public MethodBuilder GetBuilder, SetBuilder;
-
- //
- // The type, once we compute it.
- Type PropertyType;
-
- bool explicit_impl;
-
- //
- // If true, the interface type we are explicitly implementing
- //
- Type explicit_iface_type = null;
-
- const int AllowedModifiers =
- Modifiers.NEW |
- Modifiers.PUBLIC |
- Modifiers.PROTECTED |
- Modifiers.INTERNAL |
- Modifiers.PRIVATE |
- Modifiers.STATIC |
- Modifiers.SEALED |
- Modifiers.OVERRIDE |
- Modifiers.ABSTRACT |
- Modifiers.UNSAFE |
- Modifiers.EXTERN |
- Modifiers.VIRTUAL;
+ }
- public Property (Expression type, string name, int mod_flags,
- Accessor get_block, Accessor set_block,
- Attributes attrs, Location loc)
- : base (name, loc)
+ //
+ // Properties and Indexers both generate PropertyBuilders, we use this to share
+ // their common bits.
+ //
+ abstract public class PropertyBase : MethodCore {
+ public Accessor Get, Set;
+ public PropertyBuilder PropertyBuilder;
+ public MethodBuilder GetBuilder, SetBuilder;
+ public MethodData GetData, SetData;
+
+ protected EmitContext ec;
+
+ public PropertyBase (Expression type, string name, int mod_flags, int allowed_mod,
+ Parameters parameters, Accessor get_block, Accessor set_block,
+ Attributes attrs, Location loc)
+ : base (type, mod_flags, allowed_mod, name, attrs, parameters, loc)
{
- Type = type;
- ModFlags = Modifiers.Check (AllowedModifiers, mod_flags, Modifiers.PRIVATE, loc);
Get = get_block;
Set = set_block;
- OptAttributes = attrs;
+ }
+
+ protected override bool DoDefine (TypeContainer parent)
+ {
+ if (!base.DoDefine (parent))
+ return false;
+
+ ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
+
+ return true;
}
//
// Checks our base implementation if any
//
- bool CheckBase (MethodAttributes flags, TypeContainer parent)
+ protected override bool CheckBase (TypeContainer parent)
{
+ // Check whether arguments were correct.
+ if (!DoDefineParameters (parent))
+ return false;
+
+ if (IsExplicitImpl)
+ return true;
+
+ string report_name;
+ MethodSignature ms, base_ms;
+ if (this is Indexer) {
+ string name, base_name;
+
+ report_name = "this";
+ name = TypeManager.IndexerPropertyName (parent.TypeBuilder);
+ ms = new MethodSignature (name, null, ParameterTypes);
+ base_name = TypeManager.IndexerPropertyName (parent.TypeBuilder.BaseType);
+ base_ms = new MethodSignature (base_name, null, ParameterTypes);
+ } else {
+ report_name = Name;
+ ms = base_ms = new MethodSignature (Name, null, ParameterTypes);
+ }
+
+ MemberList props_this;
+
+ props_this = TypeContainer.FindMembers (
+ parent.TypeBuilder, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public |
+ BindingFlags.Static | BindingFlags.Instance |
+ BindingFlags.DeclaredOnly,
+ MethodSignature.method_signature_filter, ms);
+
+ if (props_this.Count > 0) {
+ Report.Error (111, Location, "Class `" + parent.Name + "' " +
+ "already defines a member called `" + report_name + "' " +
+ "with the same parameter types");
+ return false;
+ }
+
//
// Find properties with the same name on the base class
//
-
- MemberInfo [] props;
- MemberInfo [] props_static = TypeManager.MemberLookup (
- parent.TypeBuilder,
- parent.TypeBuilder.BaseType,
- MemberTypes.Property, BindingFlags.Public | BindingFlags.Static,
- Name);
-
- MemberInfo [] props_instance = TypeManager.MemberLookup (
- parent.TypeBuilder,
- parent.TypeBuilder.BaseType,
- MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance,
- Name);
+ MemberList props;
+ MemberList props_static = TypeContainer.FindMembers (
+ parent.TypeBuilder.BaseType, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static,
+ MethodSignature.inheritable_property_signature_filter, base_ms);
+
+ MemberList props_instance = TypeContainer.FindMembers (
+ parent.TypeBuilder.BaseType, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+ MethodSignature.inheritable_property_signature_filter,
+ base_ms);
//
// Find if we have anything
//
- if (props_static != null && props_static.Length > 0)
+ if (props_static.Count > 0)
props = props_static;
- else if (props_instance != null && props_instance.Length > 0)
+ else if (props_instance.Count > 0)
props = props_instance;
else
props = null;
//
// If we have something on the base.
- if (props != null && props.Length > 0){
- if (props.Length > 1)
- throw new Exception ("Should not happen");
-
+ if (props != null && props.Count > 0){
PropertyInfo pi = (PropertyInfo) props [0];
MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
MethodInfo reference = inherited_get == null ?
inherited_set : inherited_get;
- if (reference != null)
- if (!CheckMethodAgainstBase (parent, flags, reference))
+ if (reference != null) {
+ string name = reference.DeclaringType.Name + "." + report_name;
+
+ if (!CheckMethodAgainstBase (parent, flags, reference, name))
return false;
-
+ }
+
+ if (((ModFlags & Modifiers.NEW) == 0) && (pi.PropertyType != MemberType)) {
+ Report.Error (508, parent.MakeName (Name) + ": cannot " +
+ "change return type when overriding inherited " +
+ "member `" + pi.DeclaringType + "." + pi.Name + "'");
+ return false;
+ }
} else {
if ((ModFlags & Modifiers.NEW) != 0)
WarningNotHiding (parent);
if ((ModFlags & Modifiers.OVERRIDE) != 0){
- Report.Error (115, Location,
- parent.MakeName (Name) +
- " no suitable properties found to override");
+ if (this is Indexer)
+ Report.Error (115, Location,
+ parent.MakeName (Name) +
+ " no suitable indexers found to override");
+ else
+ Report.Error (115, Location,
+ parent.MakeName (Name) +
+ " no suitable properties found to override");
return false;
}
}
return true;
}
- bool DefineMethod (TypeContainer parent, string short_name,
- MethodAttributes flags, bool is_get, ref bool is_implementing)
+ public void Emit (TypeContainer tc)
{
- Type [] parameters = TypeManager.NoTypes;
- MethodInfo implementing = null;
- Type fn_type;
- string name, prefix;
-
- if (explicit_impl)
- prefix = explicit_iface_type.FullName + ".";
- else
- prefix = "";
-
- if (is_get){
- fn_type = PropertyType;
- name = "get_" + short_name;
- } else {
- name = "set_" + short_name;
- parameters = new Type [1];
- parameters [0] = PropertyType;
- fn_type = TypeManager.void_type;
- }
-
- if (parent.Pending != null){
- implementing = parent.Pending.IsInterfaceMethod (
- explicit_iface_type, name, fn_type, parameters);
-
- if (explicit_iface_type != null && implementing == null){
- TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, name);
- return false;
- }
- }
-
- //
- // For implicit implementations, make sure we are public, for
- // explicit implementations, make sure we are private.
- //
- if (implementing != null){
- //
- // Setting null inside this block will trigger a more
- // verbose error reporting for missing interface implementations
- //
- // The "candidate" function has been flagged already
- // but it wont get cleared
- //
- if (explicit_iface_type == null){
- //
- // We already catch different accessibility settings
- // so we just need to check that we are not private
- //
- if ((ModFlags & Modifiers.PRIVATE) != 0)
- implementing = null;
-
- //
- // Static is not allowed
- //
- if ((ModFlags & Modifiers.STATIC) != 0)
- implementing = null;
- } else {
- if ((ModFlags & (Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
- Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
- implementing = null;
- }
- }
- }
-
//
- // If implementing is still valid, set flags
+ // The PropertyBuilder can be null for explicit implementations, in that
+ // case, we do not actually emit the ".property", so there is nowhere to
+ // put the attribute
//
- if (implementing != null){
- //
- // When implementing interface methods, set NewSlot.
- //
- if (implementing.DeclaringType.IsInterface)
- flags |= MethodAttributes.NewSlot;
-
- flags |=
- MethodAttributes.Virtual |
- MethodAttributes.HideBySig;
-
- //
- // clear the pending implemntation flag
- //
- parent.Pending.ImplementMethod (
- explicit_iface_type, name, fn_type, parameters, explicit_impl);
+ if (PropertyBuilder != null)
+ Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
- is_implementing = true;
- }
+ if (GetData != null)
+ GetData.Emit (tc, Get.Block, Get);
- //
- // If this is not an explicit interface implementation,
- // clear implementing, as it is only used for explicit
- // interface implementation
- //
- if (Name.IndexOf (".") == -1)
- implementing = null;
-
- if (is_get){
- GetBuilder = parent.TypeBuilder.DefineMethod (
- prefix + name, flags, PropertyType, null);
+ if (SetData != null)
+ SetData.Emit (tc, Set.Block, Set);
+ }
+ }
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- GetBuilder, implementing);
-
- //
- // HACK because System.Reflection.Emit is lame
- //
- InternalParameters ip = new InternalParameters (
- parent, Parameters.GetEmptyReadOnlyParameters ());
-
- if (!TypeManager.RegisterMethod (GetBuilder, ip, null)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types as the " +
- "'get' method of property `" + Name + "'");
- return false;
- }
- } else {
- SetBuilder = parent.TypeBuilder.DefineMethod (
- prefix + name, flags, null, parameters);
-
- if (implementing != null)
- parent.TypeBuilder.DefineMethodOverride (
- SetBuilder, implementing);
-
- SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
-
- //
- // HACK because System.Reflection.Emit is lame
- //
- Parameter [] parms = new Parameter [1];
- parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
- InternalParameters ip = new InternalParameters (
- parent, new Parameters (parms, null, Location));
-
- if (!TypeManager.RegisterMethod (SetBuilder, ip, parameters)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types as the " +
- "'set' method of property `" + Name + "'");
- return false;
- }
- }
+ public class Property : PropertyBase {
+ const int AllowedModifiers =
+ Modifiers.NEW |
+ Modifiers.PUBLIC |
+ Modifiers.PROTECTED |
+ Modifiers.INTERNAL |
+ Modifiers.PRIVATE |
+ Modifiers.STATIC |
+ Modifiers.SEALED |
+ Modifiers.OVERRIDE |
+ Modifiers.ABSTRACT |
+ Modifiers.UNSAFE |
+ Modifiers.EXTERN |
+ Modifiers.VIRTUAL;
- return true;
+ public Property (Expression type, string name, int mod_flags,
+ Accessor get_block, Accessor set_block,
+ Attributes attrs, Location loc)
+ : base (type, name, mod_flags, AllowedModifiers,
+ Parameters.EmptyReadOnlyParameters,
+ get_block, set_block, attrs, loc)
+ {
}
public override bool Define (TypeContainer parent)
{
- string short_name;
-
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
- return false;
-
- MethodAttributes flags = Modifiers.MethodAttr (ModFlags);
-
- flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
-
- // Lookup Type, verify validity
- PropertyType = parent.ResolveType (Type, false, Location);
- if (PropertyType == null)
+ if (!DoDefine (parent))
return false;
- // verify accessibility
- if (!TypeContainer.AsAccessible (PropertyType, ModFlags))
+ if (!CheckBase (parent))
return false;
- if (PropertyType.IsPointer && !UnsafeOK (parent))
- return false;
-
- if (!CheckBase (flags, parent))
- return false;
+ flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
- //
- // Check for explicit interface implementation
- //
- if (Name.IndexOf (".") != -1){
- int pos = Name.LastIndexOf (".");
- string iface = Name.Substring (0, pos);
+ if (Get != null) {
+ Type [] parameters = TypeManager.NoTypes;
- explicit_iface_type = RootContext.LookupType (parent, iface, false, Location);
- if (explicit_iface_type == null)
- return false;
+ InternalParameters ip = new InternalParameters (
+ parent, Parameters.EmptyReadOnlyParameters);
- short_name = Name.Substring (pos + 1);
+ GetData = new MethodData (this, "get", MemberType,
+ parameters, ip, CallingConventions.Standard,
+ Get.OptAttributes, ModFlags, flags, false);
- // Compute the full name that we need to export.
- Name = explicit_iface_type.FullName + "." + short_name;
-
- if (!parent.VerifyImplements (explicit_iface_type, short_name, Name, Location))
+ if (!GetData.Define (parent))
return false;
-
- explicit_impl = true;
- } else {
- explicit_impl = false;
- short_name = Name;
+
+ GetBuilder = GetData.MethodBuilder;
}
- bool is_implementing = false;
- if (Get != null)
- if (!DefineMethod (parent, short_name, flags, true, ref is_implementing))
- return false;
-
- if (Set != null)
- if (!DefineMethod (parent, short_name, flags, false, ref is_implementing))
+ if (Set != null) {
+ Type [] parameters = new Type [1];
+ parameters [0] = MemberType;
+
+ Parameter [] parms = new Parameter [1];
+ parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
+ InternalParameters ip = new InternalParameters (
+ parent, new Parameters (parms, null, Location));
+
+ SetData = new MethodData (this, "set", TypeManager.void_type,
+ parameters, ip, CallingConventions.Standard,
+ Set.OptAttributes, ModFlags, flags, false);
+
+ if (!SetData.Define (parent))
return false;
+ SetBuilder = SetData.MethodBuilder;
+ SetBuilder.DefineParameter (1, ParameterAttributes.None, "value");
+ }
+
// FIXME - PropertyAttributes.HasDefault ?
PropertyAttributes prop_attr =
PropertyAttributes.RTSpecialName |
PropertyAttributes.SpecialName;
- if (!explicit_impl){
+ if (!IsExplicitImpl){
PropertyBuilder = parent.TypeBuilder.DefineProperty (
- Name, prop_attr, PropertyType, null);
+ Name, prop_attr, MemberType, null);
if (Get != null)
PropertyBuilder.SetGetMethod (GetBuilder);
}
return true;
}
-
- public void Emit (TypeContainer tc)
- {
- ILGenerator ig;
- EmitContext ec;
-
- ec = new EmitContext (tc, Location, null, PropertyType, ModFlags);
-
- //
- // The PropertyBuilder can be null for explicit implementations, in that
- // case, we do not actually emit the ".property", so there is nowhere to
- // put the attribute
- //
- if (PropertyBuilder != null)
- Attribute.ApplyAttributes (ec, PropertyBuilder, this, OptAttributes, Location);
- if (Get != null)
- Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
- if (Set != null)
- Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
-
- //
- // abstract or extern properties have no bodies
- //
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
- return;
-
- if (Get != null){
- ig = GetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, PropertyType, ModFlags);
-
- ec.EmitTopBlock (Get.Block, Location);
- }
-
- if (Set != null){
- ig = SetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, null, ModFlags);
-
- ec.EmitTopBlock (Set.Block, Location);
- }
- }
}
-
/// </summary>
/// Gigantic workaround for lameness in SRE follows :
/// This class derives from EventInfo and attempts to basically
public readonly Accessor Remove;
public MyEventBuilder EventBuilder;
- Type EventType;
MethodBuilder AddBuilder, RemoveBuilder;
+ MethodData AddData, RemoveData;
public Event (Expression type, string name, Object init, int mod, Accessor add,
Accessor remove, Attributes attrs, Location loc)
public override bool Define (TypeContainer parent)
{
- if (!parent.MethodModifiersValid (ModFlags, Name, Location))
- return false;
-
- MethodAttributes m_attr = Modifiers.MethodAttr (ModFlags);
EventAttributes e_attr = EventAttributes.RTSpecialName | EventAttributes.SpecialName;
- EventType = parent.ResolveType (Type, false, Location);
- if (EventType == null)
- return false;
-
- if (!TypeContainer.AsAccessible (EventType, ModFlags))
- return false;
-
- if (EventType.IsPointer && !UnsafeOK (parent))
- return false;
-
- if (!EventType.IsSubclassOf (TypeManager.delegate_type)) {
- Report.Error (66, Location, "'" + parent.Name + "." + Name +
- "' : event must be of a delegate type");
+ if (!DoDefine (parent))
return false;
- }
-
- Type [] parameters = new Type [1];
- parameters [0] = EventType;
-
- EventBuilder = new MyEventBuilder (parent.TypeBuilder, Name, e_attr, EventType);
-
- if (Add == null && Remove == null) {
- FieldBuilder = parent.TypeBuilder.DefineField (
- Name, EventType, FieldAttributes.FamANDAssem);
- TypeManager.RegisterPrivateFieldOfEvent ((EventInfo) EventBuilder, FieldBuilder);
- TypeManager.RegisterFieldBase (FieldBuilder, this);
- }
-
- //
- // Now define the accessors
- //
- string add_name = "add_" + Name;
-
- AddBuilder = parent.TypeBuilder.DefineMethod (
- add_name, m_attr, null, parameters);
- AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- EventBuilder.SetAddOnMethod (AddBuilder);
- if (parent.Pending != null)
- parent.Pending.ImplementMethod (null, add_name, null, parameters, false);
-
- //
- // HACK because System.Reflection.Emit is lame
- //
+
+ if (!MemberType.IsSubclassOf (TypeManager.delegate_type)) {
+ Report.Error (66, Location, "'" + parent.Name + "." + Name +
+ "' : event must be of a delegate type");
+ return false;
+ }
+
+ Type [] parameter_types = new Type [1];
+ parameter_types [0] = MemberType;
+
Parameter [] parms = new Parameter [1];
parms [0] = new Parameter (Type, "value", Parameter.Modifier.NONE, null);
InternalParameters ip = new InternalParameters (
- parent, new Parameters (parms, null, Location));
-
- if (!TypeManager.RegisterMethod (AddBuilder, ip, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name + "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'add' method of event `" + Name + "'");
- return false;
- }
+ parent, new Parameters (parms, null, Location));
- string remove_name = "remove_" + Name;
- RemoveBuilder = parent.TypeBuilder.DefineMethod (
- remove_name, m_attr, null, parameters);
- RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- EventBuilder.SetRemoveOnMethod (RemoveBuilder);
- if (parent.Pending != null)
- parent.Pending.ImplementMethod (null, remove_name, null, parameters, false);
+ if (!CheckBase (parent))
+ return false;
//
- // This looks like dead code
+ // Now define the accessors
//
- //if (parent.Pending != null)
- // parent.Pending.IsInterfaceMethod (null, remove_name, null, parameters, false);
+ AddData = new MethodData (this, "add", TypeManager.void_type,
+ parameter_types, ip, CallingConventions.Standard,
+ (Add != null) ? Add.OptAttributes : null,
+ ModFlags, flags, false);
- //
- // HACK because System.Reflection.Emit is lame
- //
+ if (!AddData.Define (parent))
+ return false;
+
+ AddBuilder = AddData.MethodBuilder;
+ AddBuilder.DefineParameter (1, ParameterAttributes.None, "value");
- if (!TypeManager.RegisterMethod (RemoveBuilder, ip, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name + "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'remove' method of event `" + Name + "'");
+ RemoveData = new MethodData (this, "remove", TypeManager.void_type,
+ parameter_types, ip, CallingConventions.Standard,
+ (Remove != null) ? Remove.OptAttributes : null,
+ ModFlags, flags, false);
+
+ if (!RemoveData.Define (parent))
return false;
- }
+
+ RemoveBuilder = RemoveData.MethodBuilder;
+ RemoveBuilder.DefineParameter (1, ParameterAttributes.None, "value");
+
+ if (!IsExplicitImpl){
+ EventBuilder = new MyEventBuilder (
+ parent.TypeBuilder, Name, e_attr, MemberType);
+
+ if (Add == null && Remove == null) {
+ FieldBuilder = parent.TypeBuilder.DefineField (
+ Name, MemberType,
+ FieldAttributes.FamANDAssem | ((ModFlags & Modifiers.STATIC) != 0 ? FieldAttributes.Static : 0));
+ TypeManager.RegisterPrivateFieldOfEvent (
+ (EventInfo) EventBuilder, FieldBuilder);
+ TypeManager.RegisterFieldBase (FieldBuilder, this);
+ }
- if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition for the event `" +
- Name + "'");
- return false;
+ EventBuilder.SetAddOnMethod (AddBuilder);
+ EventBuilder.SetRemoveOnMethod (RemoveBuilder);
+
+ if (!TypeManager.RegisterEvent (EventBuilder, AddBuilder, RemoveBuilder)) {
+ Report.Error (111, Location,
+ "Class `" + parent.Name +
+ "' already contains a definition for the event `" +
+ Name + "'");
+ return false;
+ }
}
return true;
method = TypeManager.delegate_combine_delegate_delegate;
else
method = TypeManager.delegate_remove_delegate_delegate;
-
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldarg_0);
- ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
- ig.Emit (OpCodes.Ldarg_1);
- ig.Emit (OpCodes.Call, method);
- ig.Emit (OpCodes.Castclass, EventType);
- ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
+
+ if ((ModFlags & Modifiers.STATIC) != 0) {
+ ig.Emit (OpCodes.Ldsfld, (FieldInfo) FieldBuilder);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Call, method);
+ ig.Emit (OpCodes.Castclass, MemberType);
+ ig.Emit (OpCodes.Stsfld, (FieldInfo) FieldBuilder);
+ } else {
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldarg_0);
+ ig.Emit (OpCodes.Ldfld, (FieldInfo) FieldBuilder);
+ ig.Emit (OpCodes.Ldarg_1);
+ ig.Emit (OpCodes.Call, method);
+ ig.Emit (OpCodes.Castclass, MemberType);
+ ig.Emit (OpCodes.Stfld, (FieldInfo) FieldBuilder);
+ }
ig.Emit (OpCodes.Ret);
}
public void Emit (TypeContainer tc)
{
EmitContext ec;
- ILGenerator ig;
- ig = AddBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
+ ec = new EmitContext (tc, Location, null, MemberType, ModFlags);
+ Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
- if (Add != null) {
- Attribute.ApplyAttributes (ec, AddBuilder, Add, Add.OptAttributes, Location);
- ec.EmitTopBlock (Add.Block, Location);
- } else
+ if (Add != null)
+ AddData.Emit (tc, Add.Block, Add);
+ else {
+ ILGenerator ig = AddData.MethodBuilder.GetILGenerator ();
+ ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
EmitDefaultMethod (ec, true);
+ }
- ig = RemoveBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
-
- if (Remove != null) {
- Attribute.ApplyAttributes (ec, RemoveBuilder, Remove, Remove.OptAttributes, Location);
- ec.EmitTopBlock (Remove.Block, Location);
- } else
+ if (Remove != null)
+ RemoveData.Emit (tc, Remove.Block, Remove);
+ else {
+ ILGenerator ig = RemoveData.MethodBuilder.GetILGenerator ();
+ ec = new EmitContext (tc, Location, ig, TypeManager.void_type, ModFlags);
EmitDefaultMethod (ec, false);
-
- ec = new EmitContext (tc, Location, null, EventType, ModFlags);
- Attribute.ApplyAttributes (ec, EventBuilder, this, OptAttributes, Location);
-
+ }
}
}
//
// int this [ args ]
- public class Indexer : MemberCore {
+ public class Indexer : PropertyBase {
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.EXTERN |
Modifiers.ABSTRACT;
- public readonly Expression Type;
- public readonly string InterfaceType;
- public readonly Parameters FormalParameters;
- public readonly Accessor Get, Set;
- public Attributes OptAttributes;
- public MethodBuilder GetBuilder;
- public MethodBuilder SetBuilder;
- public PropertyBuilder PropertyBuilder;
- public Type IndexerType;
public string IndexerName;
public string InterfaceIndexerName;
+
+ //
+ // Are we implementing an interface ?
+ //
+ bool IsImplementing = false;
- EmitContext ec;
-
- public Indexer (Expression type, string int_type, int flags, Parameters parms,
+ public Indexer (Expression type, string int_type, int flags, Parameters parameters,
Accessor get_block, Accessor set_block, Attributes attrs, Location loc)
- : base ("", loc)
+ : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
+ attrs, loc)
{
-
- Type = type;
- InterfaceType = int_type;
- ModFlags = Modifiers.Check (AllowedModifiers, flags, Modifiers.PRIVATE, loc);
- FormalParameters = parms;
- Get = get_block;
- Set = set_block;
- OptAttributes = attrs;
+ ExplicitInterfaceName = int_type;
}
- bool DefineMethod (TypeContainer parent, Type explicit_iface_type,
- Type ret_type, string name,
- Type [] parameters, MethodAttributes attr, bool is_get)
- {
- MethodInfo implementing = null;
- bool is_implementation;
-
- if (parent.Pending != null){
- implementing = parent.Pending.IsInterfaceIndexer (
- explicit_iface_type, ret_type, parameters);
-
- if (implementing != null)
- InterfaceIndexerName = implementing.Name.Substring (4);
-
- if (explicit_iface_type != null && implementing == null){
- TypeContainer.Error_ExplicitInterfaceNotMemberInterface (Location, "this");
- return false;
- }
- }
-
- is_implementation = implementing != null;
-
- //
- // Setting null inside this block will trigger a more
- // verbose error reporting for missing interface implementations
- //
- // The "candidate" function has been flagged already
- // but it wont get cleared
- //
- if (implementing != null){
- if (explicit_iface_type == null){
- //
- // We already catch different accessibility settings
- // so we just need to check that we are not private
- //
- if ((ModFlags & Modifiers.PRIVATE) != 0)
- implementing = null;
-
- //
- // Static is not allowed
- //
- if ((ModFlags & Modifiers.STATIC) != 0)
- implementing = null;
- } else {
- if((ModFlags&(Modifiers.PUBLIC | Modifiers.ABSTRACT | Modifiers.VIRTUAL)) != 0){
- Modifiers.Error_InvalidModifier (Location, "public, virtual or abstract");
- implementing = null;
- }
- }
- }
-
- string meth_name = null;
- string prefix;
- if (explicit_iface_type == null)
- prefix = "";
- else
- prefix = explicit_iface_type.FullName + ".";
-
- if (implementing != null){
- //
- // When implementing interface methods, set NewSlot.
- //
- if (implementing.DeclaringType.IsInterface)
- attr |= MethodAttributes.NewSlot;
-
- attr |=
- MethodAttributes.Virtual |
- MethodAttributes.HideBySig;
-
- // Get the method name from the explicit interface.
- if (explicit_iface_type != null)
- meth_name = prefix + implementing.Name;
- }
-
- if (is_get){
- if (meth_name == null)
- meth_name = prefix + "get_" + IndexerName;
-
- GetBuilder = parent.TypeBuilder.DefineMethod (
- meth_name, attr, IndexerType, parameters);
-
- if (implementing != null) {
- parent.Pending.ImplementIndexer (
- explicit_iface_type, GetBuilder,
- ret_type, parameters, true);
-
- if (InterfaceType != null)
- parent.TypeBuilder.DefineMethodOverride (
- GetBuilder, implementing);
- }
- } else {
- if (meth_name == null)
- meth_name = prefix + "set_" + IndexerName;
-
- SetBuilder = parent.TypeBuilder.DefineMethod (
- meth_name, attr, null, parameters);
-
- if (implementing != null) {
- parent.Pending.ImplementIndexer (
- explicit_iface_type, SetBuilder,
- ret_type, parameters, true);
-
- if (InterfaceType != null)
- parent.TypeBuilder.DefineMethodOverride (
- SetBuilder, implementing);
- }
- }
-
- return is_implementation;
- }
-
public override bool Define (TypeContainer parent)
{
PropertyAttributes prop_attr =
PropertyAttributes.RTSpecialName |
PropertyAttributes.SpecialName;
- bool error = false;
- IndexerType = parent.ResolveType (Type, false, Location);
- Type [] parameters = FormalParameters.GetParameterInfo (parent);
-
- // Check if the return type and arguments were correct
- if (IndexerType == null || parameters == null)
- return false;
-
- if (!parent.MethodModifiersValid (ModFlags, InterfaceType == null ?
- "this" : InterfaceType, Location))
+ if (!DoDefine (parent))
return false;
- //
- // verify accessibility and unsafe pointers
- //
- if (!TypeContainer.AsAccessible (IndexerType, ModFlags))
- return false;
-
- if (IndexerType.IsPointer && !UnsafeOK (parent))
- return false;
-
- foreach (Type partype in parameters){
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- error = true;
- if (partype.IsPointer && !UnsafeOK (parent))
- error = true;
- }
-
- if (error)
- return false;
-
- Type explicit_iface_type = null;
-
- if (InterfaceType != null){
- explicit_iface_type = RootContext.LookupType (parent, InterfaceType, false, Location);
- if (explicit_iface_type == null)
- return false;
-
- if (!parent.VerifyImplements (explicit_iface_type, "this", "this", Location))
- return false;
- }
-
- ec = new EmitContext (parent, Location, null, IndexerType, ModFlags);
-
IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
if (IndexerName == null)
IndexerName = "Item";
- else if (explicit_iface_type != null)
+ else if (IsExplicitImpl)
Report.Error (592, Location,
"Attribute 'IndexerName' is not valid on this declaration " +
"type. It is valid on `property' declarations only.");
- if (explicit_iface_type != null)
- InterfaceIndexerName = TypeManager.IndexerPropertyName (explicit_iface_type);
- else
+ ShortName = IndexerName;
+ if (IsExplicitImpl) {
+ InterfaceIndexerName = TypeManager.IndexerPropertyName (InterfaceType);
+ Name = InterfaceType.FullName + "." + IndexerName;
+ } else {
InterfaceIndexerName = IndexerName;
+ Name = ShortName;
+ }
- MethodAttributes attr = Modifiers.MethodAttr (ModFlags);
+ if (!CheckBase (parent))
+ return false;
- bool is_implementing = false;
-
if (Get != null){
- is_implementing = DefineMethod (
- parent, explicit_iface_type, IndexerType, "get_" + IndexerName,
- parameters, attr, true);
- InternalParameters pi = new InternalParameters (parent, FormalParameters);
- if (!TypeManager.RegisterMethod (GetBuilder, pi, parameters)) {
- Report.Error (111, Location,
- "Class `" + parent.Name +
- "' already contains a definition with the " +
- "same return value and parameter types for the " +
- "'get' indexer");
+ InternalParameters ip = new InternalParameters (parent, Parameters);
+
+ GetData = new MethodData (this, "get", MemberType,
+ ParameterTypes, ip, CallingConventions.Standard,
+ Get.OptAttributes, ModFlags, flags, false);
+
+ if (!GetData.Define (parent))
return false;
- }
+
+ GetBuilder = GetData.MethodBuilder;
}
if (Set != null){
- int top = parameters.Length;
+ int top = ParameterTypes.Length;
Type [] set_pars = new Type [top + 1];
- parameters.CopyTo (set_pars, 0);
- set_pars [top] = IndexerType;
+ ParameterTypes.CopyTo (set_pars, 0);
+ set_pars [top] = MemberType;
- Parameter [] fixed_parms = FormalParameters.FixedParameters;
+ Parameter [] fixed_parms = Parameters.FixedParameters;
if (fixed_parms == null){
throw new Exception ("We currently do not support only array arguments in an indexer");
Parameters set_formal_params = new Parameters (tmp, null, Location);
- is_implementing = DefineMethod (
- parent, explicit_iface_type, TypeManager.void_type,
- "set_" + IndexerName, set_pars, attr, false);
-
InternalParameters ip = new InternalParameters (parent, set_formal_params);
-
- if (!TypeManager.RegisterMethod (SetBuilder, ip, set_pars)) {
- Report.Error (
- 111, Location,
- "Class `" + parent.Name + "' already contains a " +
- "definition with the " +
- "same return value and parameter types for the " +
- "'set' indexer");
+
+ SetData = new MethodData (this, "set", TypeManager.void_type,
+ set_pars, ip, CallingConventions.Standard,
+ Set.OptAttributes, ModFlags, flags, false);
+
+ if (!SetData.Define (parent))
return false;
- }
+
+ SetBuilder = SetData.MethodBuilder;
}
//
// Now name the parameters
//
- Parameter [] p = FormalParameters.FixedParameters;
+ Parameter [] p = Parameters.FixedParameters;
if (p != null) {
int i;
SetBuilder.DefineParameter (
i + 1, ParameterAttributes.None, "value");
- if (i != parameters.Length) {
- Parameter array_param = FormalParameters.ArrayParameter;
- SetBuilder.DefineParameter (i + 1, array_param.Attributes,
- array_param.Name);
+ if (i != ParameterTypes.Length) {
+ Parameter array_param = Parameters.ArrayParameter;
+ SetBuilder.DefineParameter (
+ i + 1, array_param.Attributes, array_param.Name);
}
}
+ if (GetData != null)
+ IsImplementing = GetData.IsImplementing;
+ else if (SetData != null)
+ IsImplementing = SetData.IsImplementing;
//
// Define the PropertyBuilder if one of the following conditions are met:
// b) the indexer has a different IndexerName and this is no
// explicit interface implementation.
//
- if (!is_implementing ||
- ((explicit_iface_type == null) && (IndexerName != InterfaceIndexerName))){
+ if (!IsExplicitImpl) {
PropertyBuilder = parent.TypeBuilder.DefineProperty (
- IndexerName, prop_attr, IndexerType, parameters);
+ IndexerName, prop_attr, MemberType, ParameterTypes);
- if (GetBuilder != null)
+ if (GetData != null)
PropertyBuilder.SetGetMethod (GetBuilder);
- if (SetBuilder != null)
+ if (SetData != null)
PropertyBuilder.SetSetMethod (SetBuilder);
- TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
+ TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
+ ParameterTypes);
}
return true;
}
-
- public void Emit (TypeContainer tc)
- {
- ILGenerator ig;
-
- //
- // The PropertyBuilder can be null for explicit implementations, in that
- // case, we do not actually emit the ".property", so there is nowhere to
- // put the attribute
- //
- if (PropertyBuilder != null)
- Attribute.ApplyAttributes (
- ec, PropertyBuilder, this, OptAttributes, Location);
- if (Get != null)
- Attribute.ApplyAttributes (ec, GetBuilder, Get, Get.OptAttributes, Location);
- if (Set != null)
- Attribute.ApplyAttributes (ec, SetBuilder, Set, Set.OptAttributes, Location);
-
- if ((ModFlags & (Modifiers.ABSTRACT | Modifiers.EXTERN)) != 0)
- return;
-
- if (Get != null){
- ig = GetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, IndexerType, ModFlags);
-
- ec.EmitTopBlock (Get.Block, Location);
- }
-
- if (Set != null){
- ig = SetBuilder.GetILGenerator ();
- ec = new EmitContext (tc, Location, ig, null, ModFlags);
-
- ec.EmitTopBlock (Set.Block, Location);
- }
- }
}
public class Operator : MemberCore {
OperatorMethod = new Method (ReturnType, ModFlags, MethodName,
new Parameters (param_list, null, Location),
OptAttributes, Mono.CSharp.Location.Null);
-
+
+ OperatorMethod.IsOperator = true;
OperatorMethod.Define (parent);
if (OperatorMethod.MethodBuilder == null)
OperatorMethodBuilder = OperatorMethod.MethodBuilder;
- Type [] param_types = OperatorMethod.ParameterTypes (parent);
+ Type [] param_types = OperatorMethod.ParameterTypes;
Type declaring_type = OperatorMethodBuilder.DeclaringType;
- Type return_type = OperatorMethod.GetReturnType (parent);
+ Type return_type = OperatorMethod.GetReturnType ();
Type first_arg_type = param_types [0];
// Rules for conversion operators
OperatorMethod.Block = Block;
OperatorMethod.Emit (parent);
}
+
+ public static string GetName (OpType ot)
+ {
+ switch (ot){
+ case OpType.LogicalNot:
+ return "!";
+ case OpType.OnesComplement:
+ return "~";
+ case OpType.Increment:
+ return "++";
+ case OpType.Decrement:
+ return "--";
+ case OpType.True:
+ return "true";
+ case OpType.False:
+ return "false";
+ case OpType.Addition:
+ return "+";
+ case OpType.Subtraction:
+ return "-";
+ case OpType.UnaryPlus:
+ return "+";
+ case OpType.UnaryNegation:
+ return "-";
+ case OpType.Multiply:
+ return "*";
+ case OpType.Division:
+ return "/";
+ case OpType.Modulus:
+ return "%";
+ case OpType.BitwiseAnd:
+ return "&";
+ case OpType.BitwiseOr:
+ return "|";
+ case OpType.ExclusiveOr:
+ return "^";
+ case OpType.LeftShift:
+ return "<<";
+ case OpType.RightShift:
+ return ">>";
+ case OpType.Equality:
+ return "==";
+ case OpType.Inequality:
+ return "!=";
+ case OpType.GreaterThan:
+ return ">";
+ case OpType.LessThan:
+ return "<";
+ case OpType.GreaterThanOrEqual:
+ return ">=";
+ case OpType.LessThanOrEqual:
+ return "<=";
+ case OpType.Implicit:
+ return "implicit";
+ case OpType.Explicit:
+ return "explicit";
+ default: return "";
+ }
+ }
+
+ public override string ToString ()
+ {
+ Type return_type = OperatorMethod.GetReturnType();
+ Type [] param_types = OperatorMethod.ParameterTypes;
+
+ if (SecondArgType == null)
+ return String.Format (
+ "{0} operator {1}({2})",
+ TypeManager.CSharpName (return_type),
+ GetName (OperatorType),
+ param_types [0]);
+ else
+ return String.Format (
+ "{0} operator {1}({2}, {3})",
+ TypeManager.CSharpName (return_type),
+ GetName (OperatorType),
+ param_types [0], param_types [1]);
+ }
}
//
/// from the current assembly and class
/// </summary>
public static MemberFilter inheritable_method_signature_filter;
+
+ /// <summary>
+ /// This delegate is used to extract inheritable methods which
+ /// have the same signature as the argument. By inheritable,
+ /// this means that we have permissions to override the method
+ /// from the current assembly and class
+ /// </summary>
+ public static MemberFilter inheritable_property_signature_filter;
static MethodSignature ()
{
method_signature_filter = new MemberFilter (MemberSignatureCompare);
inheritable_method_signature_filter = new MemberFilter (
InheritableMemberSignatureCompare);
+ inheritable_property_signature_filter = new MemberFilter (
+ InheritablePropertySignatureCompare);
}
public MethodSignature (string name, Type ret_type, Type [] parameters)
static bool MemberSignatureCompare (MemberInfo m, object filter_criteria)
{
- MethodInfo mi;
+ MethodSignature sig = (MethodSignature) filter_criteria;
- if (! (m is MethodInfo))
+ if (m.Name != sig.Name)
return false;
- MethodSignature sig = (MethodSignature) filter_criteria;
+ Type ReturnType;
+ MethodInfo mi = m as MethodInfo;
+ PropertyInfo pi = m as PropertyInfo;
- if (m.Name != sig.Name)
+ if (mi != null)
+ ReturnType = mi.ReturnType;
+ else if (pi != null)
+ ReturnType = pi.PropertyType;
+ else
return false;
- mi = (MethodInfo) m;
-
//
// we use sig.RetType == null to mean `do not check the
// method return value.
//
if (sig.RetType != null)
- if (mi.ReturnType != sig.RetType)
+ if (ReturnType != sig.RetType)
return false;
- Type [] args = TypeManager.GetArgumentTypes (mi);
+ Type [] args;
+ if (mi != null)
+ args = TypeManager.GetArgumentTypes (mi);
+ else
+ args = TypeManager.GetArgumentTypes (pi);
Type [] sigp = sig.Parameters;
if (args.Length != sigp.Length)
}
return false;
}
- }
+
+ //
+ // This filter should be used when we are requesting properties that
+ // we want to override.
+ //
+ // This makes a number of assumptions, for example
+ // that the methods being extracted are of a parent
+ // class (this means we know implicitly that we are
+ // being called to find out about members by a derived
+ // class).
+ //
+ static bool InheritablePropertySignatureCompare (MemberInfo m, object filter_criteria)
+ {
+ if (MemberSignatureCompare (m, filter_criteria)){
+ PropertyInfo pi = (PropertyInfo) m;
+
+ MethodInfo inherited_get = TypeManager.GetPropertyGetter (pi);
+ MethodInfo inherited_set = TypeManager.GetPropertySetter (pi);
+
+ MethodInfo mi = inherited_get == null ? inherited_set : inherited_get;
+
+ MethodAttributes prot = mi.Attributes & MethodAttributes.MemberAccessMask;
+
+ // If only accessible to the current class.
+ if (prot == MethodAttributes.Private)
+ return false;
+
+ // If only accessible to the defining assembly or
+ if (prot == MethodAttributes.FamANDAssem ||
+ prot == MethodAttributes.Assembly){
+ if (m.DeclaringType.Assembly == CodeGen.AssemblyBuilder)
+ return true;
+ else
+ return false;
+ }
+
+ // Anything else (FamOrAssembly and Public) is fine
+ return true;
+ }
+ return false;
+ }
+ }
}