+
//
// 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
//
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 (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
class_indexer_name = "Item";
IndexerName = class_indexer_name;
}
-
+
+ static void Report1530 (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
+ Report1530 (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);
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;
+ }
+
/// <summary>
/// This function is based by a delegate to the FindMembers routine
/// </summary>
//
// 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)
+ internal override MemberList FindMembers (MemberTypes mt, BindingFlags bf,
+ MemberFilter filter, object criteria)
{
ArrayList members = new ArrayList ();
bool priv = (bf & BindingFlags.NonPublic) != 0;
// 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;
+ return new MemberList (members);
}
- 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));
}
//
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");
}
+
+ public override MemberCache MemberCache {
+ get {
+ return null;
+ }
+ }
}
public class Class : TypeContainer {
return MemberType;
}
+ // Whether this is an operator method.
+ public bool IsOperator;
+
void DuplicateEntryPoint (MethodInfo b, Location location)
{
Report.Error (
if (!DoDefineParameters (parent))
return false;
+ 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 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.
// ptype is only null for System.Object while compiling corlib.
if (ptype != null){
- MethodSignature ms = new MethodSignature (Name, null, ParameterTypes);
- 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;
+ }
}
- parent_method = (MethodInfo) mi [0];
} else {
if ((ModFlags & Modifiers.NEW) != 0)
WarningNotHiding (parent);
if (!DoDefine (parent))
return false;
+ if (!CheckBase (parent))
+ return false;
+
CallingConventions cc = GetCallingConvention (parent is Class);
MethodData = new MethodData (this, null, MemberType, ParameterTypes,
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 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)
{
}
}
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);
//
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);
}
}
//
if ((modifiers & Modifiers.ABSTRACT) != 0)
Report.Error (
- 500, "Abstract method `" +
+ 500, Location, "Abstract method `" +
TypeManager.CSharpSignature (builder) +
"' can not have a body");
if ((modifiers & Modifiers.EXTERN) != 0)
Report.Error (
- 179, "External method `" +
+ 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
//
end.SymbolDocument,
end.Row, 0);
- ec.EmitTopBlock (block, Location);
+ ec.EmitTopBlock (block, ParameterInfo, Location);
sw.CloseMethod ();
} else
- ec.EmitTopBlock (block, Location);
+ ec.EmitTopBlock (block, ParameterInfo, Location);
}
}
ec.InTry = true;
ec.ReturnLabel = finish;
ec.HasReturnLabel = true;
- ec.EmitTopBlock (block, Location);
+ ec.EmitTopBlock (block, null, Location);
ec.InTry = old_in_try;
// ig.MarkLabel (finish);
bool error = false;
foreach (Type partype in parameters){
- if (!TypeContainer.AsAccessible (partype, ModFlags))
- error = true;
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;
return false;
// verify accessibility
- if (!TypeContainer.AsAccessible (MemberType, ModFlags))
+ 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;
- if (!CheckBase (parent))
- return false;
-
//
// Check for explicit interface implementation
//
// their common bits. This is also used to flag usage of the field
//
abstract public class FieldBase : MemberBase {
- public readonly Object Initializer;
public FieldBuilder FieldBuilder;
public Status status;
object init, Attributes attrs, Location loc)
: base (type, mod, allowed_mod, name, attrs, loc)
{
- Initializer = init;
+ 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;
}
}
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,
OptAttributes = attrs;
}
}
-
- public class Property : MemberBase {
+
+ //
+ // 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;
- 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;
+ protected EmitContext ec;
- public Property (Expression type, string name, int mod_flags,
- Accessor get_block, Accessor set_block,
- Attributes attrs, Location loc)
- : base (type, mod_flags, AllowedModifiers, name, attrs, loc)
+ 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)
{
Get = get_block;
Set = set_block;
}
+ 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
//
protected override bool CheckBase (TypeContainer parent)
{
+ // Check whether arguments were correct.
+ if (!DoDefineParameters (parent))
+ return false;
+
+ MethodSignature 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 `" + 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, ms);
+
+ MemberList props_instance = TypeContainer.FindMembers (
+ parent.TypeBuilder.BaseType, MemberTypes.Property,
+ BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance,
+ MethodSignature.inheritable_property_signature_filter,
+ 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 + "." + 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;
}
+ public void Emit (TypeContainer tc)
+ {
+ //
+ // 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 (GetData != null)
+ GetData.Emit (tc, Get.Block, Get);
+
+ if (SetData != null)
+ SetData.Emit (tc, Set.Block, Set);
+ }
+ }
+
+ 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;
+
+ 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)
{
if (!DoDefine (parent))
return false;
+ if (!CheckBase (parent))
+ return false;
+
flags |= MethodAttributes.HideBySig | MethodAttributes.SpecialName;
if (Get != null) {
Type [] parameters = TypeManager.NoTypes;
InternalParameters ip = new InternalParameters (
- parent, Parameters.GetEmptyReadOnlyParameters ());
+ parent, Parameters.EmptyReadOnlyParameters);
GetData = new MethodData (this, "get", MemberType,
parameters, ip, CallingConventions.Standard,
}
return true;
}
-
- public void Emit (TypeContainer tc)
- {
- EmitContext ec;
-
- ec = new EmitContext (tc, Location, null, MemberType, 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 (GetData != null)
- GetData.Emit (tc, Get.Block, Get);
-
- if (SetData != null)
- SetData.Emit (tc, Set.Block, Set);
- }
}
-
/// </summary>
/// Gigantic workaround for lameness in SRE follows :
/// This class derives from EventInfo and attempts to basically
InternalParameters ip = new InternalParameters (
parent, new Parameters (parms, null, Location));
+ if (!CheckBase (parent))
+ return false;
+
//
// Now define the accessors
//
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, MemberType);
- 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);
}
//
// int this [ args ]
- public class Indexer : MemberBase {
+ public class Indexer : PropertyBase {
const int AllowedModifiers =
Modifiers.NEW |
Modifiers.EXTERN |
Modifiers.ABSTRACT;
- public readonly Parameters FormalParameters;
- public readonly Accessor Get, Set;
- public MethodData GetData;
- public MethodData SetData;
- public MethodBuilder GetBuilder;
- public MethodBuilder SetBuilder;
- public PropertyBuilder PropertyBuilder;
public string IndexerName;
public string InterfaceIndexerName;
//
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 (type, flags, AllowedModifiers, "", attrs, loc)
+ : base (type, "", flags, AllowedModifiers, parameters, get_block, set_block,
+ attrs, loc)
{
ExplicitInterfaceName = int_type;
- FormalParameters = parms;
- Get = get_block;
- Set = set_block;
}
-
+
public override bool Define (TypeContainer parent)
{
PropertyAttributes prop_attr =
if (!DoDefine (parent))
return false;
- Type [] parameters = FormalParameters.GetParameterInfo (parent);
-
- // Check if the and arguments were correct
- if ((parameters == null) || !CheckParameters (parent, parameters))
- return false;
-
- ec = new EmitContext (parent, Location, null, MemberType, ModFlags);
-
IndexerName = Attribute.ScanForIndexerName (ec, OptAttributes);
if (IndexerName == null)
IndexerName = "Item";
Name = ShortName;
}
+ if (!CheckBase (parent))
+ return false;
+
if (Get != null){
- InternalParameters ip = new InternalParameters (parent, FormalParameters);
+ InternalParameters ip = new InternalParameters (parent, Parameters);
GetData = new MethodData (this, "get", MemberType,
- parameters, ip, CallingConventions.Standard,
+ ParameterTypes, ip, CallingConventions.Standard,
Get.OptAttributes, ModFlags, flags, false);
if (!GetData.Define (parent))
}
if (Set != null){
- int top = parameters.Length;
+ int top = ParameterTypes.Length;
Type [] set_pars = new Type [top + 1];
- parameters.CopyTo (set_pars, 0);
+ 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");
//
// 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;
+ if (i != ParameterTypes.Length) {
+ Parameter array_param = Parameters.ArrayParameter;
SetBuilder.DefineParameter (
i + 1, array_param.Attributes, array_param.Name);
}
// b) the indexer has a different IndexerName and this is no
// explicit interface implementation.
//
- if (!IsImplementing ||
- (!IsExplicitImpl && (IndexerName != InterfaceIndexerName))){
+ if (!IsExplicitImpl) {
PropertyBuilder = parent.TypeBuilder.DefineProperty (
- IndexerName, prop_attr, MemberType, parameters);
+ IndexerName, prop_attr, MemberType, ParameterTypes);
if (GetData != null)
PropertyBuilder.SetGetMethod (GetBuilder);
if (SetData != null)
PropertyBuilder.SetSetMethod (SetBuilder);
- TypeManager.RegisterProperty (PropertyBuilder, GetBuilder, SetBuilder);
+ TypeManager.RegisterIndexer (PropertyBuilder, GetBuilder, SetBuilder,
+ ParameterTypes);
}
return true;
}
-
- public void Emit (TypeContainer tc)
- {
- //
- // 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 (GetData != null)
- GetData.Emit (tc, Get.Block, Get);
-
- if (SetData != null)
- SetData.Emit (tc, Set.Block, Set);
- }
}
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)
/// 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;
+ }
+ }
}