Hi,
Carlos Alberto Cortez <[EMAIL PROTECTED]> writes:
The attached patch implements friend access for class members (methods,
properties, fields).
I'm not including the type-check section, since that part will be
modified (next merge to gmcs) and I'm waiting for that to happen.
However, that change should be small (I will send the patch).
I have completed the merge of the relevant parts. Please post an
updated patch.
Meanwhile, I have some comments:
[snip]
@@ -2646,25 +2726,38 @@
MethodBase mb = (MethodBase) m;
MethodAttributes ma = mb.Attributes &
MethodAttributes.MemberAccessMask;
+ if (ma == MethodAttributes.Public)
+ return true;
Ok.
if (ma == MethodAttributes.Private)
return private_ok ||
IsPrivateAccessible
(invocation_type, m.DeclaringType) ||
IsNestedChildOf
(invocation_type, m.DeclaringType);
- if (invocation_assembly ==
mb.DeclaringType.Assembly) {
+ if (invocation_assembly ==
mb.DeclaringType.Assembly)
if (ma == MethodAttributes.Assembly ||
ma == MethodAttributes.FamORAssem)
return true;
- } else {
- if (ma == MethodAttributes.Assembly ||
ma == MethodAttributes.FamANDAssem)
- return false;
I would retain the old code, and change the check to:
if (invocation_assembly == mb.DeclaringType.Assembly ||
TypeManager.InternalsVisibleTo (invocation_assembly, mb.DeclaringType.Assembly))
+
+ if (ma == MethodAttributes.Family ||
+ ma == MethodAttributes.FamANDAssem ||
+ ma == MethodAttributes.FamORAssem) {
+ if (!CheckValidFamilyAccess
(mb.IsStatic, m)) {
+ if (ma ==
MethodAttributes.Family || ma == MethodAttributes.FamANDAssem)
+ return false;
+ } else {
+ // We are valid
+ if (ma ==
MethodAttributes.Family || ma == MethodAttributes.FamORAssem)
+ return true;
+
+ // Check for FamANDAssem
+ if (invocation_assembly ==
mb.DeclaringType.Assembly)
+ return true;
+ }
}
- if (ma == MethodAttributes.Family ||
- ma == MethodAttributes.FamANDAssem ||
- ma == MethodAttributes.FamORAssem)
- return CheckValidFamilyAccess
(mb.IsStatic, m);
I don't like this too much. I'd much rather keep the old code.
- Hari
------------------------------------------------------------------------
Index: typemanager.cs
===================================================================
--- typemanager.cs (revisión: 52315)
+++ typemanager.cs (copia de trabajo)
@@ -252,6 +252,8 @@
static Hashtable fieldbuilders_to_fields;
static Hashtable fields;
+ static PtrHashtable assembly_internals_vis_attrs;
+
struct Signature {
public string name;
public Type [] args;
@@ -274,6 +276,8 @@
priv_fields_events = null;
type_hash = null;
+
+ assembly_internals_vis_attrs = null;
CleanUpGenerics ();
TypeHandle.CleanUp ();
@@ -375,6 +379,8 @@
fieldbuilders_to_fields = new Hashtable ();
fields = new Hashtable ();
type_hash = new DoubleHash ();
+
+ assembly_internals_vis_attrs = new PtrHashtable ();
InitGenerics ();
}
@@ -1654,6 +1660,80 @@
return false;
}
+ //
+ // Checks whether `extern_type' is friend of the output assembly
+ //
+ public static bool IsFriendAssembly (Assembly assembly)
+ {
+ if (assembly_internals_vis_attrs.Contains (assembly))
+ return (bool)(assembly_internals_vis_attrs [assembly]);
+
+ object [] attrs = assembly.GetCustomAttributes
(internals_visible_attr_type, false);
+ if (attrs.Length == 0) {
+ AddFriendAssembly (assembly, false);
+ return false;
+ }
+
+ AssemblyName this_name = CodeGen.Assembly.Name;
+ byte [] this_token = this_name.GetPublicKeyToken ();
+ bool is_friend = false;
+ foreach (object o in attrs) {
+ InternalsVisibleToAttribute attr = o as
InternalsVisibleToAttribute;
+ if (attr.AssemblyName == null ||
attr.AssemblyName.Length == 0)
+ continue;
+
+ AssemblyName aname = null;
+ try {
+ aname = new AssemblyName (attr.AssemblyName);
+ } catch (FileLoadException) {
+ } catch (ArgumentException) {
+ }
+
+ if (aname == null || aname.Name != this_name.Name)
+ continue;
+
+ byte [] key_token = aname.GetPublicKeyToken ();
+ if (key_token != null) {
+ if (this_token == null) {
+ // Same name, but key token is null
+ Error_FriendAccessNameNotMatching
(aname.FullName);
+ break;
+ }
+
+ if (!CompareKeyTokens (this_token, key_token))
+ continue;
+ }
+
+ is_friend = true;
+ break;
+ }
+
+ AddFriendAssembly (assembly, is_friend);
+ return is_friend;
+ }
+
+ static bool CompareKeyTokens (byte [] token1, byte [] token2)
+ {
+ for (int i = 0; i < token1.Length; i++)
+ if (token1 [i] != token2 [i])
+ return false;
+
+ return true;
+ }
+
+ static string this_fullname;
+
+ static void Error_FriendAccessNameNotMatching (string other_name)
+ {
+ if (this_fullname == null)
+ this_fullname = CodeGen.Assembly.Name.FullName;
+
+ Report.Error (281, "Friend access was granted to `" + other_name +
+ "', but the output assembly is named `" + this_fullname +
+ "'. Try adding a reference to `" + other_name +
+ "' or change the output assembly name to match it.");
+ }
+
//
// Do the right thing when returning the element type of an
// array type based on whether we are compiling corlib or not
@@ -2478,12 +2558,16 @@
MethodBase mb = (MethodBase) m;
MethodAttributes ma = mb.Attributes &
MethodAttributes.MemberAccessMask;
+ if (ma == MethodAttributes.Public)
+ return true;
+
if (ma == MethodAttributes.Private)
return private_ok ||
IsPrivateAccessible
(invocation_type, m.DeclaringType) ||
IsNestedChildOf
(invocation_type, m.DeclaringType);
- if (invocation_assembly ==
mb.DeclaringType.Assembly) {
+ if (invocation_assembly ==
mb.DeclaringType.Assembly ||
+ TypeManager.IsFriendAssembly
(mb.DeclaringType.Assembly)) {
if (ma == MethodAttributes.Assembly ||
ma == MethodAttributes.FamORAssem)
return true;
} else {
@@ -2491,25 +2575,24 @@
return false;
}
- if (ma == MethodAttributes.Family ||
- ma == MethodAttributes.FamANDAssem ||
- ma == MethodAttributes.FamORAssem)
- return CheckValidFamilyAccess
(mb.IsStatic, m);
-
- // Public.
- return true;
+ // Family, FamORAssem or FamANDAssem
+ return CheckValidFamilyAccess (mb.IsStatic, m);
}
if (m is FieldInfo){
FieldInfo fi = (FieldInfo) m;
FieldAttributes fa = fi.Attributes &
FieldAttributes.FieldAccessMask;
+ if (fa == FieldAttributes.Public)
+ return true;
+
if (fa == FieldAttributes.Private)
return private_ok ||
IsPrivateAccessible
(invocation_type, m.DeclaringType) ||
IsNestedChildOf
(invocation_type, m.DeclaringType);
- if (invocation_assembly ==
fi.DeclaringType.Assembly) {
+ if (invocation_assembly ==
fi.DeclaringType.Assembly ||
+ TypeManager.IsFriendAssembly
(fi.DeclaringType.Assembly)) {
if (fa == FieldAttributes.Assembly ||
fa == FieldAttributes.FamORAssem)
return true;
} else {
@@ -2517,13 +2600,8 @@
return false;
}
- if (fa == FieldAttributes.Family ||
- fa == FieldAttributes.FamANDAssem ||
- fa == FieldAttributes.FamORAssem)
- return CheckValidFamilyAccess
(fi.IsStatic, m);
-
- // Public.
- return true;
+ // Family, FamORAssem or FamANDAssem
+ return CheckValidFamilyAccess (fi.IsStatic, m);
}
//
@@ -2784,6 +2862,11 @@
}
return false;
}
+
+ static void AddFriendAssembly (Assembly assembly, bool is_friend)
+ {
+ assembly_internals_vis_attrs.Add (assembly, is_friend);
+ }
#endregion
Index: namespace.cs
===================================================================
--- namespace.cs (revisión: 52314)
+++ namespace.cs (copia de trabajo)
@@ -112,12 +112,17 @@
if (t.IsPointer)
throw new InternalErrorException ("Use
GetPointerType() to get a pointer");
+
TypeAttributes ta = t.Attributes &
TypeAttributes.VisibilityMask;
+ if (ta == TypeAttributes.NestedPrivate)
+ return null;
+
if (ta == TypeAttributes.NotPublic ||
- ta == TypeAttributes.NestedPrivate ||
- ta == TypeAttributes.NestedAssembly ||
- ta == TypeAttributes.NestedFamANDAssem)
- return null;
+ ta == TypeAttributes.NestedAssembly ||
+ /*ta == TypeAttributes.NestedFamORAssem
||*/
+ ta == TypeAttributes.NestedFamANDAssem)
+ if (!TypeManager.IsFriendAssembly (t.Assembly))
+ return null;
return t;
}
Index: ecore.cs
===================================================================
--- ecore.cs (revisión: 52315)
+++ ecore.cs (copia de trabajo)
@@ -156,6 +156,9 @@
must_do_cs1540_check = false; // by default we do not
check for this
+ if (ma == MethodAttributes.Public)
+ return true;
+
//
// If only accessible to the current class or children
//
@@ -163,7 +166,8 @@
return TypeManager.IsPrivateAccessible
(invocation_type, mi.DeclaringType) ||
TypeManager.IsNestedChildOf
(invocation_type, mi.DeclaringType);
- if (mi.DeclaringType.Assembly ==
invocation_type.Assembly) {
+ if (mi.DeclaringType.Assembly ==
invocation_type.Assembly ||
+ TypeManager.IsFriendAssembly
(mi.DeclaringType.Assembly)) {
if (ma == MethodAttributes.Assembly || ma ==
MethodAttributes.FamORAssem)
return true;
} else {
@@ -173,18 +177,12 @@
// Family and FamANDAssem require that we derive.
// FamORAssem requires that we derive if in different
assemblies.
- if (ma == MethodAttributes.Family ||
- ma == MethodAttributes.FamANDAssem ||
- ma == MethodAttributes.FamORAssem) {
- if (!TypeManager.IsNestedFamilyAccessible
(invocation_type, mi.DeclaringType))
- return false;
+ if (!TypeManager.IsNestedFamilyAccessible
(invocation_type, mi.DeclaringType))
+ return false;
- if (!TypeManager.IsNestedChildOf
(invocation_type, mi.DeclaringType))
- must_do_cs1540_check = true;
+ if (!TypeManager.IsNestedChildOf (invocation_type,
mi.DeclaringType))
+ must_do_cs1540_check = true;
- return true;
- }
-
return true;
}
Index: decl.cs
===================================================================
--- decl.cs (revisión: 52314)
+++ decl.cs (copia de trabajo)
@@ -925,7 +925,8 @@
//
// This test should probably use the
declaringtype.
//
- return check_type.Assembly ==
TypeBuilder.Assembly;
+ return check_type.Assembly ==
TypeBuilder.Assembly ||
+ TypeManager.IsFriendAssembly
(check_type.Assembly);
case TypeAttributes.NestedPublic:
return true;
@@ -940,15 +941,18 @@
return FamilyAccessible (tb, check_type);
case TypeAttributes.NestedFamANDAssem:
- return (check_type.Assembly == tb.Assembly) &&
+ return ((check_type.Assembly == tb.Assembly) ||
+ TypeManager.IsFriendAssembly (check_type.Assembly)) &&
FamilyAccessible (tb, check_type);
case TypeAttributes.NestedFamORAssem:
return (check_type.Assembly == tb.Assembly) ||
- FamilyAccessible (tb, check_type);
+ FamilyAccessible (tb, check_type) ||
+ TypeManager.IsFriendAssembly
(check_type.Assembly);
case TypeAttributes.NestedAssembly:
- return check_type.Assembly == tb.Assembly;
+ return check_type.Assembly == tb.Assembly ||
+ TypeManager.IsFriendAssembly
(check_type.Assembly);
}
Console.WriteLine ("HERE: " + check_attr);
------------------------------------------------------------------------
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list