2010-01-07 Marek Safar <marek.safar@gmail.com>
[mono.git] / mcs / mcs / cfold.cs
index 0c69e1c5d3dfc80be89753efb9f04014b287e1c0..51bbbd1c54000797e89755f840da58701002c5a5 100644 (file)
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Marek Safar (marek.safar@seznam.cz)
 //
-// (C) 2002, 2003 Ximian, Inc.
-//
-
+// Copyright 2002, 2003 Ximian, Inc.
+// Copyright 2003-2008, Novell, Inc.
+// 
 using System;
 
 namespace Mono.CSharp {
 
        public class ConstantFold {
 
+               public static readonly Type[] binary_promotions = new Type[] { 
+                       TypeManager.decimal_type, TypeManager.double_type, TypeManager.float_type,
+                       TypeManager.uint64_type, TypeManager.int64_type, TypeManager.uint32_type };
+
                //
                // Performs the numeric promotions on the left and right expresions
-               // and desposits the results on `lc' and `rc'.
+               // and deposits the results on `lc' and `rc'.
                //
                // On success, the types of `lc' and `rc' on output will always match,
                // and the pair will be one of:
                //
-               //   (double, double)
-               //   (float, float)
-               //   (ulong, ulong)
-               //   (long, long)
-               //   (uint, uint)
-               //   (int, int)
-               //   (short, short)   (Happens with enumerations with underlying short type)
-               //   (ushort, ushort) (Happens with enumerations with underlying short type)
-               //
-               static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
-                                                        ref Constant left, ref Constant right,
-                                                        Location loc)
+               // TODO: BinaryFold should be called as an optimization step only,
+               // error checking here is weak
+               //              
+               static bool DoBinaryNumericPromotions (ResolveContext rc, ref Constant left, ref Constant right)
                {
-                       if (left is DoubleConstant || right is DoubleConstant){
-                               //
-                               // If either side is a double, convert the other to a double
-                               //
-                               if (!(left is DoubleConstant))
-                                       left = left.ToDouble (loc);
-
-                               if (!(right is DoubleConstant))
-                                       right = right.ToDouble (loc);
-                               return;
-                       } else if (left is FloatConstant || right is FloatConstant) {
-                               //
-                               // If either side is a float, convert the other to a float
-                               //
-                               if (!(left is FloatConstant))
-                                       left = left.ToFloat (loc);
-
-                               if (!(right is FloatConstant))
-                                       right = right.ToFloat (loc);
-;                              return;
-                       } else if (left is ULongConstant || right is ULongConstant){
-                               //
-                               // If either operand is of type ulong, the other operand is
-                               // converted to type ulong.  or an error ocurrs if the other
-                               // operand is of type sbyte, short, int or long
-                               //
-#if WRONG
-                               Constant match, other;
-#endif
-                                       
-                               if (left is ULongConstant){
-#if WRONG
-                                       other = right;
-                                       match = left;
-#endif
-                                       if (!(right is ULongConstant))
-                                               right = right.ToULong (loc);
-                               } else {
-#if WRONG
-                                       other = left;
-                                       match = right;
-#endif
-                                       left = left.ToULong (loc);
-                               }
-
-#if WRONG
-                               if (other is SByteConstant || other is ShortConstant ||
-                                   other is IntConstant || other is LongConstant){
-                                       Binary.Error_OperatorAmbiguous
-                                               (loc, oper, other.Type, match.Type);
-                                       left = null;
-                                       right = null;
-                               }
-#endif
-                               return;
-                       } else if (left is LongConstant || right is LongConstant){
-                               //
-                               // If either operand is of type long, the other operand is converted
-                               // to type long.
-                               //
-                               if (!(left is LongConstant))
-                                       left = left.ToLong (loc);
-                               else if (!(right is LongConstant))
-                                       right = right.ToLong (loc);
-                               return;
-                       } else if (left is UIntConstant || right is UIntConstant){
-                               //
-                               // If either operand is of type uint, and the other
-                               // operand is of type sbyte, short or int, the operands are
-                               // converted to type long.
-                               //
-                               Constant other;
-                               if (left is UIntConstant)
-                                       other = right;
-                               else
-                                       other = left;
+                       Type ltype = left.Type;
+                       Type rtype = right.Type;
 
-                               // Nothing to do.
-                               if (other is UIntConstant)
-                                       return;
+                       foreach (Type t in binary_promotions) {
+                               if (t == ltype)
+                                       return t == rtype || ConvertPromotion (rc, ref right, ref left, t);
 
-                               IntConstant ic = other as IntConstant;
-                               if (ic != null){
-                                       if (ic.Value >= 0){
-                                               if (left == other)
-                                                       left = new UIntConstant ((uint) ic.Value);
-                                               else
-                                                       right = new UIntConstant ((uint) ic.Value);
-                                               return;
-                                       }
-                               }
-                               
-                               if (other is SByteConstant || other is ShortConstant || ic != null){
-                                       left = left.ToLong (loc);
-                                       right = right.ToLong (loc);
-                               } else {
-                                       left = left.ToUInt (loc);
-                                       right = left.ToUInt (loc);
-                               }
-
-                               return;
-                       } else if (left is DecimalConstant || right is DecimalConstant) {
-                               if (!(left is DecimalConstant))
-                                       left = left.ToDecimal (loc);
-                               else if (!(right is DecimalConstant))
-                                       right = right.ToDecimal (loc);
-                               return;
-                       } else if (left is EnumConstant || right is EnumConstant){
-                               //
-                               // If either operand is an enum constant, the other one must
-                               // be implicitly convertable to that enum's underlying type.
-                               //
-                               EnumConstant match;
-                               Constant other;
-                               if (left is EnumConstant){
-                                       other = right;
-                                       match = (EnumConstant) left;
-                               } else {
-                                       other = left;
-                                       match = (EnumConstant) right;
-                               }
-
-                               bool need_check = (other is EnumConstant) ||
-                                       !(oper == Binary.Operator.Addition || 
-                                         oper == Binary.Operator.Subtraction ||
-                                         (other.IsZeroInteger && other is IntConstant));
-
-                               if (need_check &&
-                                   !Convert.ImplicitConversionExists (ec, match, other.Type)) {
-                                       Convert.Error_CannotImplicitConversion (loc, match.Type, other.Type);
-                                       left = null;
-                                       right = null;
-                                       return;
-                               }
+                               if (t == rtype)
+                                       return t == ltype || ConvertPromotion (rc, ref left, ref right, t);
+                       }
 
-                               if (left is EnumConstant)
-                                       left = ((EnumConstant) left).Child;
-                               if (right is EnumConstant)
-                                       right = ((EnumConstant) right).Child;
+                       left = left.ConvertImplicitly (rc, TypeManager.int32_type);
+                       right = right.ConvertImplicitly (rc, TypeManager.int32_type);
+                       return left != null && right != null;
+               }
 
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               return;
+               static bool ConvertPromotion (ResolveContext rc, ref Constant prim, ref Constant second, Type type)
+               {
+                       Constant c = prim.ConvertImplicitly (rc, type);
+                       if (c != null) {
+                               prim = c;
+                               return true;
+                       }
 
-                       } else {
-                               //
-                               // Force conversions to int32
-                               //
-                               if (!(left is IntConstant))
-                                       left = left.ToInt (loc);
-                               if (!(right is IntConstant))
-                                       right = right.ToInt (loc);
+                       if (type == TypeManager.uint32_type) {
+                               type = TypeManager.int64_type;
+                               prim = prim.ConvertImplicitly (rc, type);
+                               second = second.ConvertImplicitly (rc, type);
+                               return prim != null && second != null;
                        }
-                       return;
+
+                       return false;
                }
 
-               static void Error_CompileTimeOverflow (Location loc)
+               internal static void Error_CompileTimeOverflow (ResolveContext rc, Location loc)
                {
-                       Report.Error (220, loc, "The operation overflows at compile time in checked mode");
+                       rc.Report.Error (220, loc, "The operation overflows at compile time in checked mode");
                }
                
                /// <summary>
@@ -198,244 +74,208 @@ namespace Mono.CSharp {
                ///
                ///   Returns null if the expression can not be folded.
                /// </summary>
-               static public Expression BinaryFold (EmitContext ec, Binary.Operator oper,
+               static public Constant BinaryFold (ResolveContext ec, Binary.Operator oper,
                                                     Constant left, Constant right, Location loc)
                {
+                       Constant result = null;
+
+                       if (left is EmptyConstantCast)
+                               return BinaryFold (ec, oper, ((EmptyConstantCast)left).child, right, loc);
+
+                       if (left is SideEffectConstant) {
+                               result = BinaryFold (ec, oper, ((SideEffectConstant) left).value, right, loc);
+                               if (result == null)
+                                       return null;
+                               return new SideEffectConstant (result, left, loc);
+                       }
+
+                       if (right is EmptyConstantCast)
+                               return BinaryFold (ec, oper, left, ((EmptyConstantCast)right).child, loc);
+
+                       if (right is SideEffectConstant) {
+                               result = BinaryFold (ec, oper, left, ((SideEffectConstant) right).value, loc);
+                               if (result == null)
+                                       return null;
+                               return new SideEffectConstant (result, right, loc);
+                       }
+
                        Type lt = left.Type;
                        Type rt = right.Type;
-                       Type result_type = null;
                        bool bool_res;
 
-                       //
-                       // Enumerator folding
-                       //
-                       if (rt == lt && left is EnumConstant)
-                               result_type = lt;
+                       if (lt == TypeManager.bool_type && lt == rt) {
+                               bool lv = (bool) left.GetValue ();
+                               bool rv = (bool) right.GetValue ();                     
+                               switch (oper) {
+                               case Binary.Operator.BitwiseAnd:
+                               case Binary.Operator.LogicalAnd:
+                                       return new BoolConstant (lv && rv, left.Location);
+                               case Binary.Operator.BitwiseOr:
+                               case Binary.Operator.LogicalOr:
+                                       return new BoolConstant (lv || rv, left.Location);
+                               case Binary.Operator.ExclusiveOr:
+                                       return new BoolConstant (lv ^ rv, left.Location);
+                               case Binary.Operator.Equality:
+                                       return new BoolConstant (lv == rv, left.Location);
+                               case Binary.Operator.Inequality:
+                                       return new BoolConstant (lv != rv, left.Location);
+                               }
+                               return null;
+                       }
 
                        //
-                       // During an enum evaluation, we need to unwrap enumerations
+                       // During an enum evaluation, none of the rules are valid
+                       // Not sure whether it is bug in csc or in documentation
                        //
-                       if (ec.InEnumContext){
+                       if (ec.HasSet (ResolveContext.Options.EnumScope)){
                                if (left is EnumConstant)
                                        left = ((EnumConstant) left).Child;
                                
                                if (right is EnumConstant)
                                        right = ((EnumConstant) right).Child;
+                       } else if (left is EnumConstant && rt == lt) {
+                               switch (oper){
+                                       ///
+                                       /// E operator |(E x, E y);
+                                       /// E operator &(E x, E y);
+                                       /// E operator ^(E x, E y);
+                                       /// 
+                                       case Binary.Operator.BitwiseOr:
+                                       case Binary.Operator.BitwiseAnd:
+                                       case Binary.Operator.ExclusiveOr:
+                                               result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
+                                               if (result != null)
+                                                       result = result.Resolve (ec).TryReduce (ec, lt, loc);
+                                               return result;
+
+                                       ///
+                                       /// U operator -(E x, E y);
+                                       /// 
+                                       case Binary.Operator.Subtraction:
+                                               result = BinaryFold (ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
+                                               if (result != null)
+                                                       result = result.Resolve (ec).TryReduce (ec, ((EnumConstant)left).Child.Type, loc);
+                                               return result;
+
+                                       ///
+                                       /// bool operator ==(E x, E y);
+                                       /// bool operator !=(E x, E y);
+                                       /// bool operator <(E x, E y);
+                                       /// bool operator >(E x, E y);
+                                       /// bool operator <=(E x, E y);
+                                       /// bool operator >=(E x, E y);
+                                       /// 
+                                       case Binary.Operator.Equality:                          
+                                       case Binary.Operator.Inequality:
+                                       case Binary.Operator.LessThan:                          
+                                       case Binary.Operator.GreaterThan:
+                                       case Binary.Operator.LessThanOrEqual:                           
+                                       case Binary.Operator.GreaterThanOrEqual:
+                                               return BinaryFold(ec, oper, ((EnumConstant)left).Child, ((EnumConstant)right).Child, loc);
+                               }
+                               return null;
                        }
 
-                       Type wrap_as;
-                       Constant result = null;
                        switch (oper){
                        case Binary.Operator.BitwiseOr:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                if (left is IntConstant){
-                                       IntConstant v;
                                        int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
                                        
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UIntConstant){
-                                       UIntConstant v;
+                                       return new IntConstant (res, left.Location);
+                               }
+                               if (left is UIntConstant){
                                        uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
                                        
-                                       v = new UIntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is LongConstant){
-                                       LongConstant v;
+                                       return new UIntConstant (res, left.Location);
+                               }
+                               if (left is LongConstant){
                                        long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
                                        
-                                       v = new LongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ULongConstant){
-                                       ULongConstant v;
+                                       return new LongConstant (res, left.Location);
+                               }
+                               if (left is ULongConstant){
                                        ulong res = ((ULongConstant)left).Value |
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UShortConstant){
-                                       UShortConstant v;
-                                       ushort res = (ushort) (((UShortConstant)left).Value |
-                                                              ((UShortConstant)right).Value);
-                                       
-                                       v = new UShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ShortConstant){
-                                       ShortConstant v;
-                                       short res = (short) (((ShortConstant)left).Value |
-                                                            ((ShortConstant)right).Value);
-                                       
-                                       v = new ShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
+                                       return new ULongConstant (res, left.Location);
                                }
                                break;
                                
                        case Binary.Operator.BitwiseAnd:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
                                
+                               ///
+                               /// int operator &(int x, int y);
+                               /// uint operator &(uint x, uint y);
+                               /// long operator &(long x, long y);
+                               /// ulong operator &(ulong x, ulong y);
+                               ///
                                if (left is IntConstant){
-                                       IntConstant v;
                                        int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UIntConstant){
-                                       UIntConstant v;
+                                       return new IntConstant (res, left.Location);
+                               }
+                               if (left is UIntConstant){
                                        uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
-                                       
-                                       v = new UIntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is LongConstant){
-                                       LongConstant v;
+                                       return new UIntConstant (res, left.Location);
+                               }
+                               if (left is LongConstant){
                                        long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
-                                       
-                                       v = new LongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ULongConstant){
-                                       ULongConstant v;
+                                       return new LongConstant (res, left.Location);
+                               }
+                               if (left is ULongConstant){
                                        ulong res = ((ULongConstant)left).Value &
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UShortConstant){
-                                       UShortConstant v;
-                                       ushort res = (ushort) (((UShortConstant)left).Value &
-                                                              ((UShortConstant)right).Value);
-                                       
-                                       v = new UShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ShortConstant){
-                                       ShortConstant v;
-                                       short res = (short) (((ShortConstant)left).Value &
-                                                            ((ShortConstant)right).Value);
-                                       
-                                       v = new ShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
+                                       return new ULongConstant (res, left.Location);
                                }
                                break;
 
                        case Binary.Operator.ExclusiveOr:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
                                
                                if (left is IntConstant){
-                                       IntConstant v;
                                        int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
-                                       
-                                       v = new IntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UIntConstant){
-                                       UIntConstant v;
+                                       return new IntConstant (res, left.Location);
+                               }
+                               if (left is UIntConstant){
                                        uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
                                        
-                                       v = new UIntConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is LongConstant){
-                                       LongConstant v;
+                                       return  new UIntConstant (res, left.Location);
+                               }
+                               if (left is LongConstant){
                                        long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
                                        
-                                       v = new LongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ULongConstant){
-                                       ULongConstant v;
+                                       return new LongConstant (res, left.Location);
+                               }
+                               if (left is ULongConstant){
                                        ulong res = ((ULongConstant)left).Value ^
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is UShortConstant){
-                                       UShortConstant v;
-                                       ushort res = (ushort) (((UShortConstant)left).Value ^
-                                                              ((UShortConstant)right).Value);
-                                       
-                                       v = new UShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
-                               } else if (left is ShortConstant){
-                                       ShortConstant v;
-                                       short res = (short)(((ShortConstant)left).Value ^
-                                                           ((ShortConstant)right).Value);
-                                       
-                                       v = new ShortConstant (res);
-                                       if (result_type == null)
-                                               return v;
-                                       else
-                                               return new EnumConstant (v, result_type);
+                                       return new ULongConstant (res, left.Location);
                                }
                                break;
 
                        case Binary.Operator.Addition:
-                               bool left_is_string = left is StringConstant;
-                               bool right_is_string = right is StringConstant;
+                               if (lt == TypeManager.null_type)
+                                       return right;
+
+                               if (rt == TypeManager.null_type)
+                                       return left;
 
                                //
                                // If both sides are strings, then concatenate, if
                                // one is a string, and the other is not, then defer
                                // to runtime concatenation
                                //
-                               wrap_as = null;
-                               if (left_is_string || right_is_string){
-                                       if (left_is_string && right_is_string)
-                                               return new StringConstant (
-                                                       ((StringConstant) left).Value +
-                                                       ((StringConstant) right).Value);
+                               if (lt == TypeManager.string_type || rt == TypeManager.string_type){
+                                       if (lt == rt)
+                                               return new StringConstant ((string)left.GetValue () + (string)right.GetValue (),
+                                                       left.Location);
                                        
                                        return null;
                                }
@@ -444,29 +284,32 @@ namespace Mono.CSharp {
                                // handle "E operator + (E x, U y)"
                                // handle "E operator + (Y y, E x)"
                                //
-                               // note that E operator + (E x, E y) is invalid
-                               //
-                               if (left is EnumConstant){
-                                       if (right is EnumConstant){
-                                               return null;
+                               EnumConstant lc = left as EnumConstant;
+                               EnumConstant rc = right as EnumConstant;
+                               if (lc != null || rc != null){
+                                       if (lc == null) {
+                                               lc = rc;
+                                               lt = lc.Type;
+                                               right = left;
                                        }
 
-                                       right = right.ToType (((EnumConstant) left).Child.Type, loc);
+                                       // U has to be implicitly convetible to E.base
+                                       right = right.ConvertImplicitly (ec, lc.Child.Type);
                                        if (right == null)
                                                return null;
 
-                                       wrap_as = left.Type;
-                               } else if (right is EnumConstant){
-                                       left = left.ToType (((EnumConstant) right).Child.Type, loc);
-                                       if (left == null)
+                                       result = BinaryFold (ec, oper, lc.Child, right, loc);
+                                       if (result == null)
+                                               return null;
+
+                                       result = result.Resolve (ec).TryReduce (ec, lt, loc);
+                                       if (result == null)
                                                return null;
 
-                                       wrap_as = right.Type;
+                                       return new EnumConstant (result, lt);
                                }
 
-                               result = null;
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                try {
@@ -480,8 +323,9 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value +
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               result = new DoubleConstant (res);
-                                       } else if (left is FloatConstant){
+                                               return new DoubleConstant (res, left.Location);
+                                       }
+                                       if (left is FloatConstant){
                                                float res;
                                                
                                                if (ec.ConstantCheckState)
@@ -491,7 +335,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value +
                                                                         ((FloatConstant) right).Value);
                                                
-                                               result = new FloatConstant (res);
+                                               result = new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -502,7 +346,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value +
                                                                         ((ULongConstant) right).Value);
 
-                                               result = new ULongConstant (res);
+                                               result = new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -513,7 +357,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value +
                                                                         ((LongConstant) right).Value);
                                                
-                                               result = new LongConstant (res);
+                                               result = new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -524,7 +368,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value +
                                                                         ((UIntConstant) right).Value);
                                                
-                                               result = new UIntConstant (res);
+                                               result = new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -535,7 +379,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value +
                                                                         ((IntConstant) right).Value);
 
-                                               result = new IntConstant (res);
+                                               result = new IntConstant (res, left.Location);
                                        } else if (left is DecimalConstant) {
                                                decimal res;
 
@@ -546,59 +390,45 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DecimalConstant) left).Value +
                                                                ((DecimalConstant) right).Value);
 
-                                               result = new DecimalConstant (res);
-                                       } else {
-                                               throw new Exception ( "Unexepected addition input: " + left);
+                                               result = new DecimalConstant (res, left.Location);
                                        }
                                } catch (OverflowException){
-                                       Error_CompileTimeOverflow (loc);
+                                       Error_CompileTimeOverflow (ec, loc);
                                }
 
-                               if (wrap_as != null)
-                                       return new EnumConstant (result, wrap_as);
-                               else
-                                       return result;
+                               return result;
 
                        case Binary.Operator.Subtraction:
                                //
                                // handle "E operator - (E x, U y)"
                                // handle "E operator - (Y y, E x)"
-                               // handle "U operator - (E x, E y)"
                                //
-                               wrap_as = null;
-                               if (left is EnumConstant){
-                                       if (right is EnumConstant){
-                                               if (left.Type != right.Type) {
-                                                       Binary.Error_OperatorCannotBeApplied (loc, "-", left.Type, right.Type);
-                                                       return null;
-                                               }
-
-                                               wrap_as = TypeManager.EnumToUnderlying (left.Type);
-                                               right = ((EnumConstant) right).Child.ToType (wrap_as, loc);
-                                               if (right == null)
-                                                       return null;
-
-                                               left = ((EnumConstant) left).Child.ToType (wrap_as, loc);
-                                               if (left == null)
-                                                       return null;
+                               lc = left as EnumConstant;
+                               rc = right as EnumConstant;
+                               if (lc != null || rc != null){
+                                       if (lc == null) {
+                                               lc = rc;
+                                               lt = lc.Type;
+                                               right = left;
                                        }
-                                       else {
-                                               right = right.ToType (((EnumConstant) left).Child.Type, loc);
-                                               if (right == null)
-                                                       return null;
 
-                                               wrap_as = left.Type;
-                                       }
-                               } else if (right is EnumConstant){
-                                       left = left.ToType (((EnumConstant) right).Child.Type, loc);
-                                       if (left == null)
+                                       // U has to be implicitly convetible to E.base
+                                       right = right.ConvertImplicitly (ec, lc.Child.Type);
+                                       if (right == null)
                                                return null;
 
-                                       wrap_as = right.Type;
+                                       result = BinaryFold (ec, oper, lc.Child, right, loc);
+                                       if (result == null)
+                                               return null;
+
+                                       result = result.Resolve (ec).TryReduce (ec, lt, loc);
+                                       if (result == null)
+                                               return null;
+
+                                       return new EnumConstant (result, lt);
                                }
 
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                try {
@@ -612,7 +442,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value -
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               result = new DoubleConstant (res);
+                                               result = new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -623,7 +453,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value -
                                                                         ((FloatConstant) right).Value);
                                                
-                                               result = new FloatConstant (res);
+                                               result = new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -634,7 +464,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value -
                                                                         ((ULongConstant) right).Value);
                                                
-                                               result = new ULongConstant (res);
+                                               result = new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -645,7 +475,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value -
                                                                         ((LongConstant) right).Value);
                                                
-                                               result = new LongConstant (res);
+                                               result = new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -656,7 +486,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value -
                                                                         ((UIntConstant) right).Value);
                                                
-                                               result = new UIntConstant (res);
+                                               result = new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -667,7 +497,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value -
                                                                         ((IntConstant) right).Value);
 
-                                               result = new IntConstant (res);
+                                               result = new IntConstant (res, left.Location);
                                        } else if (left is DecimalConstant) {
                                                decimal res;
 
@@ -678,21 +508,18 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DecimalConstant) left).Value -
                                                                ((DecimalConstant) right).Value);
 
-                                               return new DecimalConstant (res);
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
                                                throw new Exception ( "Unexepected subtraction input: " + left);
                                        }
                                } catch (OverflowException){
-                                       Error_CompileTimeOverflow (loc);
+                                       Error_CompileTimeOverflow (ec, loc);
                                }
-                               if (wrap_as != null)
-                                       return new EnumConstant (result, wrap_as);
-                               else
-                                       return result;
+
+                               return result;
                                
                        case Binary.Operator.Multiply:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                try {
@@ -706,7 +533,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value *
                                                                ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               return new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -717,7 +544,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value *
                                                                ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               return new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -728,7 +555,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value *
                                                                ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               return new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -739,7 +566,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value *
                                                                ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               return new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -750,7 +577,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value *
                                                                ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               return new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -761,7 +588,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value *
                                                                ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               return new IntConstant (res, left.Location);
                                        } else if (left is DecimalConstant) {
                                                decimal res;
 
@@ -772,18 +599,17 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DecimalConstant) left).Value *
                                                                ((DecimalConstant) right).Value);
 
-                                               return new DecimalConstant (res);
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
                                                throw new Exception ( "Unexepected multiply input: " + left);
                                        }
                                } catch (OverflowException){
-                                       Error_CompileTimeOverflow (loc);
+                                       Error_CompileTimeOverflow (ec, loc);
                                }
                                break;
 
                        case Binary.Operator.Division:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                try {
@@ -797,7 +623,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value /
                                                                ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               return new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -808,7 +634,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value /
                                                                ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               return new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -819,7 +645,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value /
                                                                ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               return new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -830,7 +656,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value /
                                                                ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               return new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -841,7 +667,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value /
                                                                ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               return new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -852,7 +678,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value /
                                                                ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               return new IntConstant (res, left.Location);
                                        } else if (left is DecimalConstant) {
                                                decimal res;
 
@@ -863,22 +689,21 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DecimalConstant) left).Value /
                                                                ((DecimalConstant) right).Value);
 
-                                               return new DecimalConstant (res);
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
                                                throw new Exception ( "Unexepected division input: " + left);
                                        }
                                } catch (OverflowException){
-                                       Error_CompileTimeOverflow (loc);
+                                       Error_CompileTimeOverflow (ec, loc);
 
                                } catch (DivideByZeroException) {
-                                       Report.Error (020, loc, "Division by constant zero");
+                                       ec.Report.Error (20, loc, "Division by constant zero");
                                }
                                
                                break;
                                
                        case Binary.Operator.Modulus:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                try {
@@ -892,7 +717,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value %
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               return new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -903,7 +728,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value %
                                                                         ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               return new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -914,7 +739,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value %
                                                                         ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               return new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -925,7 +750,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value %
                                                                         ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               return new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -936,7 +761,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value %
                                                                         ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               return new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -947,14 +772,14 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value %
                                                                         ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               return new IntConstant (res, left.Location);
                                        } else {
                                                throw new Exception ( "Unexepected modulus input: " + left);
                                        }
                                } catch (DivideByZeroException){
-                                       Report.Error (020, loc, "Division by constant zero");
+                                       ec.Report.Error (20, loc, "Division by constant zero");
                                } catch (OverflowException){
-                                       Error_CompileTimeOverflow (loc);
+                                       Error_CompileTimeOverflow (ec, loc);
                                }
                                break;
 
@@ -962,107 +787,67 @@ namespace Mono.CSharp {
                                // There is no overflow checking on left shift
                                //
                        case Binary.Operator.LeftShift:
-                               IntConstant ic = right.ToInt (loc);
+                               IntConstant ic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
                                if (ic == null){
-                                       Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+                                       Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
                                        return null;
                                }
-                               int lshift_val = ic.Value;
-
-                               IntConstant lic;
-                               if ((lic = left.ConvertToInt ()) != null)
-                                       return new IntConstant (lic.Value << lshift_val);
 
-                               UIntConstant luic;
-                               if ((luic = left.ConvertToUInt ()) != null)
-                                       return new UIntConstant (luic.Value << lshift_val);
-
-                               LongConstant llc;
-                               if ((llc = left.ConvertToLong ()) != null)
-                                       return new LongConstant (llc.Value << lshift_val);
-
-                               ULongConstant lulc;
-                               if ((lulc = left.ConvertToULong ()) != null)
-                                       return new ULongConstant (lulc.Value << lshift_val);
-
-                               Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
+                               int lshift_val = ic.Value;
+                               if (left.Type == TypeManager.uint64_type)
+                                       return new ULongConstant (((ULongConstant)left).Value << lshift_val, left.Location);
+                               if (left.Type == TypeManager.int64_type)
+                                       return new LongConstant (((LongConstant)left).Value << lshift_val, left.Location);
+                               if (left.Type == TypeManager.uint32_type)
+                                       return new UIntConstant (((UIntConstant)left).Value << lshift_val, left.Location);
+
+                               left = left.ConvertImplicitly (ec, TypeManager.int32_type);
+                               if (left.Type == TypeManager.int32_type)
+                                       return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location);
+
+                               Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
                                break;
 
                                //
                                // There is no overflow checking on right shift
                                //
                        case Binary.Operator.RightShift:
-                               IntConstant sic = right.ToInt (loc);
+                               IntConstant sic = right.ConvertImplicitly (ec, TypeManager.int32_type) as IntConstant;
                                if (sic == null){
-                                       Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+                                       Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc); ;
                                        return null;
                                }
                                int rshift_val = sic.Value;
-
-                               IntConstant ric;
-                               if ((ric = left.ConvertToInt ()) != null)
-                                       return new IntConstant (ric.Value >> rshift_val);
-
-                               UIntConstant ruic;
-                               if ((ruic = left.ConvertToUInt ()) != null)
-                                       return new UIntConstant (ruic.Value >> rshift_val);
-
-                               LongConstant rlc;
-                               if ((rlc = left.ConvertToLong ()) != null)
-                                       return new LongConstant (rlc.Value >> rshift_val);
-
-                               ULongConstant rulc;
-                               if ((rulc = left.ConvertToULong ()) != null)
-                                       return new ULongConstant (rulc.Value >> rshift_val);
-
-                               Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
+                               if (left.Type == TypeManager.uint64_type)
+                                       return new ULongConstant (((ULongConstant)left).Value >> rshift_val, left.Location);
+                               if (left.Type == TypeManager.int64_type)
+                                       return new LongConstant (((LongConstant)left).Value >> rshift_val, left.Location);
+                               if (left.Type == TypeManager.uint32_type)
+                                       return new UIntConstant (((UIntConstant)left).Value >> rshift_val, left.Location);
+
+                               left = left.ConvertImplicitly (ec, TypeManager.int32_type);
+                               if (left.Type == TypeManager.int32_type)
+                                       return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location);
+
+                               Binary.Error_OperatorCannotBeApplied (ec, left, right, oper, loc);
                                break;
 
-                       case Binary.Operator.LogicalAnd:
-                               if (left is BoolConstant && right is BoolConstant){
-                                       return new BoolConstant (
-                                               ((BoolConstant) left).Value &&
-                                               ((BoolConstant) right).Value);
-                               }
-                               break;
-
-                       case Binary.Operator.LogicalOr:
-                               if (left is BoolConstant && right is BoolConstant){
-                                       return new BoolConstant (
-                                               ((BoolConstant) left).Value ||
-                                               ((BoolConstant) right).Value);
-                               }
-                               break;
-                               
                        case Binary.Operator.Equality:
-                               if (left is BoolConstant && right is BoolConstant){
-                                       return new BoolConstant (
-                                               ((BoolConstant) left).Value ==
-                                               ((BoolConstant) right).Value);
-                               
-                               }
-                               if (left is NullLiteral){
-                                       if (right is NullLiteral)
-                                               return new BoolConstant (true);
-                                       else if (right is StringConstant)
-                                               return new BoolConstant (
-                                                       ((StringConstant) right).Value == null);
-                               } else if (right is NullLiteral){
-                                       if (left is NullLiteral)
-                                               return new BoolConstant (true);
-                                       else if (left is StringConstant)
+                               if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
+                                       if (left.IsNull || right.IsNull) {
+                                               return ReducedExpression.Create (
+                                                       new BoolConstant (left.IsNull == right.IsNull, left.Location).Resolve (ec),
+                                                       new Binary (oper, left, right));
+                                       }
+
+                                       if (left is StringConstant && right is StringConstant)
                                                return new BoolConstant (
-                                                       ((StringConstant) left).Value == null);
-                               }
-                               if (left is StringConstant && right is StringConstant){
-                                       return new BoolConstant (
-                                               ((StringConstant) left).Value ==
-                                               ((StringConstant) right).Value);
-                                       
+                                                       ((StringConstant) left).Value == ((StringConstant) right).Value, left.Location);
+
+                                       return null;
                                }
 
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1087,35 +872,24 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.Inequality:
-                               if (left is BoolConstant && right is BoolConstant){
-                                       return new BoolConstant (
-                                               ((BoolConstant) left).Value !=
-                                               ((BoolConstant) right).Value);
-                               }
-                               if (left is NullLiteral){
-                                       if (right is NullLiteral)
-                                               return new BoolConstant (false);
-                                       else if (right is StringConstant)
-                                               return new BoolConstant (
-                                                       ((StringConstant) right).Value != null);
-                               } else if (right is NullLiteral){
-                                       if (left is NullLiteral)
-                                               return new BoolConstant (false);
-                                       else if (left is StringConstant)
+                               if (TypeManager.IsReferenceType (lt) && TypeManager.IsReferenceType (lt)) {
+                                       if (left.IsNull || right.IsNull) {
+                                               return ReducedExpression.Create (
+                                                       new BoolConstant (left.IsNull != right.IsNull, left.Location).Resolve (ec),
+                                                       new Binary (oper, left, right));
+                                       }
+
+                                       if (left is StringConstant && right is StringConstant)
                                                return new BoolConstant (
-                                                       ((StringConstant) left).Value != null);
-                               }
-                               if (left is StringConstant && right is StringConstant){
-                                       return new BoolConstant (
-                                               ((StringConstant) left).Value !=
-                                               ((StringConstant) right).Value);
-                                       
+                                                       ((StringConstant) left).Value != ((StringConstant) right).Value, left.Location);
+
+                                       return null;
                                }
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1140,11 +914,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.LessThan:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1169,11 +942,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
                                
                        case Binary.Operator.GreaterThan:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1198,11 +970,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.GreaterThanOrEqual:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1227,11 +998,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.LessThanOrEqual:
-                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
-                               if (left == null || right == null)
+                               if (!DoBinaryNumericPromotions (ec, ref left, ref right))
                                        return null;
 
                                bool_res = false;
@@ -1256,7 +1026,7 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
                        }
                                        
                        return null;