+ //
+ // Null constant can have its own type, think of `default (Foo)'
+ //
+ public class NullConstant : Constant
+ {
+ public NullConstant (TypeSpec type, Location loc)
+ : base (loc)
+ {
+ eclass = ExprClass.Value;
+ this.type = type;
+ }
+
+ 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 == InternalType.Null)
+ enc.Encode (TypeManager.string_type);
+
+ 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 {
+ enc.Encode (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 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.Kind == MemberKind.InternalCompilerType && targetType != InternalType.Dynamic && targetType != InternalType.Null)
+ 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 string GetSignatureForError ()
+ {
+ return "null";
+ }
+
+ public override object GetValue ()
+ {
+ return null;
+ }
+
+ public override string GetValueAsLiteral ()
+ {
+ return GetSignatureForError ();
+ }
+
+ 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; }
+ }
+ }
+