//
// Author:
// Miguel de Icaza (miguel@ximian.com)
-// Marek Safar (marek.safar@seznam.cz)
+// Marek Safar (marek.safar@gmail.com)
//
// Copyright 2001-2003 Ximian, Inc.
// Copyright 2003-2008 Novell, Inc.
+// Copyright 2011-2013 Xamarin Inc
//
using System;
}
#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) &&
BuiltinTypeSpec.IsPrimitiveTypeOrDecimal (type)) {
ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
- GetValueAsLiteral (), TypeManager.CSharpName (target));
+ GetValueAsLiteral (), target.GetSignatureForError ());
} else {
- base.Error_ValueCannotBeConverted (ec, loc, target, expl);
+ base.Error_ValueCannotBeConverted (ec, target, expl);
}
}
{
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)
return this;
- if (Convert.ImplicitNumericConversion (this, type) == null)
+ if (!Convert.ImplicitNumericConversionExists (this.type, type))
return null;
bool fail;
// reached, by calling Convert.ImplicitStandardConversionExists
//
throw new InternalErrorException ("Missing constant conversion between `{0}' and `{1}'",
- TypeManager.CSharpName (Type), TypeManager.CSharpName (type));
+ Type.GetSignatureForError (), type.GetSignatureForError ());
}
- return CreateConstant (type, constant_value, loc);
+ return CreateConstantFromValue (type, constant_value, loc);
}
//
// Returns a constant instance based on Type
//
- public static Constant CreateConstant (TypeSpec t, object v, Location loc)
- {
- return CreateConstantFromValue (t, v, loc);
- }
-
public static Constant CreateConstantFromValue (TypeSpec t, object v, Location loc)
{
switch (t.BuiltinType) {
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)
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)
+ {
+ try {
+ return TryReduceConstant (rc, targetType);
+ } catch (OverflowException) {
+ return null;
+ }
+ }
+
+ Constant TryReduceConstant (ResolveContext ec, TypeSpec target_type)
{
- if (Type == 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;
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,
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
{
ec.Report.Error (31, loc, "Constant value `{0}' cannot be converted to a `{1}'",
- GetValue ().ToString (), TypeManager.CSharpName (target));
+ GetValue ().ToString (), target.GetSignatureForError ());
}
}
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 {
public override void Emit (EmitContext ec)
{
if (Value == null) {
- ec.Emit (OpCodes.Ldnull);
+ ec.EmitNull ();
return;
}
public override void Emit (EmitContext ec)
{
- ec.Emit (OpCodes.Ldnull);
+ ec.EmitNull ();
// Only to make verifier happy
if (type.IsGenericParameter)
if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
return null;
- if (TypeManager.IsReferenceType (targetType))
+ if (TypeSpec.IsReferenceType (targetType))
return new NullConstant (targetType, loc);
if (targetType.IsNullableType)
//
// Emits null pointer
//
- ec.Emit (OpCodes.Ldc_I4_0);
+ ec.EmitInt (0);
ec.Emit (OpCodes.Conv_U);
}
}
/// 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;
this.side_effect = side_effect;
}
+ public override bool IsSideEffectFree {
+ get {
+ return false;
+ }
+ }
+
public override object GetValue ()
{
return value.GetValue ();