"' because it is sealed.");
ok = false;
}
-
//
// Check that the permissions are not being changed
//
MethodAttributes thisp = my_attrs & MethodAttributes.MemberAccessMask;
MethodAttributes parentp = mb.Attributes & MethodAttributes.MemberAccessMask;
- if (thisp != parentp){
- Error_CannotChangeAccessModifiers (parent, mb, name);
- ok = false;
+ //
+ // special case for "protected internal"
+ //
+
+ if ((parentp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+ //
+ // when overriding protected internal, the method can be declared
+ // protected internal only within the same assembly
+ //
+
+ if ((thisp & MethodAttributes.FamORAssem) == MethodAttributes.FamORAssem){
+ if (parent.TypeBuilder.Assembly != mb.DeclaringType.Assembly){
+ //
+ // assemblies differ - report an error
+ //
+
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ } else if (thisp != parentp) {
+ //
+ // same assembly, but other attributes differ - report an error
+ //
+
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ };
+ } else if ((thisp & MethodAttributes.Family) != MethodAttributes.Family) {
+ //
+ // if it's not "protected internal", it must be "protected"
+ //
+
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ } else if (parent.TypeBuilder.Assembly == mb.DeclaringType.Assembly) {
+ //
+ // protected within the same assembly - an error
+ //
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ } else if ((thisp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem)) !=
+ (parentp & ~(MethodAttributes.Family | MethodAttributes.FamORAssem))) {
+ //
+ // protected ok, but other attributes differ - report an error
+ //
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ }
+ } else {
+ if (thisp != parentp){
+ Error_CannotChangeAccessModifiers (parent, mb, name);
+ ok = false;
+ }
}
}
/// Returns a status code based purely on the name
/// of the member being added
/// </summary>
- protected AdditionResult IsValid (string name)
+ protected AdditionResult IsValid (string basename, string name)
{
- if (name == Basename)
+ if (basename == Basename)
return AdditionResult.EnclosingClash;
if (defined_names.Contains (name))
return AdditionResult.Success;
}
+ public static int length;
+ public static int small;
+
/// <summary>
/// Introduce @name into this declaration space and
/// associates it with the object @o. Note that for
protected void DefineName (string name, object o)
{
defined_names.Add (name, o);
+
+#if DEBUGME
+ int p = name.LastIndexOf (".");
+ int l = name.Length;
+ length += l;
+ small += l -p;
+#endif
}
/// <summary>
public static string MakeFQN (string nsn, string name)
{
- string prefix = (nsn == "" ? "" : nsn + ".");
-
- return prefix + name;
+ if (nsn == "")
+ return name;
+ return String.Concat (nsn, ".", name);
}
EmitContext type_resolve_ec;
if (type_resolve_ec == null)
type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
type_resolve_ec.loc = loc;
+ type_resolve_ec.ContainerType = TypeBuilder;
int errors = Report.Errors;
- Expression d = e.Resolve (type_resolve_ec, ResolveFlags.Type);
+ Expression d = e.ResolveAsTypeTerminal (type_resolve_ec);
+
if (d == null || d.eclass != ExprClass.Type){
if (!silent && errors == Report.Errors){
Report.Error (246, loc, "Cannot find type `"+ e.ToString () +"'");
return null;
}
+ if (!CheckAccessLevel (d.Type)) {
+ Report. Error (122, loc, "`" + d.Type + "' " +
+ "is inaccessible because of its protection level");
+ return null;
+ }
+
return d.Type;
}
{
if (type_resolve_ec == null)
type_resolve_ec = GetTypeResolveEmitContext (parent, loc);
+ type_resolve_ec.loc = loc;
+ type_resolve_ec.ContainerType = TypeBuilder;
- Expression d = e.Resolve (type_resolve_ec, ResolveFlags.Type);
+ Expression d = e.ResolveAsTypeTerminal (type_resolve_ec);
+
if (d == null || d.eclass != ExprClass.Type){
if (!silent){
Report.Error (246, loc, "Cannot find type `"+ e +"'");
return d;
}
+ public bool CheckAccessLevel (Type check_type)
+ {
+ if (check_type == TypeBuilder)
+ return true;
+
+ TypeAttributes check_attr = check_type.Attributes & TypeAttributes.VisibilityMask;
+
+ //
+ // Broken Microsoft runtime, return public for arrays, no matter what
+ // the accessibility is for their underlying class, and they return
+ // NonPublic visibility for pointers
+ //
+ if (check_type.IsArray || check_type.IsPointer)
+ return CheckAccessLevel (check_type.GetElementType ());
+
+ if (check_attr == TypeAttributes.Public)
+ return true;
+
+ if (check_attr == TypeAttributes.NestedPublic)
+ return true;
+
+ if (check_attr == TypeAttributes.NestedPrivate){
+ string check_type_name = check_type.FullName;
+ string type_name = TypeBuilder.FullName;
+
+ int cio = check_type_name.LastIndexOf ("+");
+ string container = check_type_name.Substring (0, cio);
+
+ //
+ // Check if the check_type is a nested class of the current type
+ //
+ if (check_type_name.StartsWith (type_name + "+")){
+ return true;
+ }
+
+ if (type_name.StartsWith (container)){
+ return true;
+ }
+
+ return false;
+ }
+
+ if (check_type.Assembly == TypeBuilder.Assembly){
+ return true;
+ }
+
+ return false;
+
+ }
+
+
Type LookupInterfaceOrClass (string ns, string name, out bool error)
{
DeclSpace parent;
Type t;
error = false;
+
name = MakeFQN (ns, name);
-
+
t = TypeManager.LookupType (name);
if (t != null)
return t;
while (current_type != null) {
string pre = current_type.FullName;
-
+
t = LookupInterfaceOrClass (pre, name, out error);
if (error)
return null;
// Attempt to lookup the class on our namespace and all it's implicit parents
//
for (string ns = Namespace.Name; ns != null; ns = RootContext.ImplicitParent (ns)) {
-
t = LookupInterfaceOrClass (ns, name, out error);
if (error)
return null;
}
t = match;
- ue.Used = true;
}
}
if (t != null)
/// </summary>
void AddMethods (Type type)
{
- AddMethods (BindingFlags.Static | BindingFlags.Public, type);
- AddMethods (BindingFlags.Static | BindingFlags.NonPublic, type);
+ AddMethods (BindingFlags.Static | BindingFlags.Public |
+ BindingFlags.FlattenHierarchy, type);
+ AddMethods (BindingFlags.Static | BindingFlags.NonPublic |
+ BindingFlags.FlattenHierarchy, type);
AddMethods (BindingFlags.Instance | BindingFlags.Public, type);
AddMethods (BindingFlags.Instance | BindingFlags.NonPublic, type);
}
// If this is a method-only search, we try to use the method cache if
// possible; a lookup in the method cache will return a MemberInfo with
// the correct ReflectedType for inherited methods.
+
if (method_search && (method_hash != null))
applicable = (ArrayList) method_hash [name];
else
applicable = (ArrayList) member_hash [name];
-
+
if (applicable == null)
return MemberList.Empty;
// search, we restart in method-only search mode if the first match is
// a method. This ensures that we return a MemberInfo with the correct
// ReflectedType for inherited methods.
- if (do_method_search && (list.Count > 0))
+ if (do_method_search && (list.Count > 0)){
return FindMembers (MemberTypes.Method, bf, name, filter, criteria);
+ }
return new MemberList (list);
}