You've already forked linux-packaging-mono
Imported Upstream version 5.16.0.100
Former-commit-id: 38faa55fb9669e35e7d8448b15c25dc447f25767
This commit is contained in:
parent
0a9828183b
commit
7d7f676260
@@ -95,13 +95,8 @@ namespace System.Reflection.Emit {
|
||||
public virtual void SetConstant (object defaultValue)
|
||||
{
|
||||
if (position > 0) {
|
||||
Type t = methodb.GetParameterType (position - 1);
|
||||
if (defaultValue != null && t != defaultValue.GetType ()) {
|
||||
if(!t.IsEnum || t.UnderlyingSystemType != defaultValue.GetType ())
|
||||
throw new ArgumentException ("Constant does not match the defined type.");
|
||||
}
|
||||
if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof (DateTime))
|
||||
throw new ArgumentException ("" + t + " is not a supported constant type.");
|
||||
TypeBuilder.SetConstantValue (methodb.GetParameterType (position - 1),
|
||||
defaultValue, ref defaultValue);
|
||||
}
|
||||
|
||||
def_value = defaultValue;
|
||||
|
@@ -1903,6 +1903,125 @@ namespace System.Reflection.Emit
|
||||
{
|
||||
return base.IsAssignableFrom (typeInfo);
|
||||
}
|
||||
|
||||
internal static bool SetConstantValue (Type destType, Object value, ref Object destValue)
|
||||
{
|
||||
// Mono: This is based on the CoreCLR
|
||||
// TypeBuilder.SetConstantValue except it writes to an
|
||||
// out argument instead of doing an icall, and it uses
|
||||
// TypeCode instead of CorElementType (like
|
||||
// MonoTypeEnum) which we don't have in our corlib and
|
||||
// our member fields are different.
|
||||
|
||||
// This is a helper function that is used by ParameterBuilder, PropertyBuilder,
|
||||
// and FieldBuilder to validate a default value and save it in the meta-data.
|
||||
|
||||
if (value != null) {
|
||||
Type type = value.GetType ();
|
||||
|
||||
// We should allow setting a constant value on a ByRef parameter
|
||||
if (destType.IsByRef)
|
||||
destType = destType.GetElementType ();
|
||||
|
||||
// Convert nullable types to their underlying type.
|
||||
// This is necessary for nullable enum types to pass the IsEnum check that's coming next.
|
||||
destType = Nullable.GetUnderlyingType (destType) ?? destType;
|
||||
|
||||
if (destType.IsEnum)
|
||||
{
|
||||
// | UnderlyingSystemType | Enum.GetUnderlyingType() | IsEnum
|
||||
// ----------------------------------|---------------------------|---------------------------|---------
|
||||
// runtime Enum Type | self | underlying type of enum | TRUE
|
||||
// EnumBuilder | underlying type of enum | underlying type of enum* | TRUE
|
||||
// TypeBuilder of enum types** | underlying type of enum | Exception | TRUE
|
||||
// TypeBuilder of enum types (baked) | runtime enum type | Exception | TRUE
|
||||
|
||||
// *: the behavior of Enum.GetUnderlyingType(EnumBuilder) might change in the future
|
||||
// so let's not depend on it.
|
||||
// **: created with System.Enum as the parent type.
|
||||
|
||||
// The above behaviors might not be the most consistent but we have to live with them.
|
||||
|
||||
Type underlyingType;
|
||||
EnumBuilder enumBldr;
|
||||
TypeBuilder typeBldr;
|
||||
if ((enumBldr = destType as EnumBuilder) != null) {
|
||||
underlyingType = enumBldr.GetEnumUnderlyingType ();
|
||||
|
||||
// The constant value supplied should match either the baked enum type or its underlying type
|
||||
// we don't need to compare it with the EnumBuilder itself because you can never have an object of that type
|
||||
if (!((enumBldr.GetTypeBuilder ().is_created && type == enumBldr.GetTypeBuilder ().created) ||
|
||||
type == underlyingType))
|
||||
throw_argument_ConstantDoesntMatch ();
|
||||
} else if ((typeBldr = destType as TypeBuilder) != null) {
|
||||
underlyingType = typeBldr.underlying_type;
|
||||
|
||||
// The constant value supplied should match either the baked enum type or its underlying type
|
||||
// typeBldr.m_enumUnderlyingType is null if the user hasn't created a "value__" field on the enum
|
||||
if (underlyingType == null || (type != typeBldr.UnderlyingSystemType && type != underlyingType))
|
||||
throw_argument_ConstantDoesntMatch ();
|
||||
} else {
|
||||
// must be a runtime Enum Type
|
||||
|
||||
// Debug.Assert(destType is RuntimeType, "destType is not a runtime type, an EnumBuilder, or a TypeBuilder.");
|
||||
|
||||
underlyingType = Enum.GetUnderlyingType (destType);
|
||||
|
||||
// The constant value supplied should match either the enum itself or its underlying type
|
||||
if (type != destType && type != underlyingType)
|
||||
throw_argument_ConstantDoesntMatch ();
|
||||
}
|
||||
|
||||
type = underlyingType;
|
||||
} else {
|
||||
// Note that it is non CLS compliant if destType != type. But RefEmit never guarantees CLS-Compliance.
|
||||
if (!destType.IsAssignableFrom (type))
|
||||
throw_argument_ConstantDoesntMatch ();
|
||||
}
|
||||
|
||||
TypeCode corType = Type.GetTypeCode (type);
|
||||
|
||||
switch (corType)
|
||||
{
|
||||
case TypeCode.Byte:
|
||||
case TypeCode.SByte:
|
||||
case TypeCode.Boolean:
|
||||
case TypeCode.Int16:
|
||||
case TypeCode.UInt16:
|
||||
case TypeCode.Char:
|
||||
case TypeCode.Int32:
|
||||
case TypeCode.UInt32:
|
||||
case TypeCode.Single:
|
||||
case TypeCode.Int64:
|
||||
case TypeCode.UInt64:
|
||||
case TypeCode.Double:
|
||||
destValue = value;
|
||||
return true;
|
||||
case TypeCode.String:
|
||||
destValue = value;
|
||||
return true;
|
||||
case TypeCode.DateTime:
|
||||
//date is a I8 representation
|
||||
long ticks = ((DateTime)value).Ticks;
|
||||
destValue = ticks;
|
||||
return true;
|
||||
default:
|
||||
throw new ArgumentException(type.ToString() + " is not a supported constant type.");
|
||||
}
|
||||
} else {
|
||||
// A null default value in metadata is permissible even for non-nullable value types.
|
||||
// (See ECMA-335 II.15.4.1.4 "The .param directive" and II.22.9 "Constant" for details.)
|
||||
// This is how the Roslyn compilers generally encode `default(TValueType)` default values.
|
||||
|
||||
destValue = null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void throw_argument_ConstantDoesntMatch ()
|
||||
{
|
||||
throw new ArgumentException("Constant does not match the defined type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user