X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fcfold.cs;h=d2b8c0bf07a2223e366b148e557b84bfc2d7b6f9;hb=06a1ce9f42b0feb1ee6f56c0010a0ffe89ca3249;hp=a8775a54f93ee53e749b0d1a3dede4b27711416e;hpb=3d693eeb90339833968d66c3dc9fde2fa3ba2cef;p=mono.git diff --git a/mcs/mcs/cfold.cs b/mcs/mcs/cfold.cs index a8775a54f93..d2b8c0bf07a 100644 --- a/mcs/mcs/cfold.cs +++ b/mcs/mcs/cfold.cs @@ -5,16 +5,16 @@ // 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 { - static Type[] binary_promotions = new Type[] { + 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 }; @@ -25,21 +25,40 @@ namespace Mono.CSharp { // On success, the types of `lc' and `rc' on output will always match, // and the pair will be one of: // - static void DoBinaryNumericPromotions (ref Constant left, ref Constant right) + static bool DoBinaryNumericPromotions (ref Constant left, ref Constant right) { Type ltype = left.Type; Type rtype = right.Type; foreach (Type t in binary_promotions) { - if (t == ltype || t == rtype) { - left = left.ConvertImplicitly (t); - right = right.ConvertImplicitly (t); - return; - } + if (t == ltype) + return t == rtype || ConvertPromotion (ref right, ref left, t); + + if (t == rtype) + return t == ltype || ConvertPromotion (ref left, ref right, t); } left = left.ConvertImplicitly (TypeManager.int32_type); right = right.ConvertImplicitly (TypeManager.int32_type); + return left != null && right != null; + } + + static bool ConvertPromotion (ref Constant prim, ref Constant second, Type type) + { + Constant c = prim.ConvertImplicitly (type); + if (c != null) { + prim = c; + return true; + } + + if (type == TypeManager.uint32_type) { + type = TypeManager.int64_type; + prim = prim.ConvertImplicitly (type); + second = second.ConvertImplicitly (type); + return prim != null && second != null; + } + + return false; } internal static void Error_CompileTimeOverflow (Location loc) @@ -55,16 +74,31 @@ namespace Mono.CSharp { static public Constant BinaryFold (EmitContext 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; bool bool_res; - Constant result = null; if (lt == TypeManager.bool_type && lt == rt) { bool lv = ((BoolConstant) left ).Value; @@ -137,8 +171,7 @@ namespace Mono.CSharp { switch (oper){ case Binary.Operator.BitwiseOr: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; if (left is IntConstant){ @@ -165,8 +198,7 @@ namespace Mono.CSharp { break; case Binary.Operator.BitwiseAnd: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; /// @@ -196,8 +228,7 @@ namespace Mono.CSharp { break; case Binary.Operator.ExclusiveOr: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; if (left is IntConstant){ @@ -237,6 +268,9 @@ namespace Mono.CSharp { return null; } + if (lt == TypeManager.null_type && lt == rt) + return left; + // // handle "E operator + (E x, U y)" // handle "E operator + (Y y, E x)" @@ -266,8 +300,7 @@ namespace Mono.CSharp { return new EnumConstant (result, lt); } - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -388,8 +421,7 @@ namespace Mono.CSharp { return new EnumConstant (result, lt); } - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -480,8 +512,7 @@ namespace Mono.CSharp { return result; case Binary.Operator.Multiply: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -571,8 +602,7 @@ namespace Mono.CSharp { break; case Binary.Operator.Division: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -666,8 +696,7 @@ namespace Mono.CSharp { break; case Binary.Operator.Modulus: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; try { @@ -753,7 +782,7 @@ namespace Mono.CSharp { case Binary.Operator.LeftShift: IntConstant ic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant; if (ic == null){ - Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt); + Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); return null; } @@ -769,7 +798,7 @@ namespace Mono.CSharp { if (left.Type == TypeManager.int32_type) return new IntConstant (((IntConstant)left).Value << lshift_val, left.Location); - Binary.Error_OperatorCannotBeApplied (loc, "<<", lt, rt); + Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); break; // @@ -778,7 +807,7 @@ namespace Mono.CSharp { case Binary.Operator.RightShift: IntConstant sic = right.ConvertImplicitly (TypeManager.int32_type) as IntConstant; if (sic == null){ - Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt); + Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); ; return null; } int rshift_val = sic.Value; @@ -793,18 +822,18 @@ namespace Mono.CSharp { if (left.Type == TypeManager.int32_type) return new IntConstant (((IntConstant)left).Value >> rshift_val, left.Location); - Binary.Error_OperatorCannotBeApplied (loc, ">>", lt, rt); + Binary.Error_OperatorCannotBeApplied (left, right, oper, loc); break; case Binary.Operator.Equality: - if (left is NullConstant){ - if (right is NullConstant) + 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 NullConstant){ - if (left is NullConstant) + } else if (right is NullLiteral) { + if (left is NullLiteral) return new BoolConstant (true, left.Location); else if (left is StringConstant) return new BoolConstant ( @@ -817,8 +846,7 @@ namespace Mono.CSharp { } - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; @@ -846,14 +874,14 @@ namespace Mono.CSharp { return new BoolConstant (bool_res, left.Location); case Binary.Operator.Inequality: - if (left is NullConstant){ - if (right is NullConstant) + 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 NullConstant){ - if (left is NullConstant) + } else if (right is NullLiteral) { + if (left is NullLiteral) return new BoolConstant (false, left.Location); else if (left is StringConstant) return new BoolConstant ( @@ -866,8 +894,7 @@ namespace Mono.CSharp { } - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; @@ -895,8 +922,7 @@ namespace Mono.CSharp { return new BoolConstant (bool_res, left.Location); case Binary.Operator.LessThan: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; @@ -924,8 +950,7 @@ namespace Mono.CSharp { return new BoolConstant (bool_res, left.Location); case Binary.Operator.GreaterThan: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; @@ -953,8 +978,7 @@ namespace Mono.CSharp { return new BoolConstant (bool_res, left.Location); case Binary.Operator.GreaterThanOrEqual: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false; @@ -982,8 +1006,7 @@ namespace Mono.CSharp { return new BoolConstant (bool_res, left.Location); case Binary.Operator.LessThanOrEqual: - DoBinaryNumericPromotions (ref left, ref right); - if (left == null || right == null) + if (!DoBinaryNumericPromotions (ref left, ref right)) return null; bool_res = false;