Merge pull request #409 from Alkarex/patch-1
[mono.git] / mcs / mcs / constant.cs
index 3532c7d33fc85dc2ee58a8090ee5a466467795fa..e13e300f35c75e10c1c629c8c6b2a52dfd1b5d13 100644 (file)
@@ -7,6 +7,7 @@
 //
 // Copyright 2001-2003 Ximian, Inc.
 // Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 
 using System;
@@ -57,7 +58,7 @@ namespace Mono.CSharp {
                }
 #endif
 
-               public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
+               public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
                {
                        if (!expl && IsLiteral && 
                                BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (target) &&
@@ -65,7 +66,7 @@ namespace Mono.CSharp {
                                ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
                                        GetValueAsLiteral (), TypeManager.CSharpName (target));
                        } else {
-                               base.Error_ValueCannotBeConverted (ec, loc, target, expl);
+                               base.Error_ValueCannotBeConverted (ec, target, expl);
                        }
                }
 
@@ -73,11 +74,16 @@ namespace Mono.CSharp {
                {
                        Constant c = ConvertImplicitly (type);
                        if (c == null)
-                               Error_ValueCannotBeConverted (ec, loc, type, false);
+                               Error_ValueCannotBeConverted (ec, type, false);
 
                        return c;
                }
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return false;
+               }
+
                public virtual Constant ConvertImplicitly (TypeSpec type)
                {
                        if (this.type == type)
@@ -154,8 +160,11 @@ namespace Mono.CSharp {
                                        return new NullConstant (t, loc);
                        }
 
-                       throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'",
-                               v, TypeManager.CSharpName (t));
+#if STATIC
+                       throw new InternalErrorException ("Constant value `{0}' has unexpected underlying type `{1}'", v, t.GetSignatureForError ());
+#else
+                       return null;
+#endif
                }
 
                public override Expression CreateExpressionTree (ResolveContext ec)
@@ -242,35 +251,52 @@ namespace Mono.CSharp {
                        return this;
                }
 
-               /// <summary>
-               ///   Attempts to do a compile-time folding of a constant cast.
-               /// </summary>
-               public Constant TryReduce (ResolveContext ec, TypeSpec target_type, Location loc)
+               //
+               // Attempts to do a compile-time folding of a constant cast and handles
+               // error reporting for constant overlows only, on normal conversion
+               // errors returns null
+               // 
+               public Constant Reduce (ResolveContext ec, TypeSpec target_type)
                {
                        try {
-                               return TryReduce (ec, target_type);
-                       }
-                       catch (OverflowException) {
+                               return TryReduceConstant (ec, target_type);
+                       } catch (OverflowException) {
                                if (ec.ConstantCheckState && Type.BuiltinType != BuiltinTypeSpec.Type.Decimal) {
                                        ec.Report.Error (221, loc,
                                                "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)",
                                                GetValueAsLiteral (), target_type.GetSignatureForError ());
                                } else {
-                                       Error_ValueCannotBeConverted (ec, loc, target_type, false);
+                                       Error_ValueCannotBeConverted (ec, target_type, false);
                                }
 
                                return New.Constantify (target_type, loc);
                        }
                }
 
-               Constant TryReduce (ResolveContext ec, TypeSpec target_type)
+               public Constant TryReduce (ResolveContext rc, TypeSpec targetType)
                {
-                       if (Type == target_type)
+                       try {
+                               return TryReduceConstant (rc, targetType);
+                       } catch (OverflowException) {
+                               return null;
+                       }
+               }
+
+               Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
+               {
+                       if (Type == target_type) {
+                               //
+                               // Reducing literal value produces a new constant. Syntactically 10 is not same as (int)10 
+                               //
+                               if (IsLiteral)
+                                       return CreateConstantFromValue (target_type, GetValue (), loc);
+
                                return this;
+                       }
 
                        Constant c;
-                       if (TypeManager.IsEnumType (target_type)) {
-                               c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
+                       if (target_type.IsEnum) {
+                               c = TryReduceConstant (ec, EnumSpec.GetUnderlyingType (target_type));
                                if (c == null)
                                        return null;
 
@@ -366,11 +392,11 @@ namespace Mono.CSharp {
                        eclass = ExprClass.Value;
                }
 
-               public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl)
+               public override void Error_ValueCannotBeConverted (ResolveContext ec, TypeSpec target, bool expl)
                {
                        try {
                                ConvertExplicitly (true, target);
-                               base.Error_ValueCannotBeConverted (ec, loc, target, expl);
+                               base.Error_ValueCannotBeConverted (ec, target, expl);
                        }
                        catch
                        {
@@ -427,9 +453,9 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        if (Value)
-                               ec.Emit (OpCodes.Ldc_I4_1);
+                               ec.EmitInt (1);
                        else
-                               ec.Emit (OpCodes.Ldc_I4_0);
+                               ec.EmitInt (0);
                }
 
                public override bool IsDefaultValue {
@@ -1945,7 +1971,7 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        if (Value == null) {
-                               ec.Emit (OpCodes.Ldnull);
+                               ec.EmitNull ();
                                return;
                        }
 
@@ -2050,7 +2076,7 @@ namespace Mono.CSharp {
 
                public override void Emit (EmitContext ec)
                {
-                       ec.Emit (OpCodes.Ldnull);
+                       ec.EmitNull ();
 
                        // Only to make verifier happy
                        if (type.IsGenericParameter)
@@ -2152,7 +2178,7 @@ namespace Mono.CSharp {
                        //
                        // Emits null pointer
                        //
-                       ec.Emit (OpCodes.Ldc_I4_0);
+                       ec.EmitInt (0);
                        ec.Emit (OpCodes.Conv_U);
                }
        }