internal static void DecodeMethodImplAttribute <T, TAttributeSyntaxNode, TAttributeData, TAttributeLocation>( ref DecodeWellKnownAttributeArguments <TAttributeSyntaxNode, TAttributeData, TAttributeLocation> arguments, CommonMessageProvider messageProvider) where T : CommonMethodWellKnownAttributeData, new() where TAttributeSyntaxNode : SyntaxNode where TAttributeData : AttributeData { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); MethodImplOptions options; var attribute = arguments.Attribute; if (attribute.CommonConstructorArguments.Length == 1) { if (attribute.AttributeConstructor.Parameters[0].Type.SpecialType == SpecialType.System_Int16) { options = (MethodImplOptions)attribute.CommonConstructorArguments[0].DecodeValue <short>(SpecialType.System_Int16); } else { options = attribute.CommonConstructorArguments[0].DecodeValue <MethodImplOptions>(SpecialType.System_Enum); } // low two bits should only be set via MethodCodeType property if (((int)options & 3) != 0) { messageProvider.ReportInvalidAttributeArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, attribute); options = options & ~(MethodImplOptions)3; } } else { options = default(MethodImplOptions); } MethodImplAttributes codeType = MethodImplAttributes.IL; int position = 1; foreach (var namedArg in attribute.CommonNamedArguments) { if (namedArg.Key == "MethodCodeType") { var value = (MethodImplAttributes)namedArg.Value.DecodeValue <int>(SpecialType.System_Enum); if (value < 0 || value > MethodImplAttributes.Runtime) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, attribute.AttributeClass, "MethodCodeType"); } else { codeType = value; } } position++; } arguments.GetOrCreateData <T>().SetMethodImplementation(arguments.Index, (MethodImplAttributes)options | codeType); }
internal static void DecodeStructLayoutAttribute <TTypeWellKnownAttributeData, TAttributeSyntaxNode, TAttributeData, TAttributeLocation>( ref DecodeWellKnownAttributeArguments <TAttributeSyntaxNode, TAttributeData, TAttributeLocation> arguments, CharSet defaultCharSet, int defaultAutoLayoutSize, CommonMessageProvider messageProvider) where TTypeWellKnownAttributeData : CommonTypeWellKnownAttributeData, new() where TAttributeSyntaxNode : SyntaxNode where TAttributeData : AttributeData { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); var attribute = arguments.Attribute; CharSet charSet = (defaultCharSet != Cci.Constants.CharSet_None) ? defaultCharSet : CharSet.Ansi; int? size = null; int? pack = null; int? alignment = null; bool hasErrors = false; LayoutKind kind = attribute.CommonConstructorArguments[0].DecodeValue <LayoutKind>(StarkPlatform.Compiler.SpecialType.System_Enum); switch (kind) { case LayoutKind.Auto: case LayoutKind.Explicit: case LayoutKind.Sequential: break; default: messageProvider.ReportInvalidAttributeArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, attribute); hasErrors = true; break; } int position = 1; foreach (var namedArg in attribute.CommonNamedArguments) { switch (namedArg.Key) { case "charset": charSet = namedArg.Value.DecodeValue <CharSet>(SpecialType.System_Enum); switch (charSet) { case Cci.Constants.CharSet_None: charSet = CharSet.Ansi; break; case CharSet.Ansi: case Cci.Constants.CharSet_Auto: case CharSet.Unicode: break; default: messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, attribute.AttributeClass, namedArg.Key); hasErrors = true; break; } break; case "pack": pack = namedArg.Value.DecodeValue <int>(SpecialType.System_Int32); // only powers of 2 less or equal to 128 are allowed: if (pack > 128 || (pack & (pack - 1)) != 0) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, attribute.AttributeClass, namedArg.Key); hasErrors = true; } break; case "align": alignment = namedArg.Value.DecodeValue <int>(SpecialType.System_Int32); // only powers of 2 less or equal to 128 are allowed: if (alignment > 128 || (alignment & (alignment - 1)) != 0) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, attribute.AttributeClass, namedArg.Key); hasErrors = true; } break; case "size": size = namedArg.Value.DecodeValue <int>(StarkPlatform.Compiler.SpecialType.System_Int32); if (size < 0) { messageProvider.ReportInvalidNamedArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, position, attribute.AttributeClass, namedArg.Key); hasErrors = true; } break; } position++; } if (!hasErrors) { if (kind == LayoutKind.Auto && size == null && pack != null) { // If size is unspecified // C# emits size=0 // VB emits size=1 if the type is a struct, auto-layout and has alignment specified; 0 otherwise size = defaultAutoLayoutSize; } arguments.GetOrCreateData <TTypeWellKnownAttributeData>().SetStructLayout(new TypeLayout(kind, size ?? 0, (byte)(pack ?? 0), (byte)(alignment ?? 0)), charSet); } }
internal static void Decode(ref DecodeWellKnownAttributeArguments <TAttributeSyntax, TAttributeData, TAttributeLocation> arguments, AttributeTargets target, CommonMessageProvider messageProvider) { Debug.Assert((object)arguments.AttributeSyntaxOpt != null); UnmanagedType unmanagedType = DecodeMarshalAsType(arguments.Attribute); switch (unmanagedType) { case Cci.Constants.UnmanagedType_CustomMarshaler: DecodeMarshalAsCustom(ref arguments, messageProvider); break; case UnmanagedType.Interface: case Cci.Constants.UnmanagedType_IDispatch: case UnmanagedType.IUnknown: DecodeMarshalAsComInterface(ref arguments, unmanagedType, messageProvider); break; case UnmanagedType.LPArray: DecodeMarshalAsArray(ref arguments, messageProvider, isFixed: false); break; case UnmanagedType.ByValArray: if (target != AttributeTargets.Field) { messageProvider.ReportMarshalUnmanagedTypeOnlyValidForFields(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, "ByValArray", arguments.Attribute); } else { DecodeMarshalAsArray(ref arguments, messageProvider, isFixed: true); } break; case Cci.Constants.UnmanagedType_SafeArray: DecodeMarshalAsSafeArray(ref arguments, messageProvider); break; case UnmanagedType.ByValTStr: if (target != AttributeTargets.Field) { messageProvider.ReportMarshalUnmanagedTypeOnlyValidForFields(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, "ByValTStr", arguments.Attribute); } else { DecodeMarshalAsFixedString(ref arguments, messageProvider); } break; case Cci.Constants.UnmanagedType_VBByRefStr: if (target == AttributeTargets.Field) { messageProvider.ReportMarshalUnmanagedTypeNotValidForFields(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, "VBByRefStr", arguments.Attribute); } else { // named parameters ignored with no error arguments.GetOrCreateData <TWellKnownAttributeData>().GetOrCreateData().SetMarshalAsSimpleType(unmanagedType); } break; default: if ((int)unmanagedType < 0 || (int)unmanagedType > MarshalPseudoCustomAttributeData.MaxMarshalInteger) { // Dev10 reports CS0647: "Error emitting attribute ..." messageProvider.ReportInvalidAttributeArgument(arguments.Diagnostics, arguments.AttributeSyntaxOpt, 0, arguments.Attribute); } else { // named parameters ignored with no error arguments.GetOrCreateData <TWellKnownAttributeData>().GetOrCreateData().SetMarshalAsSimpleType(unmanagedType); } break; } }