Author: raja
Date: 2005-05-26 09:55:43 -0400 (Thu, 26 May 2005)
New Revision: 45046
Added:
trunk/mcs/errors/cs0173-3.cs
trunk/mcs/tests/test-387.cs
Removed:
trunk/mcs/errors/cs0172-2.cs
Modified:
trunk/mcs/errors/ChangeLog
trunk/mcs/errors/known-issues-gmcs
trunk/mcs/mcs/ChangeLog
trunk/mcs/mcs/convert.cs
trunk/mcs/mcs/expression.cs
trunk/mcs/tests/ChangeLog
trunk/mcs/tests/Makefile
Log:
In mcs:
Improve user-defined conversion handling.
* convert.cs (GetConversionOperators): Rewrite. Return only the
applicable operators.
(AddConversionOperators): New. Helper for GetConversionOperators.
(FindMostEncompassedType, FindMostEncompassingType): Verify that
there is only one most encompassed/encompassing type.
(FindMostSpecificSource, FindMostSpecificTarget): Remove
"applicable operator" handling.
(UserConversion): Move cache here from GetConversionOperators.
Directly cache the chosen operator, rather than the whole
MethodGroup.
(ExplicitNumericConversion): Fix buggy implementation of Decimal
case. Allow conversion of decimal to sbyte and byte too.
* expression.cs (EmptyExpression.Grab, EmptyExpression.Release):
New static methods. Used to avoid allocating EmptyExpressions in
convert.cs.
In errors:
* cs0173-3.cs: Rename from cs0172-2.cs. CSC 1.1 reports CS0173,
CSC 2.0.40607 reports CS0172. CS0173 is somewhat more appropriate
since the conversion is ambiguous.
In tests:
* test-387.cs: New test from #54928.
Modified: trunk/mcs/errors/ChangeLog
===================================================================
--- trunk/mcs/errors/ChangeLog 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/errors/ChangeLog 2005-05-26 13:55:43 UTC (rev 45046)
@@ -1,3 +1,9 @@
+2005-05-26 Raja R Harinath <[EMAIL PROTECTED]>
+
+ * cs0173-3.cs: Rename from cs0172-2.cs. CSC 1.1 reports CS0173,
+ CSC 2.0.40607 reports CS0172. CS0173 is somewhat more appropriate
+ since the conversion is ambiguous.
+
2005-05-20 Martin Baulig <[EMAIL PROTECTED]>
* mcs-known-issues, gmcs-known-issues: Updated.
Deleted: trunk/mcs/errors/cs0172-2.cs
===================================================================
--- trunk/mcs/errors/cs0172-2.cs 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/errors/cs0172-2.cs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -1,31 +0,0 @@
-// cs0172.cs: Type of conditional expression can't be determined because there
is no implicit conversion between 'ClassA' and 'ClassB'
-// Line: 29
-
-class ClassA {
- public static implicit operator ClassB (ClassA value) {
- return null;
- }
-
- public static implicit operator ClassA (ClassB value) {
- return null;
- }
-}
-
-class ClassB {
- public static implicit operator ClassA (ClassB value) {
- return null;
- }
-
- public static implicit operator ClassB (ClassA value) {
- return null;
- }
-}
-
-public class MainClass {
- public static void Main() {
- ClassA a = new ClassA();
- ClassB b = new ClassB();
-
- System.Console.WriteLine(true ? a : b);
- }
-}
Copied: trunk/mcs/errors/cs0173-3.cs (from rev 45033,
trunk/mcs/errors/cs0172-2.cs)
===================================================================
--- trunk/mcs/errors/cs0172-2.cs 2005-05-26 07:08:43 UTC (rev 45033)
+++ trunk/mcs/errors/cs0173-3.cs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -0,0 +1,31 @@
+// cs0173.cs: Type of conditional expression can't be determined because there
is no implicit conversion between 'ClassA' and 'ClassB'
+// Line: 29
+
+class ClassA {
+ public static implicit operator ClassB (ClassA value) {
+ return null;
+ }
+
+ public static implicit operator ClassA (ClassB value) {
+ return null;
+ }
+}
+
+class ClassB {
+ public static implicit operator ClassA (ClassB value) {
+ return null;
+ }
+
+ public static implicit operator ClassB (ClassA value) {
+ return null;
+ }
+}
+
+public class MainClass {
+ public static void Main() {
+ ClassA a = new ClassA();
+ ClassB b = new ClassB();
+
+ System.Console.WriteLine(true ? a : b);
+ }
+}
Modified: trunk/mcs/errors/known-issues-gmcs
===================================================================
--- trunk/mcs/errors/known-issues-gmcs 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/errors/known-issues-gmcs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -15,6 +15,7 @@
cs0119.cs
cs0121-3.cs NO ERROR
cs0122-12.cs
+cs0173-3.cs
cs0201.cs
cs0202.cs # new in GMCS
cs0229.cs NO ERROR
@@ -47,11 +48,9 @@
cs1518.cs
cs1525.cs
cs1528.cs
-cs1535.cs # new in GMCS; grammar issue
cs1540-2.cs # new in GMCS
cs1540-3.cs NO ERROR # new in GMCS
cs1540-5.cs NO ERROR # new in GMCS
-cs1552.cs # new in GMCS; grammar issue
cs1586.cs
cs1638.cs NO ERROR
cs1641.cs
@@ -59,5 +58,3 @@
cs2007.cs
gcs0694.cs NO ERROR
gcs1644-2.cs NO ERROR
-
-cs0647.cs NO ERROR # not yet merged
Modified: trunk/mcs/mcs/ChangeLog
===================================================================
--- trunk/mcs/mcs/ChangeLog 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/mcs/ChangeLog 2005-05-26 13:55:43 UTC (rev 45046)
@@ -1,3 +1,22 @@
+2005-05-26 Raja R Harinath <[EMAIL PROTECTED]>
+
+ Improve user-defined conversion handling.
+ * convert.cs (GetConversionOperators): Rewrite. Return only the
+ applicable operators.
+ (AddConversionOperators): New. Helper for GetConversionOperators.
+ (FindMostEncompassedType, FindMostEncompassingType): Verify that
+ there is only one most encompassed/encompassing type.
+ (FindMostSpecificSource, FindMostSpecificTarget): Remove
+ "applicable operator" handling.
+ (UserConversion): Move cache here from GetConversionOperators.
+ Directly cache the chosen operator, rather than the whole
+ MethodGroup.
+ (ExplicitNumericConversion): Fix buggy implementation of Decimal
+ case. Allow conversion of decimal to sbyte and byte too.
+ * expression.cs (EmptyExpression.Grab, EmptyExpression.Release):
+ New static methods. Used to avoid allocating EmptyExpressions in
+ convert.cs.
+
2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
* ecore.cs (CastFromDecimal): New class for casting a decimal to
Modified: trunk/mcs/mcs/convert.cs
===================================================================
--- trunk/mcs/mcs/convert.cs 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/mcs/convert.cs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -696,13 +696,6 @@
return false;
}
- //
- // Used internally by FindMostEncompassedType, this is used
- // to avoid creating lots of objects in the tight loop inside
- // FindMostEncompassedType
- //
- static EmptyExpression priv_fmet_param;
-
/// <summary>
/// Finds "most encompassed type" according to the spec
(13.4.2)
/// amongst the methods in the MethodGroupExpr
@@ -711,31 +704,34 @@
{
Type best = null;
- if (priv_fmet_param == null)
- priv_fmet_param = new EmptyExpression ();
+ EmptyExpression expr = EmptyExpression.Grab ();
- foreach (Type t in types){
- priv_fmet_param.SetType (t);
-
+ foreach (Type t in types) {
if (best == null) {
best = t;
continue;
}
-
- if (ImplicitStandardConversionExists (ec,
priv_fmet_param, best))
+
+ expr.SetType (t);
+ if (ImplicitStandardConversionExists (ec, expr,
best))
best = t;
}
+ expr.SetType (best);
+ foreach (Type t in types) {
+ if (best == t)
+ continue;
+ if (!ImplicitStandardConversionExists (ec,
expr, t)) {
+ best = null;
+ break;
+ }
+ }
+
+ EmptyExpression.Release (expr);
+
return best;
}
-
- //
- // Used internally by FindMostEncompassingType, this is used
- // to avoid creating lots of objects in the tight loop inside
- // FindMostEncompassingType
- //
- static EmptyExpression priv_fmee_ret;
-
+
/// <summary>
/// Finds "most encompassing type" according to the spec
(13.4.2)
/// amongst the types in the given set
@@ -744,77 +740,57 @@
{
Type best = null;
- if (priv_fmee_ret == null)
- priv_fmee_ret = new EmptyExpression ();
+ EmptyExpression expr = EmptyExpression.Grab ();
- foreach (Type t in types){
- priv_fmee_ret.SetType (best);
-
+ foreach (Type t in types) {
if (best == null) {
best = t;
continue;
}
- if (ImplicitStandardConversionExists (ec,
priv_fmee_ret, t))
+ expr.SetType (best);
+ if (ImplicitStandardConversionExists (ec, expr,
t))
best = t;
}
-
+
+ foreach (Type t in types) {
+ if (best == t)
+ continue;
+ expr.SetType (t);
+ if (!ImplicitStandardConversionExists (ec,
expr, best)) {
+ best = null;
+ break;
+ }
+ }
+
+ EmptyExpression.Release (expr);
+
return best;
}
- //
- // Used to avoid creating too many objects
- //
- static EmptyExpression priv_fms_expr;
-
/// <summary>
/// Finds the most specific source Sx according to the rules
of the spec (13.4.4)
/// by making use of FindMostEncomp* methods. Applies the
correct rules separately
/// for explicit and implicit conversion operators.
/// </summary>
- static public Type FindMostSpecificSource (EmitContext ec,
MethodGroupExpr me,
+ static public Type FindMostSpecificSource (EmitContext ec,
IList list,
Expression source,
bool apply_explicit_conv_rules,
Location loc)
{
ArrayList src_types_set = new ArrayList ();
- if (priv_fms_expr == null)
- priv_fms_expr = new EmptyExpression ();
-
//
// If any operator converts from S then Sx = S
//
Type source_type = source.Type;
- foreach (MethodBase mb in me.Methods){
+ foreach (MethodBase mb in list){
ParameterData pd = TypeManager.GetParameterData
(mb);
Type param_type = pd.ParameterType (0);
if (param_type == source_type)
return param_type;
- if (apply_explicit_conv_rules) {
- //
- // From the spec :
- // Find the set of applicable
user-defined conversion operators, U. This set
- // consists of the
- // user-defined implicit or explicit
conversion operators declared by
- // the classes or structs in D that
convert from a type encompassing
- // or encompassed by S to a type
encompassing or encompassed by T
- //
- priv_fms_expr.SetType (param_type);
- if (ImplicitStandardConversionExists
(ec, priv_fms_expr, source_type))
- src_types_set.Add (param_type);
- else {
- if
(ImplicitStandardConversionExists (ec, source, param_type))
- src_types_set.Add
(param_type);
- }
- } else {
- //
- // Only if S is encompassed by
param_type
- //
- if (ImplicitStandardConversionExists
(ec, source, param_type))
- src_types_set.Add (param_type);
- }
+ src_types_set.Add (param_type);
}
//
@@ -849,50 +825,21 @@
/// <summary>
/// Finds the most specific target Tx according to section
13.4.4
/// </summary>
- static public Type FindMostSpecificTarget (EmitContext ec,
MethodGroupExpr me,
+ static public Type FindMostSpecificTarget (EmitContext ec,
IList list,
Type target, bool
apply_explicit_conv_rules,
Location loc)
{
ArrayList tgt_types_set = new ArrayList ();
- if (priv_fmt_expr == null)
- priv_fmt_expr = new EmptyExpression ();
-
//
// If any operator converts to T then Tx = T
//
- foreach (MethodInfo mi in me.Methods){
+ foreach (MethodInfo mi in list){
Type ret_type = mi.ReturnType;
-
if (ret_type == target)
return ret_type;
- if (apply_explicit_conv_rules) {
- //
- // From the spec :
- // Find the set of applicable
user-defined conversion operators, U.
- //
- // This set consists of the
- // user-defined implicit or explicit
conversion operators declared by
- // the classes or structs in D that
convert from a type encompassing
- // or encompassed by S to a type
encompassing or encompassed by T
- //
- priv_fms_expr.SetType (ret_type);
- if (ImplicitStandardConversionExists
(ec, priv_fms_expr, target))
- tgt_types_set.Add (ret_type);
- else {
- priv_fms_expr.SetType (target);
- if
(ImplicitStandardConversionExists (ec, priv_fms_expr, ret_type))
- tgt_types_set.Add
(ret_type);
- }
- } else {
- //
- // Only if T is encompassed by
param_type
- //
- priv_fms_expr.SetType (ret_type);
- if (ImplicitStandardConversionExists
(ec, priv_fms_expr, target))
- tgt_types_set.Add (ret_type);
- }
+ tgt_types_set.Add (ret_type);
}
//
@@ -901,13 +848,17 @@
if (apply_explicit_conv_rules) {
ArrayList candidate_set = new ArrayList ();
+ EmptyExpression expr = EmptyExpression.Grab ();
+
foreach (Type ret_type in tgt_types_set){
- priv_fmt_expr.SetType (ret_type);
+ expr.SetType (ret_type);
- if (ImplicitStandardConversionExists
(ec, priv_fmt_expr, target))
+ if (ImplicitStandardConversionExists
(ec, expr, target))
candidate_set.Add (ret_type);
}
+ EmptyExpression.Release (expr);
+
if (candidate_set.Count != 0)
return FindMostEncompassingType (ec,
candidate_set);
}
@@ -939,82 +890,90 @@
return UserDefinedConversion (ec, source, target, loc,
true);
}
- static DoubleHash explicit_conv = new DoubleHash (100);
- static DoubleHash implicit_conv = new DoubleHash (100);
- /// <summary>
- /// Computes the MethodGroup for the user-defined conversion
- /// operators from source_type to target_type.
`look_for_explicit'
- /// controls whether we should also include the list of
explicit
- /// operators
- /// </summary>
- static MethodGroupExpr GetConversionOperators (EmitContext ec,
- Type
source_type, Type target_type,
- Location loc,
bool look_for_explicit)
+ static void AddConversionOperators (EmitContext ec, ArrayList
list,
+ Expression source, Type
target_type,
+ bool look_for_explicit,
+ MethodGroupExpr mg)
{
- Expression mg1 = null, mg2 = null;
- Expression mg5 = null, mg6 = null, mg7 = null, mg8 =
null;
- string op_name;
+ if (mg == null)
+ return;
- op_name = "op_Implicit";
+ Type source_type = source.Type;
+ EmptyExpression expr = EmptyExpression.Grab ();
+ foreach (MethodInfo m in mg.Methods) {
+ ParameterData pd = TypeManager.GetParameterData
(m);
+ Type return_type = m.ReturnType;
+ Type arg_type = pd.ParameterType (0);
- MethodGroupExpr union3;
- object r;
- if ((look_for_explicit ? explicit_conv :
implicit_conv).Lookup (source_type, target_type, out r))
- return (MethodGroupExpr) r;
-
- mg1 = Expression.MethodLookup (ec, source_type,
op_name, loc);
- if (source_type.BaseType != null)
- mg2 = Expression.MethodLookup (ec,
source_type.BaseType, op_name, loc);
+ if (source_type != arg_type) {
+ if (!ImplicitStandardConversionExists
(ec, source, arg_type)) {
+ if (!look_for_explicit)
+ continue;
+ expr.SetType (arg_type);
+ if
(!ImplicitStandardConversionExists (ec, expr, source_type))
+ continue;
+ }
+ }
- if (mg1 == null)
- union3 = (MethodGroupExpr) mg2;
- else if (mg2 == null)
- union3 = (MethodGroupExpr) mg1;
- else
- union3 = Invocation.MakeUnionSet (mg1, mg2,
loc);
+ if (target_type != return_type) {
+ expr.SetType (return_type);
+ if (!ImplicitStandardConversionExists
(ec, expr, target_type)) {
+ if (!look_for_explicit)
+ continue;
+ expr.SetType (target_type);
+ if
(!ImplicitStandardConversionExists (ec, expr, return_type))
+ continue;
+ }
+ }
- mg1 = Expression.MethodLookup (ec, target_type,
op_name, loc);
- if (mg1 != null){
- if (union3 != null)
- union3 = Invocation.MakeUnionSet
(union3, mg1, loc);
- else
- union3 = (MethodGroupExpr) mg1;
+ list.Add (m);
}
- if (target_type.BaseType != null)
- mg1 = Expression.MethodLookup (ec,
target_type.BaseType, op_name, loc);
-
- if (mg1 != null){
- if (union3 != null)
- union3 = Invocation.MakeUnionSet
(union3, mg1, loc);
- else
- union3 = (MethodGroupExpr) mg1;
- }
+ EmptyExpression.Release (expr);
+ }
- MethodGroupExpr union4 = null;
+ /// <summary>
+ /// Computes the list of the user-defined conversion
+ /// operators from source_type to target_type.
`look_for_explicit'
+ /// controls whether we should also include the list of
explicit
+ /// operators
+ /// </summary>
+ static IList GetConversionOperators (EmitContext ec,
+ Expression source, Type
target_type,
+ Location loc, bool
look_for_explicit)
+ {
+ ArrayList ret = new ArrayList (4);
- if (look_for_explicit) {
- op_name = "op_Explicit";
+ Type source_type = source.Type;
- mg5 = Expression.MemberLookup (ec, source_type,
op_name, loc);
- if (source_type.BaseType != null)
- mg6 = Expression.MethodLookup (ec,
source_type.BaseType, op_name, loc);
-
- mg7 = Expression.MemberLookup (ec, target_type,
op_name, loc);
- if (target_type.BaseType != null)
- mg8 = Expression.MethodLookup (ec,
target_type.BaseType, op_name, loc);
-
- MethodGroupExpr union5 =
Invocation.MakeUnionSet (mg5, mg6, loc);
- MethodGroupExpr union6 =
Invocation.MakeUnionSet (mg7, mg8, loc);
+ if (source_type != TypeManager.decimal_type) {
+ AddConversionOperators (ec, ret, source,
target_type, look_for_explicit,
+ Expression.MethodLookup (
+ ec, source_type, "op_Implicit",
loc) as MethodGroupExpr);
+ if (look_for_explicit) {
+ AddConversionOperators (ec, ret,
source, target_type, look_for_explicit,
+ Expression.MethodLookup (
+ ec, source_type,
"op_Explicit", loc) as MethodGroupExpr);
+ }
+ }
- union4 = Invocation.MakeUnionSet (union5,
union6, loc);
+ if (target_type != TypeManager.decimal_type) {
+ AddConversionOperators (ec, ret, source,
target_type, look_for_explicit,
+ Expression.MethodLookup (
+ ec, target_type, "op_Implicit",
loc) as MethodGroupExpr);
+ if (look_for_explicit) {
+ AddConversionOperators (ec, ret,
source, target_type, look_for_explicit,
+ Expression.MethodLookup (
+ ec, target_type,
"op_Explicit", loc) as MethodGroupExpr);
+ }
}
-
- MethodGroupExpr ret = Invocation.MakeUnionSet (union3,
union4, loc);
- (look_for_explicit ? explicit_conv :
implicit_conv).Insert (source_type, target_type, ret);
+
return ret;
}
-
+
+ static DoubleHash explicit_conv = new DoubleHash (100);
+ static DoubleHash implicit_conv = new DoubleHash (100);
+
/// <summary>
/// User-defined conversions
/// </summary>
@@ -1022,42 +981,62 @@
Type target,
Location loc,
bool
look_for_explicit)
{
- MethodGroupExpr union;
Type source_type = source.Type;
- MethodBase method = null;
+ MethodInfo method = null;
+ Type most_specific_source = null;
+ Type most_specific_target = null;
- union = GetConversionOperators (ec, source_type,
target, loc, look_for_explicit);
- if (union == null)
- return null;
-
- Type most_specific_source, most_specific_target;
+ object o;
+ DoubleHash hash = look_for_explicit ? explicit_conv :
implicit_conv;
- most_specific_source = FindMostSpecificSource (ec,
union, source, look_for_explicit, loc);
- if (most_specific_source == null)
- return null;
-
- most_specific_target = FindMostSpecificTarget (ec,
union, target, look_for_explicit, loc);
- if (most_specific_target == null)
- return null;
-
- int count = 0;
-
-
- foreach (MethodBase mb in union.Methods){
- ParameterData pd = TypeManager.GetParameterData
(mb);
- MethodInfo mi = (MethodInfo) mb;
+ if (!(source is Constant) && hash.Lookup (source_type,
target, out o)) {
+ method = (MethodInfo) o;
+ if (method != null) {
+ ParameterData pd =
TypeManager.GetParameterData (method);
+ most_specific_source = pd.ParameterType
(0);
+ most_specific_target =
method.ReturnType;
+ }
+ } else {
+ IList ops = GetConversionOperators (ec, source,
target, loc, look_for_explicit);
+ if (ops == null || ops.Count == 0) {
+ method = null;
+ goto skip;
+ }
+
+ most_specific_source = FindMostSpecificSource
(ec, ops, source, look_for_explicit, loc);
+ if (most_specific_source == null) {
+ method = null;
+ goto skip;
+ }
- if (pd.ParameterType (0) ==
most_specific_source &&
- mi.ReturnType == most_specific_target) {
- method = mb;
- count++;
+ most_specific_target = FindMostSpecificTarget
(ec, ops, target, look_for_explicit, loc);
+ if (most_specific_target == null) {
+ method = null;
+ goto skip;
}
+
+ int count = 0;
+
+ foreach (MethodInfo m in ops) {
+ ParameterData pd =
TypeManager.GetParameterData (m);
+
+ if (pd.ParameterType (0) ==
most_specific_source &&
+ m.ReturnType ==
most_specific_target) {
+ method = m;
+ count++;
+ }
+ }
+ if (count > 1)
+ method = null;
+
+ skip:
+ if (!(source is Constant))
+ hash.Insert (source_type, target,
method);
}
-
- if (method == null || count > 1)
+
+ if (method == null)
return null;
-
//
// This will do the conversion to the best match that we
// found. Now we need to perform an implict standard
conversion
@@ -1073,7 +1052,7 @@
return null;
Expression e;
- e = new UserCast ((MethodInfo) method, source, loc);
+ e = new UserCast (method, source, loc);
if (e.Type != target){
if (!look_for_explicit)
e = ImplicitConversionStandard (ec, e,
target, loc);
@@ -1548,18 +1527,20 @@
return new CastToDecimal (ec, expr,
true);
} else if (expr_type == TypeManager.decimal_type) {
//
- // From decimal to short, ushort, int, uint,
+ // From decimal to sbyte, byte, short, ushort,
int, uint,
// long, ulong, char, double or float
//
- if (real_target_type == TypeManager.short_type)
- if (real_target_type == TypeManager.ushort_type)
- if (real_target_type == TypeManager.int32_type)
- if (real_target_type == TypeManager.uint32_type)
- if (real_target_type == TypeManager.int64_type)
- if (real_target_type == TypeManager.uint64_type)
- if (real_target_type == TypeManager.char_type)
- if (real_target_type == TypeManager.double_type)
- if (real_target_type == TypeManager.float_type)
+ if (real_target_type == TypeManager.sbyte_type
||
+ real_target_type == TypeManager.byte_type ||
+ real_target_type == TypeManager.short_type
||
+ real_target_type == TypeManager.ushort_type
||
+ real_target_type == TypeManager.int32_type
||
+ real_target_type == TypeManager.uint32_type
||
+ real_target_type == TypeManager.int64_type
||
+ real_target_type == TypeManager.uint64_type
||
+ real_target_type == TypeManager.char_type ||
+ real_target_type == TypeManager.double_type
||
+ real_target_type == TypeManager.float_type)
return new CastFromDecimal (ec, expr,
target_type);
}
return null;
Modified: trunk/mcs/mcs/expression.cs
===================================================================
--- trunk/mcs/mcs/expression.cs 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/mcs/expression.cs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -8462,6 +8462,23 @@
public class EmptyExpression : Expression {
public static readonly EmptyExpression Null = new
EmptyExpression ();
+ static EmptyExpression temp = new EmptyExpression ();
+ public static EmptyExpression Grab ()
+ {
+ if (temp == null)
+ throw new InternalErrorException ("Nested
Grab");
+ EmptyExpression retval = temp;
+ temp = null;
+ return retval;
+ }
+
+ public static void Release (EmptyExpression e)
+ {
+ if (temp != null)
+ throw new InternalErrorException ("Already
released");
+ temp = e;
+ }
+
// TODO: should be protected
public EmptyExpression ()
{
Modified: trunk/mcs/tests/ChangeLog
===================================================================
--- trunk/mcs/tests/ChangeLog 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/tests/ChangeLog 2005-05-26 13:55:43 UTC (rev 45046)
@@ -1,3 +1,8 @@
+2005-05-26 Duncan Mak <[EMAIL PROTECTED]>
+ Raja R Harinath <[EMAIL PROTECTED]>
+
+ * test-387.cs: New test from #54928.
+
2005-05-24 Duncan Mak <[EMAIL PROTECTED]>
* test-386.cs: New test from #68711.
Modified: trunk/mcs/tests/Makefile
===================================================================
--- trunk/mcs/tests/Makefile 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/tests/Makefile 2005-05-26 13:55:43 UTC (rev 45046)
@@ -33,7 +33,7 @@
# Martin Baulig will manually move them into TEST_SOURCES_common after merging
the code into GMCS.
# He may also move some to TEST_EXCLUDE_net_2_0 if some of the merges are
inappropriate for GMCS.
#
-NEW_TEST_SOURCES_common = test-386
+NEW_TEST_SOURCES_common = test-386 test-387
#
# Please do _not_ add any tests here - all new tests should go into
NEW_TEST_SOURCES_common
Added: trunk/mcs/tests/test-387.cs
===================================================================
--- trunk/mcs/tests/test-387.cs 2005-05-26 13:36:03 UTC (rev 45045)
+++ trunk/mcs/tests/test-387.cs 2005-05-26 13:55:43 UTC (rev 45046)
@@ -0,0 +1,25 @@
+public struct ObjectID {
+ long l;
+
+ public ObjectID (long l)
+ {
+ this.l = l;
+ }
+
+ public static implicit operator long (ObjectID p)
+ {
+ return p.l;
+ }
+
+ public static implicit operator ObjectID (long l)
+ {
+ return new ObjectID (l);
+ }
+
+ static void Main ()
+ {
+ ObjectID x = new ObjectID (0);
+ decimal y = x;
+ }
+}
+
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches