public void TestInvalidExplicitTypeLayout() { { DefType type = _testModule.GetType("Explicit", "MisalignedPointer"); Assert.Throws <TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } { DefType type = _testModule.GetType("Explicit", "MisalignedByRef"); Assert.Throws <TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } }
public void TestInvalidByRefLikeTypes() { { DefType type = _testModule.GetType("IsByRefLike", "Invalid"); Assert.Throws <TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } { DefType type = _testModule.GetType("IsByRefLike", "ComposedInvalid"); Assert.Throws <TypeSystemException.TypeLoadException>(() => type.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields)); } }
/// <summary> /// Validates that it will be possible to create an EEType for '<paramref name="type"/>'. /// </summary> public static void CheckCanGenerateEEType(NodeFactory factory, TypeDesc type) { // Don't validate generic definitons if (type.IsGenericDefinition) { return; } // It must be possible to create an EEType for the base type of this type TypeDesc baseType = type.BaseType; if (baseType != null) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(baseType); } // We need EETypes for interfaces foreach (var intf in type.RuntimeInterfaces) { // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(intf); } // Validate classes, structs, enums, interfaces, and delegates DefType defType = type as DefType; if (defType != null) { // Ensure we can compute the type layout defType.ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); // // The fact that we generated an EEType means that someone can call RuntimeHelpers.RunClassConstructor. // We need to make sure this is possible. // if (factory.TypeSystemContext.HasLazyStaticConstructor(defType)) { defType.ComputeStaticFieldLayout(StaticLayoutKind.StaticRegionSizesAndFields); } // Make sure instantiation length matches the expectation // TODO: it might be more resonable for the type system to enforce this (also for methods) if (defType.Instantiation.Length != defType.GetTypeDefinition().Instantiation.Length) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } foreach (TypeDesc typeArg in defType.Instantiation) { // ByRefs, pointers, function pointers, and System.Void are never valid instantiation arguments if (typeArg.IsByRef || typeArg.IsPointer || typeArg.IsFunctionPointer || typeArg.IsVoid) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // TODO: validate constraints } } // Validate parameterized types ParameterizedType parameterizedType = type as ParameterizedType; if (parameterizedType != null) { TypeDesc parameterType = parameterizedType.ParameterType; // Make sure EEType can be created for this. factory.NecessaryTypeSymbol(parameterType); if (parameterizedType.IsArray) { if (parameterType.IsPointer || parameterType.IsFunctionPointer) { // Arrays of pointers and function pointers are not currently supported throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } int elementSize = parameterType.GetElementSize(); if (elementSize >= ushort.MaxValue) { // Element size over 64k can't be encoded in the GCDesc throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadValueClassTooLarge, parameterType); } } // Validate we're not constructing a type over a ByRef if (parameterType.IsByRef) { // CLR compat note: "ldtoken int32&&" will actually fail with a message about int32&; "ldtoken int32&[]" // will fail with a message about being unable to create an array of int32&. This is a middle ground. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // It might seem reasonable to disallow array of void, but the CLR doesn't prevent that too hard. // E.g. "newarr void" will fail, but "newarr void[]" or "ldtoken void[]" will succeed. } // Function pointer EETypes are not currently supported if (type.IsFunctionPointer) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } }