I forgot to attach the patch ;-)

Carlos.


El vie, 28-10-2005 a las 16:23 +0530, Raja R Harinath escribió:
> 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);

Attachment: friend-test.tar.gz
Description: application/compressed-tar

_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to