Don't throw when loading expressions wrongly marked as constants. Fixes #4105
[mono.git] / mcs / mcs / constant.cs
index 71c8493189f04f06858b43fdc5658854228b7c9e..beb9512e6e5a5b7e31e432333e0b5fd8ff16e7ca 100644 (file)
@@ -7,6 +7,7 @@
 //
 // Copyright 2001-2003 Ximian, Inc.
 // Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
 //
 
 using System;
@@ -78,6 +79,11 @@ namespace Mono.CSharp {
                        return c;
                }
 
+               public override bool ContainsEmitWithAwait ()
+               {
+                       return false;
+               }
+
                public virtual Constant ConvertImplicitly (TypeSpec type)
                {
                        if (this.type == type)
@@ -150,19 +156,22 @@ namespace Mono.CSharp {
                                if (t.IsNullableType)
                                        return Nullable.LiftedNull.Create (t, loc);
 
-                               if (TypeManager.IsReferenceType (t))
+                               if (TypeSpec.IsReferenceType (t))
                                        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)
                {
                        Arguments args = new Arguments (2);
                        args.Add (new Argument (this));
-                       args.Add (new Argument (new TypeOf (new TypeExpression (type, loc), loc)));
+                       args.Add (new Argument (new TypeOf (type, loc)));
 
                        return CreateExpressionFactoryCall (ec, "Constant", args);
                }
@@ -269,7 +278,7 @@ namespace Mono.CSharp {
                                return this;
 
                        Constant c;
-                       if (TypeManager.IsEnumType (target_type)) {
+                       if (target_type.IsEnum) {
                                c = TryReduce (ec, EnumSpec.GetUnderlyingType (target_type));
                                if (c == null)
                                        return null;
@@ -309,7 +318,13 @@ namespace Mono.CSharp {
                
                public virtual bool IsOneInteger {
                        get { return false; }
-               }               
+               }
+
+               public override bool IsSideEffectFree {
+                       get {
+                               return true;
+                       }
+               }
 
                //
                // Returns true iff 1) the stack type of this is one of Object, 
@@ -421,9 +436,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 {
@@ -1939,7 +1954,7 @@ namespace Mono.CSharp {
                public override void Emit (EmitContext ec)
                {
                        if (Value == null) {
-                               ec.Emit (OpCodes.Ldnull);
+                               ec.EmitNull ();
                                return;
                        }
 
@@ -2020,24 +2035,31 @@ namespace Mono.CSharp {
 
                public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
                {
-                       // Type it as string cast
-                       if (targetType.BuiltinType == BuiltinTypeSpec.Type.Object)
+                       switch (targetType.BuiltinType) {
+                       case BuiltinTypeSpec.Type.Object:
+                               // Type it as string cast
                                enc.Encode (rc.Module.Compiler.BuiltinTypes.String);
-
-                       var ac = targetType as ArrayContainer;
-                       if (ac != null) {
-                               if (ac.Rank != 1 || ac.Element.IsArray)
-                                       base.EncodeAttributeValue (rc, enc, targetType);
-                               else
-                                       enc.Encode (uint.MaxValue);
-                       } else {
+                               goto case BuiltinTypeSpec.Type.String;
+                       case BuiltinTypeSpec.Type.String:
+                       case BuiltinTypeSpec.Type.Type:
                                enc.Encode (byte.MaxValue);
+                               return;
+                       default:
+                               var ac = targetType as ArrayContainer;
+                               if (ac != null && ac.Rank == 1 && !ac.Element.IsArray) {
+                                       enc.Encode (uint.MaxValue);
+                                       return;
+                               }
+
+                               break;
                        }
+
+                       base.EncodeAttributeValue (rc, enc, targetType);
                }
 
                public override void Emit (EmitContext ec)
                {
-                       ec.Emit (OpCodes.Ldnull);
+                       ec.EmitNull ();
 
                        // Only to make verifier happy
                        if (type.IsGenericParameter)
@@ -2066,7 +2088,7 @@ namespace Mono.CSharp {
                        if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
                                return null;
 
-                       if (TypeManager.IsReferenceType (targetType))
+                       if (TypeSpec.IsReferenceType (targetType))
                                return new NullConstant (targetType, loc);
 
                        if (targetType.IsNullableType)
@@ -2139,7 +2161,7 @@ namespace Mono.CSharp {
                        //
                        // Emits null pointer
                        //
-                       ec.Emit (OpCodes.Ldc_I4_0);
+                       ec.EmitInt (0);
                        ec.Emit (OpCodes.Conv_U);
                }
        }
@@ -2149,7 +2171,8 @@ namespace Mono.CSharp {
        ///   used by BitwiseAnd to ensure that the second expression is invoked
        ///   regardless of the value of the left side.  
        /// </summary>
-       public class SideEffectConstant : Constant {
+       public class SideEffectConstant : Constant
+       {
                public readonly Constant value;
                Expression side_effect;
                
@@ -2165,6 +2188,12 @@ namespace Mono.CSharp {
                        this.side_effect = side_effect;
                }
 
+               public override bool IsSideEffectFree {
+                       get {
+                               return false;
+                       }
+               }
+
                public override object GetValue ()
                {
                        return value.GetValue ();