+2004-11-15 Miguel de Icaza <miguel@ximian.com>
+
+ * anonymous.cs (AnonymousMethod.Error_AddressOfCapturedVar): New
+ routine that is used to report the use of a captured variable
+ whose address has been taken.
+
+ There are two checks: one when variables are being captured and
+ the other check is when the address of a variable is taken.
+
+ (because an anonymous methods might be resolved before *or* after
+ the address has been taken) and
+
+ * expression.cs (Conditional.DoResolve): Remove the special
+ casing that Martin added to trueExpr and falseExpr being both
+ NullLiteral. We get the right behavior now just by introducing
+ the null_type into the compiler.
+
+ * convert.cs (ExplicitConversion): Change the code to use
+ null_type instead of testing `expr is NullLiteral'.
+ (ImplicitConversionStandard): use null_type too.
+ (ImplicitReferenceConversionExists): use null_type too.
+ (ImplicitReferenceConversion): use null_type too.
+
+ * literal.cs: The type of `NullLiteral' is now null_type instead
+ of object_type.
+ (Resolve): Set the type here.
+
+ * typemanager.cs: Introduce null_type.
+
2004-11-17 Martin Baulig <martin@ximian.com>
* decl.cs (MemberCache.AddHashtable): Add entries in the opposite
+* Value Parameter
+
+ I believe that `Value Parameter' might have been introduced
+ after C# 1.0, also notice than in the treatment of Value Parameter
+ the parameters are defined in four categories:
+
+ Section 9.3 in the latest spec.
+
+
+* Review
+--------
+
+ Reference type equality operators (15.9.6) introduced
+ operator == (C x, C y) where C is a reference type.
+
+ Our compiler used:
+
+ operator == (object a, object b)
+
+ Review our implementation.
+
New
---
aec.EmitMeta (Block, amp);
aec.EmitResolvedTopBlock (Block, unreachable);
}
+
+ public static void Error_AddressOfCapturedVar (string name, Location loc)
+ {
+ Report.Error (1686, loc,
+ "Variable {0} is captured in an anonymous method and its address is also being taken: they are exclusive", name);
+ }
}
//
while (ttype.IsArray)
ttype = TypeManager.GetElementType (ttype);
- if (!TypeManager.IsBuiltinType (ttype) && (!ttype.IsSubclassOf (TypeManager.enum_type)) && !(Expr is NullLiteral)) {
+ if (!TypeManager.IsBuiltinType(ttype) && (!ttype.IsSubclassOf(TypeManager.enum_type)) && !(Expr is NullLiteral)){
Report.Error (
-3, Location,
"Constant type is not valid (only system types are allowed)");
bool fail;
// from the null type to any reference-type.
- if (expr is NullLiteral && !type.IsValueType && !TypeManager.IsEnumType (type))
+ if (expr.Type == TypeManager.null_type && !type.IsValueType && !TypeManager.IsEnumType (type))
return NullLiteral.Null;
if (!Convert.ImplicitStandardConversionExists (Convert.ConstantEC, expr, type)){
} else if (target_type == TypeManager.value_type) {
if (expr_type.IsValueType)
return new BoxedCast (expr);
- if (expr is NullLiteral)
+ if (expr_type == TypeManager.null_type)
return new NullCast (expr, target_type);
return null;
// Always ensure that the code here and there is in sync
// from the null type to any reference-type.
- if (expr is NullLiteral){
+ if (expr_type == TypeManager.null_type){
if (target_type.IsPointer)
return NullPointer.Null;
return true;
// from the null type to any reference-type.
- if (expr is NullLiteral && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
+ if (expr_type == TypeManager.null_type && !target_type.IsValueType && !TypeManager.IsEnumType (target_type))
return true;
return false;
}
}
- if (expr_type == target_type && !(expr is NullLiteral))
+ if (expr_type == target_type && expr_type != TypeManager.null_type)
return expr;
e = ImplicitNumericConversion (ec, expr, target_type, loc);
}
if (target_type.IsPointer) {
- if (expr is NullLiteral)
+ if (expr_type == TypeManager.null_type)
return new EmptyCast (expr, target_type);
if (expr_type == TypeManager.void_ptr_type)
//
// Unboxing conversion.
//
- if (expr_type == TypeManager.object_type && target_type.IsValueType){
- if (expr is NullLiteral){
- //
- // Skip the ExplicitReferenceConversion because we can not convert
- // from Null to a ValueType, and ExplicitReference wont check against
- // null literal explicitly
- //
- goto skip_explicit;
- }
+ if (expr_type == TypeManager.object_type && target_type.IsValueType)
return new UnboxCast (expr, target_type);
+ //
+ // Skip the ExplicitReferenceConversion because we can not convert
+ // from Null to a ValueType, and ExplicitReference wont check against
+ // null literal explicitly
+ //
+ if (expr_type != TypeManager.null_type){
+ ne = ExplicitReferenceConversion (expr, target_type);
+ if (ne != null)
+ return ne;
}
- ne = ExplicitReferenceConversion (expr, target_type);
- if (ne != null)
- return ne;
-
skip_explicit:
if (ec.InUnsafe){
if (target_type.IsPointer){
"of a fixed statement initializer");
return null;
}
-
+
if (ec.InFixedInitializer && ((variable != null) && variable.VerifyFixed (false))) {
Error (213, "You can not fix an already fixed expression");
return null;
}
+ LocalVariableReference lr = Expr as LocalVariableReference;
+ if (lr != null){
+ if (lr.local_info.IsCaptured){
+ AnonymousMethod.Error_AddressOfCapturedVar (lr.Name, loc);
+ return null;
+ }
+ lr.local_info.AddressTaken = true;
+ }
+
// According to the specs, a variable is considered definitely assigned if you take
// its address.
- if ((variable != null) && (variable.VariableInfo != null))
+ if ((variable != null) && (variable.VariableInfo != null)){
variable.VariableInfo.SetAssigned (ec);
+ }
type = TypeManager.GetPointerType (Expr.Type);
return this;
// Special cases: string comapred to null
//
if (oper == Operator.Equality || oper == Operator.Inequality){
- if ((!TypeManager.IsValueType (l) && (right is NullLiteral)) ||
- (!TypeManager.IsValueType (r) && (left is NullLiteral))) {
+ if ((!TypeManager.IsValueType (l) && r == TypeManager.null_type) ||
+ (!TypeManager.IsValueType (r) && l == TypeManager.null_type)) {
Type = TypeManager.bool_type;
return this;
if (trueExpr == null || falseExpr == null)
return null;
- if ((trueExpr is NullLiteral) && (falseExpr is NullLiteral))
- return trueExpr;
-
eclass = ExprClass.Value;
if (trueExpr.Type == falseExpr.Type)
type = trueExpr.Type;
// flag it for capturing
//
if (local_info.Block.Toplevel != ec.CurrentBlock.Toplevel){
+ if (local_info.AddressTaken){
+ AnonymousMethod.Error_AddressOfCapturedVar (local_info.Name, loc);
+ return null;
+ }
ec.CaptureVariable (local_info);
- //Console.WriteLine ("Capturing at " + loc);
}
}
// * There is no implicit conversion from type 'object' to other reference types
// => Conversion of 'null' to a reference type is better than conversion to 'object'
//
- // FIXME: This probably isn't necessary, since the type of a NullLiteral is 'System.Null'.
- // I think it used to be 'object' and thus needed a special case to avoid the
- // immediately following two checks.
+ // FIXME: This probably isn't necessary, since the type of a NullLiteral is the
+ // null type. I think it used to be 'object' and thus needed a special
+ // case to avoid the immediately following two checks.
//
if (!p.IsValueType && q == TypeManager.object_type)
return p;
namespace Mono.CSharp {
+ //
+ // The NullType just exists to compare type equality, and for
+ // expressions that might have the `null type'
+ //
+ public class NullType {
+ }
+
+ //
+ // The null Literal constant
+ //
public class NullLiteral : Constant {
public static readonly NullLiteral Null;
public override Expression DoResolve (EmitContext ec)
{
- type = typeof (System.Null);
+ type = TypeManager.null_type;
return this;
}
}
}
- static void Msgtry (string s)
+ static void MsgtryRef (string s)
{
Console.WriteLine (" Try using -r:" + s);
}
+
+ static void MsgtryPkg (string s)
+ {
+ Console.WriteLine (" Try using -pkg:" + s);
+ }
protected void error246 (Location loc, string name)
{
switch (name){
case "Gtk": case "GtkSharp":
- Msgtry ("gtk-sharp");
+ MsgtryPkg ("gtk-sharp");
break;
case "Gdk": case "GdkSharp":
- Msgtry ("gdk-sharp");
+ MsgtryPkg ("gdk-sharp");
break;
case "Glade": case "GladeSharp":
- Msgtry ("glade-sharp");
+ MsgtryPkg ("glade-sharp");
break;
case "System.Drawing":
- Msgtry ("System.Drawing");
+ MsgtryRef ("System.Drawing");
break;
case "System.Web.Services":
- Msgtry ("System.Web.Services");
+ MsgtryRef ("System.Web.Services");
break;
case "System.Web":
- Msgtry ("System.Web");
+ MsgtryRef ("System.Web");
break;
case "System.Data":
- Msgtry ("System.Data");
+ MsgtryRef ("System.Data");
break;
case "System.Windows.Forms":
- Msgtry ("System.Windows.Forms");
+ MsgtryRef ("System.Windows.Forms");
break;
}
}
ReadOnly = 2,
Pinned = 4,
IsThis = 8,
- Captured = 16
+ Captured = 16,
+ AddressTaken = 32
}
Flags flags;
}
}
+ public bool AddressTaken {
+ get {
+ return (flags & Flags.AddressTaken) != 0;
+ }
+
+ set {
+ flags |= Flags.AddressTaken;
+ }
+ }
+
public override string ToString ()
{
return String.Format ("LocalInfo ({0},{1},{2},{3})",
static public Type delegate_type;
static public Type multicast_delegate_type;
static public Type void_type;
+ static public Type null_type;
static public Type enumeration_type;
static public Type array_type;
static public Type runtime_handle_type;
// These are only used for compare purposes
//
anonymous_method_type = typeof (AnonymousMethod);
+ null_type = typeof (NullType);
}
//