Add some new classes/enums/delegates for 2.0 and some new CAS unit tests
[mono.git] / mcs / mcs / cfold.cs
old mode 100755 (executable)
new mode 100644 (file)
index ecc3fa2..9e8a5a1
@@ -4,7 +4,7 @@
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
 //
-// (C) 2002 Ximian, Inc.
+// (C) 2002, 2003 Ximian, Inc.
 //
 
 using System;
@@ -26,8 +26,10 @@ namespace Mono.CSharp {
                //   (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 (Binary.Operator oper,
+               static void DoConstantNumericPromotions (EmitContext ec, Binary.Operator oper,
                                                         ref Constant left, ref Constant right,
                                                         Location loc)
                {
@@ -50,23 +52,29 @@ namespace Mono.CSharp {
 
                                if (!(right is FloatConstant))
                                        right = right.ToFloat (loc);
-                               return;
+;                              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);
                                }
 
@@ -93,14 +101,54 @@ namespace Mono.CSharp {
                        } 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, othe operands are
+                               // operand is of type sbyte, short or int, the operands are
                                // converted to type long.
                                //
-                               if (!(left is UIntConstant))
+                               Constant other;
+                               if (left is UIntConstant)
+                                       other = right;
+                               else
+                                       other = left;
+
+                               // Nothing to do.
+                               if (other is UIntConstant)
+                                       return;
+
+                               IntConstant ic = other as IntConstant;
+                               if (ic != null){
+                                       if (ic.Value >= 0){
+                                               if (left == other)
+                                                       left = new UIntConstant ((uint) ic.Value, ic.Location);
+                                               else
+                                                       right = new UIntConstant ((uint) ic.Value, ic.Location);
+                                               return;
+                                       }
+                               }
+                               
+                               if (other is SByteConstant || other is ShortConstant || ic != null){
+                                       left = left.ToLong (loc);
+                                       right = right.ToLong (loc);
+                               } else {
                                        left = left.ToUInt (loc);
-                               else if (!(right is UIntConstant))
-                                       right = right.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 (left is EnumConstant)
+                                       left = ((EnumConstant) left).Child;
+                               if (right is EnumConstant)
+                                       right = ((EnumConstant) right).Child;
+
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
+                               return;
+
                        } else {
                                //
                                // Force conversions to int32
@@ -130,24 +178,37 @@ namespace Mono.CSharp {
                        Type rt = right.Type;
                        Type result_type = null;
                        bool bool_res;
-                       
+
                        //
                        // Enumerator folding
                        //
                        if (rt == lt && left is EnumConstant)
                                result_type = lt;
 
+                       //
+                       // During an enum evaluation, we need to unwrap enumerations
+                       //
+                       if (ec.InEnumContext){
+                               if (left is EnumConstant)
+                                       left = ((EnumConstant) left).Child;
+                               
+                               if (right is EnumConstant)
+                                       right = ((EnumConstant) right).Child;
+                       }
+
+                       Type wrap_as;
+                       Constant result = null;
                        switch (oper){
                        case Binary.Operator.BitwiseOr:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
-                               
+
                                if (left is IntConstant){
                                        IntConstant v;
                                        int res = ((IntConstant) left).Value | ((IntConstant) right).Value;
                                        
-                                       v = new IntConstant (res);
+                                       v = new IntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -156,7 +217,7 @@ namespace Mono.CSharp {
                                        UIntConstant v;
                                        uint res = ((UIntConstant)left).Value | ((UIntConstant)right).Value;
                                        
-                                       v = new UIntConstant (res);
+                                       v = new UIntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -165,7 +226,7 @@ namespace Mono.CSharp {
                                        LongConstant v;
                                        long res = ((LongConstant)left).Value | ((LongConstant)right).Value;
                                        
-                                       v = new LongConstant (res);
+                                       v = new LongConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -175,7 +236,27 @@ namespace Mono.CSharp {
                                        ulong res = ((ULongConstant)left).Value |
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
+                                       v = new ULongConstant (res, left.Location);
+                                       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, left.Location);
+                                       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, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -184,7 +265,7 @@ namespace Mono.CSharp {
                                break;
                                
                        case Binary.Operator.BitwiseAnd:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
                                
@@ -192,7 +273,7 @@ namespace Mono.CSharp {
                                        IntConstant v;
                                        int res = ((IntConstant) left).Value & ((IntConstant) right).Value;
                                        
-                                       v = new IntConstant (res);
+                                       v = new IntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -201,7 +282,7 @@ namespace Mono.CSharp {
                                        UIntConstant v;
                                        uint res = ((UIntConstant)left).Value & ((UIntConstant)right).Value;
                                        
-                                       v = new UIntConstant (res);
+                                       v = new UIntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -210,7 +291,7 @@ namespace Mono.CSharp {
                                        LongConstant v;
                                        long res = ((LongConstant)left).Value & ((LongConstant)right).Value;
                                        
-                                       v = new LongConstant (res);
+                                       v = new LongConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -220,7 +301,27 @@ namespace Mono.CSharp {
                                        ulong res = ((ULongConstant)left).Value &
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
+                                       v = new ULongConstant (res, left.Location);
+                                       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, left.Location);
+                                       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, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -229,7 +330,7 @@ namespace Mono.CSharp {
                                break;
 
                        case Binary.Operator.ExclusiveOr:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
                                
@@ -237,7 +338,7 @@ namespace Mono.CSharp {
                                        IntConstant v;
                                        int res = ((IntConstant) left).Value ^ ((IntConstant) right).Value;
                                        
-                                       v = new IntConstant (res);
+                                       v = new IntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -246,7 +347,7 @@ namespace Mono.CSharp {
                                        UIntConstant v;
                                        uint res = ((UIntConstant)left).Value ^ ((UIntConstant)right).Value;
                                        
-                                       v = new UIntConstant (res);
+                                       v = new UIntConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -255,7 +356,7 @@ namespace Mono.CSharp {
                                        LongConstant v;
                                        long res = ((LongConstant)left).Value ^ ((LongConstant)right).Value;
                                        
-                                       v = new LongConstant (res);
+                                       v = new LongConstant (res, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -265,7 +366,27 @@ namespace Mono.CSharp {
                                        ulong res = ((ULongConstant)left).Value ^
                                                ((ULongConstant)right).Value;
                                        
-                                       v = new ULongConstant (res);
+                                       v = new ULongConstant (res, left.Location);
+                                       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, left.Location);
+                                       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, left.Location);
                                        if (result_type == null)
                                                return v;
                                        else
@@ -282,16 +403,42 @@ namespace Mono.CSharp {
                                // 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);
+                                                       ((StringConstant) right).Value, left.Location);
                                        
                                        return null;
                                }
 
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               //
+                               // 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;
+                                       }
+
+                                       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)
+                                               return null;
+
+                                       wrap_as = right.Type;
+                               }
+
+                               result = null;
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -306,7 +453,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value +
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               result = new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -317,7 +464,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value +
                                                                         ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               result = new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -327,8 +474,8 @@ namespace Mono.CSharp {
                                                else
                                                        res = unchecked (((ULongConstant) left).Value +
                                                                         ((ULongConstant) right).Value);
-                                               
-                                               return new ULongConstant (res);
+
+                                               result = new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -339,7 +486,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value +
                                                                         ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               result = new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -350,7 +497,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value +
                                                                         ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               result = new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -361,17 +508,69 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value +
                                                                         ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               result = new IntConstant (res, left.Location);
+                                       } else if (left is DecimalConstant) {
+                                               decimal res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DecimalConstant) left).Value +
+                                                               ((DecimalConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DecimalConstant) left).Value +
+                                                               ((DecimalConstant) right).Value);
+
+                                               result = new DecimalConstant (res, left.Location);
                                        } else {
-                                               throw new Exception ( "Unexepected input: " + left);
+                                               throw new Exception ( "Unexepected addition input: " + left);
                                        }
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
                                }
-                               break;
+
+                               if (wrap_as != null)
+                                       return result.TryReduce (ec, wrap_as, loc);
+                               else
+                                       return result;
 
                        case Binary.Operator.Subtraction:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               //
+                               // 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;
+                                       }
+                                       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)
+                                               return null;
+
+                                       wrap_as = right.Type;
+                               }
+
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -386,7 +585,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((DoubleConstant) left).Value -
                                                                         ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               result = new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
@@ -397,7 +596,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((FloatConstant) left).Value -
                                                                         ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               result = new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
@@ -408,7 +607,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((ULongConstant) left).Value -
                                                                         ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               result = new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
@@ -419,7 +618,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((LongConstant) left).Value -
                                                                         ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               result = new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
@@ -430,7 +629,7 @@ namespace Mono.CSharp {
                                                        res = unchecked (((UIntConstant) left).Value -
                                                                         ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               result = new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
@@ -441,17 +640,32 @@ namespace Mono.CSharp {
                                                        res = unchecked (((IntConstant) left).Value -
                                                                         ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               result = new IntConstant (res, left.Location);
+                                       } else if (left is DecimalConstant) {
+                                               decimal res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DecimalConstant) left).Value -
+                                                               ((DecimalConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DecimalConstant) left).Value -
+                                                               ((DecimalConstant) right).Value);
+
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
-                                               throw new Exception ( "Unexepected input: " + left);
+                                               throw new Exception ( "Unexepected subtraction input: " + left);
                                        }
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
                                }
-                               break;
+
+                               if (wrap_as != null)
+                                       return result.TryReduce (ec, wrap_as, loc);
+
+                               return result;
                                
                        case Binary.Operator.Multiply:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -461,69 +675,80 @@ namespace Mono.CSharp {
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((DoubleConstant) left).Value *
-                                                                      ((DoubleConstant) right).Value);
+                                                               ((DoubleConstant) right).Value);
                                                else
                                                        res = unchecked (((DoubleConstant) left).Value *
-                                                                        ((DoubleConstant) right).Value);
+                                                               ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               return new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((FloatConstant) left).Value *
-                                                                      ((FloatConstant) right).Value);
+                                                               ((FloatConstant) right).Value);
                                                else
                                                        res = unchecked (((FloatConstant) left).Value *
-                                                                        ((FloatConstant) right).Value);
+                                                               ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               return new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((ULongConstant) left).Value *
-                                                                      ((ULongConstant) right).Value);
+                                                               ((ULongConstant) right).Value);
                                                else
                                                        res = unchecked (((ULongConstant) left).Value *
-                                                                        ((ULongConstant) right).Value);
+                                                               ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               return new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((LongConstant) left).Value *
-                                                                      ((LongConstant) right).Value);
+                                                               ((LongConstant) right).Value);
                                                else
                                                        res = unchecked (((LongConstant) left).Value *
-                                                                        ((LongConstant) right).Value);
+                                                               ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               return new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((UIntConstant) left).Value *
-                                                                      ((UIntConstant) right).Value);
+                                                               ((UIntConstant) right).Value);
                                                else
                                                        res = unchecked (((UIntConstant) left).Value *
-                                                                        ((UIntConstant) right).Value);
+                                                               ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               return new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
                                                if (ec.ConstantCheckState)
                                                        res = checked (((IntConstant) left).Value *
-                                                                      ((IntConstant) right).Value);
+                                                               ((IntConstant) right).Value);
                                                else
                                                        res = unchecked (((IntConstant) left).Value *
-                                                                        ((IntConstant) right).Value);
+                                                               ((IntConstant) right).Value);
+
+                                               return new IntConstant (res, left.Location);
+                                       } else if (left is DecimalConstant) {
+                                               decimal res;
 
-                                               return new IntConstant (res);
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DecimalConstant) left).Value *
+                                                               ((DecimalConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DecimalConstant) left).Value *
+                                                               ((DecimalConstant) right).Value);
+
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
-                                               throw new Exception ( "Unexepected input: " + left);
+                                               throw new Exception ( "Unexepected multiply input: " + left);
                                        }
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
@@ -531,7 +756,7 @@ namespace Mono.CSharp {
                                break;
 
                        case Binary.Operator.Division:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -541,77 +766,92 @@ namespace Mono.CSharp {
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((DoubleConstant) left).Value /
-                                                                      ((DoubleConstant) right).Value);
+                                                               ((DoubleConstant) right).Value);
                                                else
                                                        res = unchecked (((DoubleConstant) left).Value /
-                                                                        ((DoubleConstant) right).Value);
+                                                               ((DoubleConstant) right).Value);
                                                
-                                               return new DoubleConstant (res);
+                                               return new DoubleConstant (res, left.Location);
                                        } else if (left is FloatConstant){
                                                float res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((FloatConstant) left).Value /
-                                                                      ((FloatConstant) right).Value);
+                                                               ((FloatConstant) right).Value);
                                                else
                                                        res = unchecked (((FloatConstant) left).Value /
-                                                                        ((FloatConstant) right).Value);
+                                                               ((FloatConstant) right).Value);
                                                
-                                               return new FloatConstant (res);
+                                               return new FloatConstant (res, left.Location);
                                        } else if (left is ULongConstant){
                                                ulong res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((ULongConstant) left).Value /
-                                                                      ((ULongConstant) right).Value);
+                                                               ((ULongConstant) right).Value);
                                                else
                                                        res = unchecked (((ULongConstant) left).Value /
-                                                                        ((ULongConstant) right).Value);
+                                                               ((ULongConstant) right).Value);
                                                
-                                               return new ULongConstant (res);
+                                               return new ULongConstant (res, left.Location);
                                        } else if (left is LongConstant){
                                                long res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((LongConstant) left).Value /
-                                                                      ((LongConstant) right).Value);
+                                                               ((LongConstant) right).Value);
                                                else
                                                        res = unchecked (((LongConstant) left).Value /
-                                                                        ((LongConstant) right).Value);
+                                                               ((LongConstant) right).Value);
                                                
-                                               return new LongConstant (res);
+                                               return new LongConstant (res, left.Location);
                                        } else if (left is UIntConstant){
                                                uint res;
                                                
                                                if (ec.ConstantCheckState)
                                                        res = checked (((UIntConstant) left).Value /
-                                                                      ((UIntConstant) right).Value);
+                                                               ((UIntConstant) right).Value);
                                                else
                                                        res = unchecked (((UIntConstant) left).Value /
-                                                                        ((UIntConstant) right).Value);
+                                                               ((UIntConstant) right).Value);
                                                
-                                               return new UIntConstant (res);
+                                               return new UIntConstant (res, left.Location);
                                        } else if (left is IntConstant){
                                                int res;
 
                                                if (ec.ConstantCheckState)
                                                        res = checked (((IntConstant) left).Value /
-                                                                      ((IntConstant) right).Value);
+                                                               ((IntConstant) right).Value);
                                                else
                                                        res = unchecked (((IntConstant) left).Value /
-                                                                        ((IntConstant) right).Value);
+                                                               ((IntConstant) right).Value);
 
-                                               return new IntConstant (res);
+                                               return new IntConstant (res, left.Location);
+                                       } else if (left is DecimalConstant) {
+                                               decimal res;
+
+                                               if (ec.ConstantCheckState)
+                                                       res = checked (((DecimalConstant) left).Value /
+                                                               ((DecimalConstant) right).Value);
+                                               else
+                                                       res = unchecked (((DecimalConstant) left).Value /
+                                                               ((DecimalConstant) right).Value);
+
+                                               return new DecimalConstant (res, left.Location);
                                        } else {
-                                               throw new Exception ( "Unexepected input: " + left);
+                                               throw new Exception ( "Unexepected division input: " + left);
                                        }
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
+
+                               } catch (DivideByZeroException) {
+                                       Report.Error (020, loc, "Division by constant zero");
                                }
+                               
                                break;
                                
                        case Binary.Operator.Modulus:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -626,7 +866,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;
                                                
@@ -637,7 +877,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;
                                                
@@ -648,7 +888,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;
                                                
@@ -659,7 +899,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;
                                                
@@ -670,7 +910,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;
 
@@ -681,10 +921,12 @@ 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 input: " + left);
+                                               throw new Exception ( "Unexepected modulus input: " + left);
                                        }
+                               } catch (DivideByZeroException){
+                                       Report.Error (020, loc, "Division by constant zero");
                                } catch (OverflowException){
                                        Error_CompileTimeOverflow (loc);
                                }
@@ -703,19 +945,19 @@ namespace Mono.CSharp {
 
                                IntConstant lic;
                                if ((lic = left.ConvertToInt ()) != null)
-                                       return new IntConstant (lic.Value << lshift_val);
+                                       return new IntConstant (lic.Value << lshift_val, left.Location);
 
                                UIntConstant luic;
                                if ((luic = left.ConvertToUInt ()) != null)
-                                       return new UIntConstant (luic.Value << lshift_val);
+                                       return new UIntConstant (luic.Value << lshift_val, left.Location);
 
                                LongConstant llc;
                                if ((llc = left.ConvertToLong ()) != null)
-                                       return new LongConstant (llc.Value << lshift_val);
+                                       return new LongConstant (llc.Value << lshift_val, left.Location);
 
                                ULongConstant lulc;
                                if ((lulc = left.ConvertToULong ()) != null)
-                                       return new ULongConstant (lulc.Value << lshift_val);
+                                       return new ULongConstant (lulc.Value << lshift_val, left.Location);
 
                                Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt);
                                break;
@@ -733,19 +975,19 @@ namespace Mono.CSharp {
 
                                IntConstant ric;
                                if ((ric = left.ConvertToInt ()) != null)
-                                       return new IntConstant (ric.Value >> rshift_val);
+                                       return new IntConstant (ric.Value >> rshift_val, left.Location);
 
                                UIntConstant ruic;
                                if ((ruic = left.ConvertToUInt ()) != null)
-                                       return new UIntConstant (ruic.Value >> rshift_val);
+                                       return new UIntConstant (ruic.Value >> rshift_val, left.Location);
 
                                LongConstant rlc;
                                if ((rlc = left.ConvertToLong ()) != null)
-                                       return new LongConstant (rlc.Value >> rshift_val);
+                                       return new LongConstant (rlc.Value >> rshift_val, left.Location);
 
                                ULongConstant rulc;
                                if ((rulc = left.ConvertToULong ()) != null)
-                                       return new ULongConstant (rulc.Value >> rshift_val);
+                                       return new ULongConstant (rulc.Value >> rshift_val, left.Location);
 
                                Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt);
                                break;
@@ -754,7 +996,7 @@ namespace Mono.CSharp {
                                if (left is BoolConstant && right is BoolConstant){
                                        return new BoolConstant (
                                                ((BoolConstant) left).Value &&
-                                               ((BoolConstant) right).Value);
+                                               ((BoolConstant) right).Value, left.Location);
                                }
                                break;
 
@@ -762,7 +1004,7 @@ namespace Mono.CSharp {
                                if (left is BoolConstant && right is BoolConstant){
                                        return new BoolConstant (
                                                ((BoolConstant) left).Value ||
-                                               ((BoolConstant) right).Value);
+                                               ((BoolConstant) right).Value, left.Location);
                                }
                                break;
                                
@@ -770,17 +1012,30 @@ namespace Mono.CSharp {
                                if (left is BoolConstant && right is BoolConstant){
                                        return new BoolConstant (
                                                ((BoolConstant) left).Value ==
-                                               ((BoolConstant) right).Value);
+                                               ((BoolConstant) right).Value, left.Location);
                                
                                }
+                               if (left is NullLiteral){
+                                       if (right is NullLiteral)
+                                               return new BoolConstant (true, left.Location);
+                                       else if (right is StringConstant)
+                                               return new BoolConstant (
+                                                       ((StringConstant) right).Value == null, left.Location);
+                               } else if (right is NullLiteral){
+                                       if (left is NullLiteral)
+                                               return new BoolConstant (true, left.Location);
+                                       else if (left is StringConstant)
+                                               return new BoolConstant (
+                                                       ((StringConstant) left).Value == null, left.Location);
+                               }
                                if (left is StringConstant && right is StringConstant){
                                        return new BoolConstant (
                                                ((StringConstant) left).Value ==
-                                               ((StringConstant) right).Value);
+                                               ((StringConstant) right).Value, left.Location);
                                        
                                }
-                               
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -806,21 +1061,34 @@ 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);
+                                               ((BoolConstant) right).Value, left.Location);
+                               }
+                               if (left is NullLiteral){
+                                       if (right is NullLiteral)
+                                               return new BoolConstant (false, left.Location);
+                                       else if (right is StringConstant)
+                                               return new BoolConstant (
+                                                       ((StringConstant) right).Value != null, left.Location);
+                               } else if (right is NullLiteral){
+                                       if (left is NullLiteral)
+                                               return new BoolConstant (false, left.Location);
+                                       else if (left is StringConstant)
+                                               return new BoolConstant (
+                                                       ((StringConstant) left).Value != null, left.Location);
                                }
                                if (left is StringConstant && right is StringConstant){
                                        return new BoolConstant (
                                                ((StringConstant) left).Value !=
-                                               ((StringConstant) right).Value);
+                                               ((StringConstant) right).Value, left.Location);
                                        
                                }
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -846,10 +1114,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.LessThan:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -875,10 +1143,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
                                
                        case Binary.Operator.GreaterThan:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -904,10 +1172,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.GreaterThanOrEqual:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -933,10 +1201,10 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
 
                        case Binary.Operator.LessThanOrEqual:
-                               DoConstantNumericPromotions (oper, ref left, ref right, loc);
+                               DoConstantNumericPromotions (ec, oper, ref left, ref right, loc);
                                if (left == null || right == null)
                                        return null;
 
@@ -962,7 +1230,7 @@ namespace Mono.CSharp {
                                else
                                        return null;
 
-                               return new BoolConstant (bool_res);
+                               return new BoolConstant (bool_res, left.Location);
                        }
                                        
                        return null;