Exemplo n.º 1
0
		public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
		{
			//
			// From any value-type to the type object.
			//
			if (target_type == TypeManager.object_type || target_type == InternalType.Dynamic) {
				//
				// A pointer type cannot be converted to object
				//
				if (expr_type.IsPointer)
					return null;

				if (!TypeManager.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}
			
			//
			// From any value-type to the type System.ValueType.
			//
			if (target_type == TypeManager.value_type) {
				if (!TypeManager.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			if (target_type == TypeManager.enum_type) {
				//
				// From any enum-type to the type System.Enum.
				//
				if (TypeManager.IsEnumType (expr_type))
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			//
			// From a nullable-type to a reference type, if a boxing conversion exists from
			// the underlying type to the reference type
			//
			if (TypeManager.IsNullableType (expr_type)) {
				if (!TypeManager.IsReferenceType (target_type))
					return null;

				var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);

				// "cast" underlying type to target type to emit correct InvalidCastException when
				// underlying hierarchy changes without recompilation
				if (res != null && expr != null)
					res = new UnboxCast (res, target_type);

				return res;
			}

			if (TypeSpec.IsBaseClass (expr_type, target_type, false)) {
				//
				// Don't box same type arguments
				//
				if (TypeManager.IsGenericParameter (expr_type) && expr_type != target_type)
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

				return null;
			}

			// This code is kind of mirrored inside ImplicitStandardConversionExists
			// with the small distinction that we only probe there
			//
			// Always ensure that the code here and there is in sync

			// from any class-type S to any interface-type T.
			if (target_type.IsInterface) {
				if (expr_type.ImplementsInterface (target_type, true) &&
					(TypeManager.IsGenericParameter (expr_type) || TypeManager.IsValueType (expr_type))) {
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
				}
			}

			return null;
		}
Exemplo n.º 2
0
		public static Expression ImplicitBoxingConversion (Expression expr, TypeSpec expr_type, TypeSpec target_type)
		{
			switch (target_type.BuiltinType) {
			//
			// From any non-nullable-value-type to the type object and dynamic
			//
			case BuiltinTypeSpec.Type.Object:
			case BuiltinTypeSpec.Type.Dynamic:
			//
			// From any non-nullable-value-type to the type System.ValueType
			//
			case BuiltinTypeSpec.Type.ValueType:
				//
				// No ned to check for nullable type as underlying type is always convertible
				//
				if (!TypeSpec.IsValueType (expr_type))
					return null;

				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

			case BuiltinTypeSpec.Type.Enum:
				//
				// From any enum-type to the type System.Enum.
				//
				if (expr_type.IsEnum)
					return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);

				break;
			}

			//
			// From a nullable-type to a reference type, if a boxing conversion exists from
			// the underlying type to the reference type
			//
			if (expr_type.IsNullableType) {
				if (!TypeSpec.IsReferenceType (target_type))
					return null;

				var res = ImplicitBoxingConversion (expr, Nullable.NullableInfo.GetUnderlyingType (expr_type), target_type);

				// "cast" underlying type to target type to emit correct InvalidCastException when
				// underlying hierarchy changes without recompilation
				if (res != null && expr != null)
					res = new UnboxCast (res, target_type);

				return res;
			}

			//
			// A value type has a boxing conversion to an interface type I if it has a boxing conversion
			// to an interface or delegate type I0 and I0 is variance-convertible to I
			//
			if (target_type.IsInterface && TypeSpec.IsValueType (expr_type) && expr_type.ImplementsInterface (target_type, true)) {
				return expr == null ? EmptyExpression.Null : new BoxedCast (expr, target_type);
			}

			return null;
		}
Exemplo n.º 3
0
		public override bool Resolve (BlockContext ec)
		{
			using (ec.With (ResolveContext.Options.CatchScope, true)) {
				if (type_expr != null) {
					TypeExpr te = type_expr.ResolveAsTypeTerminal (ec, false);
					if (te == null)
						return false;

					type = te.Type;
					if (type != TypeManager.exception_type && !TypeSpec.IsBaseClass (type, TypeManager.exception_type, false)) {
						ec.Report.Error (155, loc, "The type caught or thrown must be derived from System.Exception");
					} else if (li != null) {
						li.Type = type;
						li.PrepareForFlowAnalysis (ec);

						// source variable is at the top of the stack
						Expression source = new EmptyExpression (li.Type);
						if (li.Type.IsGenericParameter)
							source = new UnboxCast (source, li.Type);

						assign = new CompilerAssign (new LocalVariableReference (li, loc), source, loc);
						Block.AddScopeStatement (new StatementExpression (assign));
					}
				}

				return Block.Resolve (ec);
			}
		}