+ public override Expression CreateExpressionTree (ResolveContext ec)
+ {
+ if (type == InternalType.Null || type == TypeManager.object_type) {
+ // Optimized version, also avoids referencing literal internal type
+ Arguments args = new Arguments (1);
+ args.Add (new Argument (this));
+ return CreateExpressionFactoryCall (ec, "Constant", args);
+ }
+
+ return base.CreateExpressionTree (ec);
+ }
+
+ protected override Expression DoResolve (ResolveContext ec)
+ {
+ return this;
+ }
+
+ public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType)
+ {
+ // Type it as string cast
+ if (targetType == TypeManager.object_type || targetType == TypeManager.null_type)
+ enc.Encode (TypeManager.string_type);
+
+ var ac = targetType as ArrayContainer;
+ if (ac != null) {
+ if (ac.Rank != 1)
+ base.EncodeAttributeValue (rc, enc, targetType);
+ else
+ enc.Stream.Write (uint.MaxValue);
+ } else {
+ enc.Stream.Write (byte.MaxValue);
+ }
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ ec.Emit (OpCodes.Ldnull);
+
+ // Only to make verifier happy
+ if (TypeManager.IsGenericParameter (type))
+ ec.Emit (OpCodes.Unbox_Any, type);
+ }
+
+ public override string ExprClassName {
+ get {
+ return GetSignatureForError ();
+ }
+ }
+
+ public override string GetSignatureForError ()
+ {
+ return "null";
+ }
+
+ public override Constant ConvertExplicitly (bool inCheckedContext, TypeSpec targetType)
+ {
+ if (targetType.IsPointer) {
+ if (IsLiteral || this is NullPointer)
+ return new EmptyConstantCast (new NullPointer (loc), targetType);
+
+ return null;
+ }
+
+ // Exlude internal compiler types
+ if (targetType == InternalType.AnonymousMethod)
+ return null;
+
+ if (!IsLiteral && !Convert.ImplicitStandardConversionExists (this, targetType))
+ return null;
+
+ if (TypeManager.IsReferenceType (targetType))
+ return new NullConstant (targetType, loc);
+
+ if (TypeManager.IsNullableType (targetType))
+ return Nullable.LiftedNull.Create (targetType, loc);
+
+ return null;
+ }
+
+ public override Constant ConvertImplicitly (ResolveContext rc, TypeSpec targetType)
+ {
+ return ConvertExplicitly (false, targetType);
+ }
+
+ public override object GetValue ()
+ {
+ return null;
+ }
+
+ public override bool IsDefaultValue {
+ get { return true; }
+ }
+
+ public override bool IsNegative {
+ get { return false; }
+ }
+
+ public override bool IsNull {
+ get { return true; }
+ }
+
+ public override bool IsZeroInteger {
+ get { return true; }
+ }
+ }
+
+ /// <summary>
+ /// The value is constant, but when emitted has a side effect. This is
+ /// 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 Constant value;
+ Expression side_effect;
+
+ public SideEffectConstant (Constant value, Expression side_effect, Location loc) : base (loc)
+ {
+ this.value = value;
+ while (side_effect is SideEffectConstant)
+ side_effect = ((SideEffectConstant) side_effect).side_effect;
+ this.side_effect = side_effect;
+ }
+
+ public override string AsString ()
+ {
+ return value.AsString ();
+ }
+
+ protected override Expression DoResolve (ResolveContext rc)
+ {
+ value = value.Resolve (rc);
+
+ type = value.Type;
+ eclass = ExprClass.Value;
+ return this;
+ }
+
+ public override object GetValue ()
+ {
+ return value.GetValue ();
+ }
+
+ public override void Emit (EmitContext ec)
+ {
+ side_effect.EmitSideEffect (ec);
+ value.Emit (ec);
+ }
+
+ public override void EmitSideEffect (EmitContext ec)
+ {
+ side_effect.EmitSideEffect (ec);
+ value.EmitSideEffect (ec);
+ }
+
+ public override bool IsDefaultValue {
+ get { return value.IsDefaultValue; }
+ }
+
+ public override bool IsNegative {
+ get { return value.IsNegative; }
+ }
+
+ public override bool IsZeroInteger {
+ get { return value.IsZeroInteger; }
+ }
+
+ public override Constant ConvertExplicitly (bool in_checked_context, TypeSpec target_type)
+ {
+ Constant new_value = value.ConvertExplicitly (in_checked_context, target_type);
+ return new_value == null ? null : new SideEffectConstant (new_value, side_effect, new_value.Location);
+ }
+ }
+}