2 // attribute.cs: Attribute Handler
4 // Author: Ravi Pratap (ravi@ximian.com)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
14 using System.Diagnostics;
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Runtime.InteropServices;
19 using System.Runtime.CompilerServices;
20 using System.Security;
21 using System.Security.Permissions;
25 namespace Mono.CSharp {
28 /// Base class for objects that can have Attributes applied to them.
30 public abstract class Attributable {
32 // Holds all attributes attached to this element
34 protected Attributes attributes;
36 public void AddAttributes (Attributes attrs, IMemberContext context)
41 if (attributes == null)
44 throw new NotImplementedException ();
46 attributes.AttachTo (this, context);
49 public Attributes OptAttributes {
59 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
61 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
64 /// Returns one AttributeTarget for this element.
66 public abstract AttributeTargets AttributeTargets { get; }
68 public abstract bool IsClsComplianceRequired ();
71 /// Gets list of valid attribute targets for explicit target declaration.
72 /// The first array item is default target. Don't break this rule.
74 public abstract string[] ValidAttributeTargets { get; }
77 public class Attribute : Expression
79 public readonly string ExplicitTarget;
80 public AttributeTargets Target;
81 readonly ATypeNameExpression expression;
83 Arguments PosArguments;
84 Arguments NamedArguments;
88 readonly bool nameEscaped;
91 // An attribute can be attached to multiple targets (e.g. multiple fields)
93 protected Attributable[] targets;
96 // A member context for the attribute, it's much easier to hold it here
97 // than trying to pull it during resolve
99 IMemberContext context;
101 public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
102 static Assembly orig_sec_assembly;
103 public static readonly object[] EmptyObject = new object [0];
105 IList<KeyValuePair<MemberExpr, NamedArgument>> named_values;
107 // Cache for parameter-less attributes
108 static Dictionary<TypeSpec, MethodSpec> att_cache;
110 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
112 this.expression = expr;
114 PosArguments = args [0];
115 NamedArguments = args [1];
118 ExplicitTarget = target;
119 this.nameEscaped = nameEscaped;
122 public Attribute Clone ()
124 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
125 a.PosArguments = PosArguments;
126 a.NamedArguments = NamedArguments;
135 public static void Reset ()
137 att_cache = new Dictionary<TypeSpec, MethodSpec> ();
141 // When the same attribute is attached to multiple fiels
142 // we use @target field as a list of targets. The attribute
143 // has to be resolved only once but emitted for each target.
145 public virtual void AttachTo (Attributable target, IMemberContext context)
147 if (this.targets == null) {
148 this.targets = new Attributable[] { target };
149 this.context = context;
153 // Resize target array
154 Attributable[] new_array = new Attributable [this.targets.Length + 1];
155 targets.CopyTo (new_array, 0);
156 new_array [targets.Length] = target;
157 this.targets = new_array;
159 // No need to update context, different targets cannot have
160 // different contexts, it's enough to remove same attributes
161 // from secondary members.
163 target.OptAttributes = null;
166 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
168 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
169 "must be fields which are not readonly, static, const or read-write properties which are " +
170 "public and not static",
174 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
176 rc.Report.Error (655, name.Location,
177 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
181 public static void Error_AttributeArgumentNotValid (IMemberContext rc, Location loc)
183 rc.Compiler.Report.Error (182, loc,
184 "An attribute argument must be a constant expression, typeof " +
185 "expression or array creation expression");
188 public void Error_MissingGuidAttribute ()
190 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
193 public void Error_MisusedExtensionAttribute ()
195 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
198 public void Error_MisusedDynamicAttribute ()
200 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
204 /// This is rather hack. We report many emit attribute error with same error to be compatible with
205 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
207 public void Error_AttributeEmitError (string inner)
209 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
210 TypeManager.CSharpName (Type), inner);
213 public void Error_InvalidSecurityParent ()
215 Error_AttributeEmitError ("it is attached to invalid parent");
224 protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
226 return expr.ResolveAsTypeTerminal (ec, false);
229 TypeSpec ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
231 TypeExpr te = ResolveAsTypeTerminal (expr, context);
235 TypeSpec t = te.Type;
239 Report.SymbolRelatedToPreviousError (t);
240 Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
246 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
248 void ResolveAttributeType ()
250 SessionReportPrinter resolve_printer = new SessionReportPrinter ();
251 ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);
253 bool t1_is_attr = false;
254 bool t2_is_attr = false;
256 ATypeNameExpression expanded = null;
259 t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
264 expanded = (ATypeNameExpression) expression.Clone (null);
265 expanded.Name += "Attribute";
267 t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
270 resolve_printer.EndSession ();
272 context.Compiler.Report.SetPrinter (prev_recorder);
275 if (t1_is_attr && t2_is_attr) {
276 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
277 GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
278 resolve_error = true;
292 resolve_printer.Merge (prev_recorder);
293 resolve_error = true;
296 public virtual TypeSpec ResolveType ()
298 if (Type == null && !resolve_error)
299 ResolveAttributeType ();
303 public override string GetSignatureForError ()
306 return TypeManager.CSharpName (Type);
308 return expression.GetSignatureForError ();
311 public bool HasSecurityAttribute {
313 PredefinedAttribute pa = PredefinedAttributes.Get.Security;
314 return pa.IsDefined && TypeManager.IsSubclassOf (type, pa.Type);
318 public bool IsValidSecurityAttribute ()
320 return HasSecurityAttribute && IsSecurityActionValid (false);
323 static bool IsValidArgumentType (TypeSpec t)
326 t = TypeManager.GetElementType (t);
328 return t == TypeManager.string_type ||
329 TypeManager.IsPrimitiveType (t) ||
330 TypeManager.IsEnumType (t) ||
331 t == TypeManager.object_type ||
332 t == TypeManager.type_type;
335 // TODO: Don't use this ambiguous value
337 get { return expression.Name; }
340 void ApplyModuleCharSet (ResolveContext rc)
342 if (Type != PredefinedAttributes.Get.DllImport)
345 if (!RootContext.ToplevelTypes.HasDefaultCharSet)
348 const string CharSetEnumMember = "CharSet";
349 if (NamedArguments == null) {
350 NamedArguments = new Arguments (1);
352 foreach (NamedArgument a in NamedArguments) {
353 if (a.Name == CharSetEnumMember)
358 var char_set = Import.ImportType (typeof (CharSet));
359 NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
360 Constant.CreateConstant (rc, char_set, RootContext.ToplevelTypes.DefaultCharSet, Location)));
363 public Report Report {
364 get { return context.Compiler.Report; }
367 public MethodSpec Resolve ()
372 resolve_error = true;
376 ResolveAttributeType ();
381 if (Type.IsAbstract) {
382 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
386 ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
387 if (obsolete_attr != null) {
388 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
392 // Try if the attribute is simple has been resolved before
393 if (PosArguments == null && NamedArguments == null) {
394 if (att_cache.TryGetValue (Type, out ctor)) {
395 resolve_error = false;
400 ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
401 ctor = ResolveConstructor (rc);
406 ApplyModuleCharSet (rc);
408 if (NamedArguments != null && !ResolveNamedArguments (rc)) {
412 resolve_error = false;
416 protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
418 if (PosArguments != null) {
420 PosArguments.Resolve (ec, out dynamic);
422 Error_AttributeArgumentNotValid (ec, loc);
427 MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
428 Type, ConstructorInfo.ConstructorName, 0, MemberKind.Constructor,
429 BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly,
430 Location) as MethodGroupExpr;
433 throw new NotImplementedException ();
435 mg = mg.OverloadResolve (ec, ref PosArguments, false, Location);
439 var constructor = (MethodSpec) mg;
443 protected virtual bool ResolveNamedArguments (ResolveContext ec)
445 int named_arg_count = NamedArguments.Count;
446 var seen_names = new List<string> (named_arg_count);
448 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
450 foreach (NamedArgument a in NamedArguments) {
451 string name = a.Name;
452 if (seen_names.Contains (name)) {
453 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
457 seen_names.Add (name);
461 Expression member = Expression.MemberLookup (ec.Compiler,
462 ec.CurrentType, Type, name, 0,
464 BindingRestriction.AccessibleOnly,
467 if (member == null) {
468 member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name, 0,
469 MemberKind.All, BindingRestriction.None,
472 if (member != null) {
473 ec.Report.SymbolRelatedToPreviousError (member.Type);
474 Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
480 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
484 if (!(member is PropertyExpr || member is FieldExpr)) {
485 Error_InvalidNamedArgument (ec, a);
489 ObsoleteAttribute obsolete_attr;
491 if (member is PropertyExpr) {
492 var pi = ((PropertyExpr) member).PropertyInfo;
494 if (!pi.HasSet || !pi.HasGet || pi.IsStatic) {
495 ec.Report.SymbolRelatedToPreviousError (pi);
496 Error_InvalidNamedArgument (ec, a);
500 if (!IsValidArgumentType (member.Type)) {
501 ec.Report.SymbolRelatedToPreviousError (pi);
502 Error_InvalidNamedArgumentType (ec, a);
506 obsolete_attr = pi.GetAttributeObsolete ();
508 var fi = ((FieldExpr) member).Spec;
510 if (fi.IsReadOnly || fi.IsStatic) {
511 Error_InvalidNamedArgument (ec, a);
515 if (!IsValidArgumentType (member.Type)) {
516 ec.Report.SymbolRelatedToPreviousError (fi);
517 Error_InvalidNamedArgumentType (ec, a);
521 obsolete_attr = fi.GetAttributeObsolete ();
524 if (obsolete_attr != null && !context.IsObsolete)
525 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
527 if (a.Type != member.Type) {
528 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
532 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
539 /// Get a string containing a list of valid targets for the attribute 'attr'
541 public string GetValidTargets ()
543 StringBuilder sb = new StringBuilder ();
544 AttributeTargets targets = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage).ValidOn;
546 if ((targets & AttributeTargets.Assembly) != 0)
547 sb.Append ("assembly, ");
549 if ((targets & AttributeTargets.Module) != 0)
550 sb.Append ("module, ");
552 if ((targets & AttributeTargets.Class) != 0)
553 sb.Append ("class, ");
555 if ((targets & AttributeTargets.Struct) != 0)
556 sb.Append ("struct, ");
558 if ((targets & AttributeTargets.Enum) != 0)
559 sb.Append ("enum, ");
561 if ((targets & AttributeTargets.Constructor) != 0)
562 sb.Append ("constructor, ");
564 if ((targets & AttributeTargets.Method) != 0)
565 sb.Append ("method, ");
567 if ((targets & AttributeTargets.Property) != 0)
568 sb.Append ("property, indexer, ");
570 if ((targets & AttributeTargets.Field) != 0)
571 sb.Append ("field, ");
573 if ((targets & AttributeTargets.Event) != 0)
574 sb.Append ("event, ");
576 if ((targets & AttributeTargets.Interface) != 0)
577 sb.Append ("interface, ");
579 if ((targets & AttributeTargets.Parameter) != 0)
580 sb.Append ("parameter, ");
582 if ((targets & AttributeTargets.Delegate) != 0)
583 sb.Append ("delegate, ");
585 if ((targets & AttributeTargets.ReturnValue) != 0)
586 sb.Append ("return, ");
588 if ((targets & AttributeTargets.GenericParameter) != 0)
589 sb.Append ("type parameter, ");
591 return sb.Remove (sb.Length - 2, 2).ToString ();
594 public AttributeUsageAttribute GetAttributeUsageAttribute ()
597 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
598 // But because a lot of attribute class code must be rewritten will be better to wait...
602 return DefaultUsageAttribute;
604 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
606 var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
608 usage_attribute.AllowMultiple = field.Value;
610 field = GetPropertyValue ("Inherited") as BoolConstant;
612 usage_attribute.Inherited = field.Value;
614 return usage_attribute;
618 /// Returns custom name of indexer
620 public string GetIndexerAttributeValue ()
623 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
624 // But because a lot of attribute class code must be rewritten will be better to wait...
630 return ((Constant) PosArguments [0].Expr).GetValue () as string;
634 /// Returns condition of ConditionalAttribute
636 public string GetConditionalAttributeValue ()
639 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
640 // But because a lot of attribute class code must be rewritten will be better to wait...
646 return ((Constant) PosArguments[0].Expr).GetValue () as string;
650 /// Creates the instance of ObsoleteAttribute from this attribute instance
652 public ObsoleteAttribute GetObsoleteAttribute ()
655 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
656 // But because a lot of attribute class code must be rewritten will be better to wait...
662 if (PosArguments == null)
663 return new ObsoleteAttribute ();
665 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
666 if (PosArguments.Count == 1)
667 return new ObsoleteAttribute (msg);
669 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
673 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
674 /// before ApplyAttribute. We need to resolve the arguments.
675 /// This situation occurs when class deps is differs from Emit order.
677 public bool GetClsCompliantAttributeValue ()
680 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
681 // But because a lot of attribute class code must be rewritten will be better to wait...
687 return ((BoolConstant) PosArguments[0].Expr).Value;
690 public TypeSpec GetCoClassAttributeValue ()
698 return GetArgumentType ();
701 public bool CheckTarget ()
703 string[] valid_targets = Owner.ValidAttributeTargets;
704 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
705 Target = Owner.AttributeTargets;
709 // TODO: we can skip the first item
710 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
711 switch (ExplicitTarget) {
712 case "return": Target = AttributeTargets.ReturnValue; return true;
713 case "param": Target = AttributeTargets.Parameter; return true;
714 case "field": Target = AttributeTargets.Field; return true;
715 case "method": Target = AttributeTargets.Method; return true;
716 case "property": Target = AttributeTargets.Property; return true;
718 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
721 StringBuilder sb = new StringBuilder ();
722 foreach (string s in valid_targets) {
726 sb.Remove (sb.Length - 2, 2);
727 Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
728 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
733 /// Tests permitted SecurityAction for assembly or other types
735 protected virtual bool IsSecurityActionValid (bool for_assembly)
737 SecurityAction action = GetSecurityActionValue ();
740 case SecurityAction.Demand:
741 case SecurityAction.Assert:
742 case SecurityAction.Deny:
743 case SecurityAction.PermitOnly:
744 case SecurityAction.LinkDemand:
745 case SecurityAction.InheritanceDemand:
750 case SecurityAction.RequestMinimum:
751 case SecurityAction.RequestOptional:
752 case SecurityAction.RequestRefuse:
758 Error_AttributeEmitError ("SecurityAction is out of range");
762 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
766 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
768 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
772 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
774 /// <returns></returns>
775 public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
777 Type orig_assembly_type = null;
779 if (Type.MemberDefinition is TypeContainer) {
780 if (!RootContext.StdLib) {
781 orig_assembly_type = System.Type.GetType (Type.GetMetaInfo ().FullName);
783 string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
784 if (orig_version_path == null) {
785 Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
789 if (orig_sec_assembly == null) {
790 string file = Path.Combine (orig_version_path, Driver.OutputFile);
791 orig_sec_assembly = Assembly.LoadFile (file);
794 orig_assembly_type = orig_sec_assembly.GetType (Type.GetMetaInfo ().FullName, true);
795 if (orig_assembly_type == null) {
796 Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
797 "was not found in previous version of assembly");
803 SecurityAttribute sa;
806 // For all non-selfreferencing security attributes we can avoid all hacks
807 if (orig_assembly_type == null) {
808 args = new object[PosArguments.Count];
809 for (int j = 0; j < args.Length; ++j) {
810 args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
813 sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
815 if (named_values != null) {
816 for (int i = 0; i < named_values.Count; ++i) {
817 PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
818 pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
822 // HACK: All security attributes have same ctor syntax
823 args = new object[] { GetSecurityActionValue () };
824 sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, args);
826 // All types are from newly created assembly but for invocation with old one we need to convert them
827 if (named_values != null) {
828 for (int i = 0; i < named_values.Count; ++i) {
829 PropertyInfo emited_pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
830 // FIXME: We are missing return type filter
831 // TODO: pi can be null
832 PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
834 pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
840 perm = sa.CreatePermission ();
841 SecurityAction action = (SecurityAction) args [0];
843 // IS is correct because for corlib we are using an instance from old corlib
844 if (!(perm is System.Security.CodeAccessPermission)) {
846 case SecurityAction.Demand:
847 action = (SecurityAction)13;
849 case SecurityAction.LinkDemand:
850 action = (SecurityAction)14;
852 case SecurityAction.InheritanceDemand:
853 action = (SecurityAction)15;
859 if (!permissions.TryGetValue (action, out ps)) {
860 if (sa is PermissionSetAttribute)
861 ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
863 ps = new PermissionSet (PermissionState.None);
865 permissions.Add (action, ps);
866 } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
867 ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
868 permissions [action] = ps;
870 ps.AddPermission (perm);
873 public Constant GetPropertyValue (string name)
875 if (named_values == null)
878 for (int i = 0; i < named_values.Count; ++i) {
879 if (named_values [i].Value.Name == name)
880 return named_values [i].Value.Expr as Constant;
887 // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
888 // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
889 // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
892 public UnmanagedMarshal GetMarshal (Attributable attr)
894 UnmanagedType UnmanagedType;
895 if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
896 UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
898 UnmanagedType = (UnmanagedType) pos_values [0];
900 object value = GetFieldValue ("SizeParamIndex");
901 if (value != null && UnmanagedType != UnmanagedType.LPArray) {
902 Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
906 object o = GetFieldValue ("ArraySubType");
907 UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
909 switch (UnmanagedType) {
910 case UnmanagedType.CustomMarshaler: {
911 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
912 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
913 if (define_custom == null) {
914 Report.RuntimeMissingSupport (Location, "set marshal info");
918 object [] args = new object [4];
919 args [0] = GetFieldValue ("MarshalTypeRef");
920 args [1] = GetFieldValue ("MarshalCookie");
921 args [2] = GetFieldValue ("MarshalType");
922 args [3] = Guid.Empty;
923 return (UnmanagedMarshal) define_custom.Invoke (null, args);
925 case UnmanagedType.LPArray: {
926 object size_const = GetFieldValue ("SizeConst");
927 object size_param_index = GetFieldValue ("SizeParamIndex");
929 if ((size_const != null) || (size_param_index != null)) {
930 MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
931 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
932 if (define_array == null) {
933 Report.RuntimeMissingSupport (Location, "set marshal info");
937 object [] args = new object [3];
938 args [0] = array_sub_type;
939 args [1] = size_const == null ? -1 : size_const;
940 args [2] = size_param_index == null ? -1 : size_param_index;
941 return (UnmanagedMarshal) define_array.Invoke (null, args);
944 return UnmanagedMarshal.DefineLPArray (array_sub_type);
946 case UnmanagedType.SafeArray:
947 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
949 case UnmanagedType.ByValArray:
950 FieldBase fm = attr as FieldBase;
952 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
955 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
957 case UnmanagedType.ByValTStr:
958 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
961 return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
965 object GetFieldValue (string name)
968 if (field_info_arr == null)
971 foreach (FieldInfo fi in field_info_arr) {
973 return GetValue (field_values_arr [i]);
979 static object GetValue (object value)
981 if (value is EnumConstant)
982 return ((EnumConstant) value).GetValue ();
989 public CharSet GetCharSetValue ()
991 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
994 public bool HasField (string fieldName)
996 if (named_values == null)
999 foreach (var na in named_values) {
1000 if (na.Value.Name == fieldName)
1007 public bool IsInternalMethodImplAttribute {
1009 if (Type != PredefinedAttributes.Get.MethodImpl)
1012 MethodImplOptions options;
1013 if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
1014 options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
1016 options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
1018 return (options & MethodImplOptions.InternalCall) != 0;
1022 public LayoutKind GetLayoutKindValue ()
1024 if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
1025 return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
1027 return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
1030 public Constant GetParameterDefaultValue (out TypeSpec type)
1032 var expr = PosArguments[0].Expr;
1034 if (expr is TypeCast)
1035 expr = ((TypeCast) expr).Child;
1038 return expr as Constant;
1041 public override bool Equals (object obj)
1043 Attribute a = obj as Attribute;
1047 return Type == a.Type && Target == a.Target;
1050 public override int GetHashCode ()
1052 return type.GetHashCode () ^ Target.GetHashCode ();
1056 /// Emit attribute for Attributable symbol
1058 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1060 var ctor = Resolve ();
1064 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage);
1065 if ((usage_attr.ValidOn & Target) == 0) {
1066 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1067 "It is valid on `{1}' declarations only",
1068 GetSignatureForError (), GetValidTargets ());
1072 var predefined = PredefinedAttributes.Get;
1074 AttributeEncoder encoder = new AttributeEncoder (false);
1076 if (PosArguments != null) {
1077 var param_types = ctor.Parameters.Types;
1078 for (int j = 0; j < PosArguments.Count; ++j) {
1079 var pt = param_types[j];
1080 if (!IsValidArgumentType (pt)) {
1081 Error_AttributeArgumentNotValid (context, loc);
1085 var arg_expr = PosArguments[j].Expr;
1087 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
1088 string v = ((StringConstant) arg_expr).Value;
1089 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
1090 context.Compiler.Report.Error (633, arg_expr.Location,
1091 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1093 } else if (Type == predefined.Guid) {
1095 string v = ((StringConstant) arg_expr).Value;
1097 } catch (Exception e) {
1098 Error_AttributeEmitError (e.Message);
1101 } else if (Type == predefined.AttributeUsage) {
1102 int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
1104 context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1105 "System.AttributeUsage");
1107 } else if (Type == predefined.MethodImpl && pt == TypeManager.short_type &&
1108 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
1109 Error_AttributeEmitError ("Incorrect argument value.");
1114 arg_expr.EncodeAttributeValue (context, encoder, pt);
1118 if (named_values != null) {
1119 encoder.Stream.Write ((ushort) named_values.Count);
1120 foreach (var na in named_values) {
1121 if (na.Key is FieldExpr)
1122 encoder.Stream.Write ((byte) 0x53);
1124 encoder.Stream.Write ((byte) 0x54);
1126 encoder.Encode (na.Key.Type);
1127 encoder.Encode (na.Value.Name);
1128 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1131 encoder.Stream.Write ((ushort) 0);
1134 byte[] cdata = encoder.ToArray ();
1137 foreach (Attributable target in targets)
1138 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1139 } catch (Exception e) {
1140 Error_AttributeEmitError (e.Message);
1144 if (!usage_attr.AllowMultiple && allEmitted != null) {
1145 if (allEmitted.ContainsKey (this)) {
1146 var a = allEmitted [this];
1148 a = new List<Attribute> (2);
1149 allEmitted [this] = a;
1153 allEmitted.Add (this, null);
1157 if (!RootContext.VerifyClsCompliance)
1160 // Here we are testing attribute arguments for array usage (error 3016)
1161 if (Owner.IsClsComplianceRequired ()) {
1162 if (PosArguments != null)
1163 PosArguments.CheckArrayAsAttribute (context.Compiler);
1165 if (NamedArguments == null)
1168 NamedArguments.CheckArrayAsAttribute (context.Compiler);
1172 private Expression GetValue ()
1174 if (PosArguments == null || PosArguments.Count < 1)
1177 return PosArguments [0].Expr;
1180 public string GetString ()
1182 Expression e = GetValue ();
1183 if (e is StringConstant)
1184 return ((StringConstant)e).Value;
1188 public bool GetBoolean ()
1190 Expression e = GetValue ();
1191 if (e is BoolConstant)
1192 return ((BoolConstant)e).Value;
1196 public TypeSpec GetArgumentType ()
1198 TypeOf e = GetValue () as TypeOf;
1201 return e.TypeArgument;
1204 public override Expression CreateExpressionTree (ResolveContext ec)
1206 throw new NotSupportedException ("ET");
1209 protected override Expression DoResolve (ResolveContext ec)
1211 throw new NotImplementedException ();
1214 public override void Emit (EmitContext ec)
1216 throw new NotImplementedException ();
1222 /// For global attributes (assembly, module) we need special handling.
1223 /// Attributes can be located in the several files
1225 public class GlobalAttribute : Attribute
1227 public readonly NamespaceEntry ns;
1229 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1230 Arguments[] args, Location loc, bool nameEscaped):
1231 base (target, expression, args, loc, nameEscaped)
1236 public override void AttachTo (Attributable target, IMemberContext context)
1238 if (ExplicitTarget == "assembly") {
1239 base.AttachTo (CodeGen.Assembly, context);
1243 if (ExplicitTarget == "module") {
1244 base.AttachTo (RootContext.ToplevelTypes, context);
1248 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
1253 // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1254 // each time a new file is parsed. However, we need to use the NamespaceEntry
1255 // in effect where the attribute was used. Since code elsewhere cannot assume
1256 // that the NamespaceEntry is right, just overwrite it.
1258 // Precondition: RootContext.ToplevelTypes == null
1260 if (RootContext.ToplevelTypes.NamespaceEntry != null)
1261 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1263 RootContext.ToplevelTypes.NamespaceEntry = ns;
1266 protected override bool IsSecurityActionValid (bool for_assembly)
1268 return base.IsSecurityActionValid (true);
1273 RootContext.ToplevelTypes.NamespaceEntry = null;
1276 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1280 return base.ResolveAsTypeTerminal (expr, ec);
1287 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1291 return base.ResolveConstructor (ec);
1298 protected override bool ResolveNamedArguments (ResolveContext ec)
1302 return base.ResolveNamedArguments (ec);
1310 public class Attributes {
1311 public readonly List<Attribute> Attrs;
1313 public Attributes (Attribute a)
1315 Attrs = new List<Attribute> ();
1319 public Attributes (List<Attribute> attrs)
1324 public void AddAttributes (List<Attribute> attrs)
1326 Attrs.AddRange (attrs);
1329 public void AttachTo (Attributable attributable, IMemberContext context)
1331 foreach (Attribute a in Attrs)
1332 a.AttachTo (attributable, context);
1335 public Attributes Clone ()
1337 var al = new List<Attribute> (Attrs.Count);
1338 foreach (Attribute a in Attrs)
1339 al.Add (a.Clone ());
1341 return new Attributes (al);
1345 /// Checks whether attribute target is valid for the current element
1347 public bool CheckTargets ()
1349 foreach (Attribute a in Attrs) {
1350 if (!a.CheckTarget ())
1356 public Attribute Search (PredefinedAttribute t)
1358 foreach (Attribute a in Attrs) {
1359 if (a.ResolveType () == t)
1366 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1368 public Attribute[] SearchMulti (PredefinedAttribute t)
1370 List<Attribute> ar = null;
1372 foreach (Attribute a in Attrs) {
1373 if (a.ResolveType () == t) {
1375 ar = new List<Attribute> (Attrs.Count);
1380 return ar == null ? null : ar.ToArray ();
1387 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1389 foreach (Attribute a in Attrs)
1392 if (ld == null || ld.Count == 0)
1395 foreach (var d in ld) {
1396 if (d.Value == null)
1399 Attribute a = d.Key;
1401 foreach (Attribute collision in d.Value)
1402 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1404 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1405 a.GetSignatureForError ());
1409 public bool Contains (PredefinedAttribute t)
1411 return Search (t) != null;
1415 public struct AttributeEncoder
1417 public readonly BinaryWriter Stream;
1419 public AttributeEncoder (bool empty)
1426 Stream = new BinaryWriter (new MemoryStream ());
1427 const ushort version = 1;
1428 Stream.Write (version);
1431 public void Encode (string value)
1434 throw new ArgumentNullException ();
1436 var buf = Encoding.UTF8.GetBytes(value);
1437 WriteCompressedValue (buf.Length);
1441 public void Encode (TypeSpec type)
1443 if (type == TypeManager.bool_type) {
1444 Stream.Write ((byte) 0x02);
1445 } else if (type == TypeManager.char_type) {
1446 Stream.Write ((byte) 0x03);
1447 } else if (type == TypeManager.sbyte_type) {
1448 Stream.Write ((byte) 0x04);
1449 } else if (type == TypeManager.byte_type) {
1450 Stream.Write ((byte) 0x05);
1451 } else if (type == TypeManager.short_type) {
1452 Stream.Write ((byte) 0x06);
1453 } else if (type == TypeManager.ushort_type) {
1454 Stream.Write ((byte) 0x07);
1455 } else if (type == TypeManager.int32_type) {
1456 Stream.Write ((byte) 0x08);
1457 } else if (type == TypeManager.uint32_type) {
1458 Stream.Write ((byte) 0x09);
1459 } else if (type == TypeManager.int64_type) {
1460 Stream.Write ((byte) 0x0A);
1461 } else if (type == TypeManager.uint64_type) {
1462 Stream.Write ((byte) 0x0B);
1463 } else if (type == TypeManager.float_type) {
1464 Stream.Write ((byte) 0x0C);
1465 } else if (type == TypeManager.double_type) {
1466 Stream.Write ((byte) 0x0D);
1467 } else if (type == TypeManager.string_type) {
1468 Stream.Write ((byte) 0x0E);
1469 } else if (type == TypeManager.type_type) {
1470 Stream.Write ((byte) 0x50);
1471 } else if (type == TypeManager.object_type) {
1472 Stream.Write ((byte) 0x51);
1473 } else if (TypeManager.IsEnumType (type)) {
1474 Stream.Write ((byte) 0x55);
1475 EncodeTypeName (type);
1476 } else if (type.IsArray) {
1477 Stream.Write ((byte) 0x1D);
1478 Encode (TypeManager.GetElementType (type));
1480 throw new NotImplementedException (type.ToString ());
1484 public bool EncodeTypeName (TypeSpec type)
1486 // if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
1489 var old_type = type.GetMetaInfo ();
1490 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1494 void WriteCompressedValue (int value)
1497 Stream.Write ((byte) value);
1501 if (value < 0x4000) {
1502 Stream.Write ((byte) (0x80 | (value >> 8)));
1503 Stream.Write ((byte) value);
1507 Stream.Write (value);
1510 public byte[] ToArray ()
1512 return ((MemoryStream) Stream.BaseStream).ToArray ();
1518 /// Helper class for attribute verification routine.
1520 static class AttributeTester
1522 public enum Result {
1529 /// Returns true if parameters of two compared methods are CLS-Compliant.
1530 /// It tests differing only in ref or out, or in array rank.
1532 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1534 TypeSpec [] types_a = pa.Types;
1535 TypeSpec [] types_b = pb.Types;
1536 if (types_a == null || types_b == null)
1539 if (types_a.Length != types_b.Length)
1542 Result result = Result.Ok;
1543 for (int i = 0; i < types_b.Length; ++i) {
1544 TypeSpec aType = types_a [i];
1545 TypeSpec bType = types_b [i];
1547 var ac_a = aType as ArrayContainer;
1548 var ac_b = aType as ArrayContainer;
1550 if (ac_a != null && ac_b != null) {
1551 if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1552 result = Result.RefOutArrayError;
1556 if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1557 result = Result.ArrayArrayError;
1565 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1566 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1567 result = Result.RefOutArrayError;
1572 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1574 Module[] modules = GlobalRootNamespace.Instance.Modules;
1575 if (modules == null)
1578 // The first module is generated assembly
1579 for (int i = 1; i < modules.Length; ++i) {
1580 Module module = modules [i];
1581 if (!GetClsCompliantAttributeValue (module, null)) {
1582 ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1583 "to match the assembly", module.Name);
1589 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
1591 object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
1592 if (cls_attr.Length == 0) {
1596 return GetClsCompliantAttributeValue (a, null);
1599 return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1603 /// Common method for Obsolete error/warning reporting.
1605 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1608 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1612 if (oa.Message == null || oa.Message.Length == 0) {
1613 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1616 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1620 public class PredefinedAttributes
1623 public readonly PredefinedAttribute ParamArray;
1624 public readonly PredefinedAttribute Out;
1627 public readonly PredefinedAttribute Obsolete;
1628 public readonly PredefinedAttribute DllImport;
1629 public readonly PredefinedAttribute MethodImpl;
1630 public readonly PredefinedAttribute MarshalAs;
1631 public readonly PredefinedAttribute In;
1632 public readonly PredefinedAttribute IndexerName;
1633 public readonly PredefinedAttribute Conditional;
1634 public readonly PredefinedAttribute CLSCompliant;
1635 public readonly PredefinedAttribute Security;
1636 public readonly PredefinedAttribute Required;
1637 public readonly PredefinedAttribute Guid;
1638 public readonly PredefinedAttribute AssemblyCulture;
1639 public readonly PredefinedAttribute AssemblyVersion;
1640 public readonly PredefinedAttribute ComImport;
1641 public readonly PredefinedAttribute CoClass;
1642 public readonly PredefinedAttribute AttributeUsage;
1643 public readonly PredefinedAttribute DefaultParameterValue;
1644 public readonly PredefinedAttribute OptionalParameter;
1647 public readonly PredefinedAttribute DefaultCharset;
1648 public readonly PredefinedAttribute TypeForwarder;
1649 public readonly PredefinedAttribute FixedBuffer;
1650 public readonly PredefinedAttribute CompilerGenerated;
1651 public readonly PredefinedAttribute InternalsVisibleTo;
1652 public readonly PredefinedAttribute RuntimeCompatibility;
1653 public readonly PredefinedAttribute DebuggerHidden;
1654 public readonly PredefinedAttribute UnsafeValueType;
1657 public readonly PredefinedAttribute Extension;
1660 public readonly PredefinedAttribute Dynamic;
1661 public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
1664 // Optional types which are used as types and for member lookup
1666 public readonly PredefinedAttribute DefaultMember;
1667 public readonly PredefinedAttribute DecimalConstant;
1668 public readonly PredefinedAttribute StructLayout;
1669 public readonly PredefinedAttribute FieldOffset;
1671 public static PredefinedAttributes Get = new PredefinedAttributes ();
1673 private PredefinedAttributes ()
1675 ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1676 Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1678 Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1679 DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1680 MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1681 MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1682 In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1683 IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1684 Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1685 CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1686 Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1687 Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1688 Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1689 AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1690 AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1691 ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1692 CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1693 AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1694 DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1695 OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1697 DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1698 TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1699 FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1700 CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1701 InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1702 RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1703 DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1704 UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1706 Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1708 Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1709 DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1711 DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
1712 DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1713 StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
1714 FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1717 public void Initialize (CompilerContext ctx)
1719 foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
1720 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
1724 public static void Reset ()
1726 Get = new PredefinedAttributes ();
1730 public class PredefinedAttribute
1733 CustomAttributeBuilder cab;
1735 readonly string ns, name;
1736 CompilerContext compiler;
1738 static readonly TypeSpec NotFound = InternalType.Null;
1740 public PredefinedAttribute (string ns, string name)
1746 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1748 return type == pa.type;
1751 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1753 return type != pa.type;
1756 public ConstructorInfo Constructor {
1757 get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
1760 public override int GetHashCode ()
1762 return base.GetHashCode ();
1765 public string GetSignatureForError ()
1767 return ns + "." + name;
1770 public override bool Equals (object obj)
1772 throw new NotSupportedException ();
1775 public void EmitAttribute (ConstructorBuilder builder)
1777 if (ResolveBuilder ())
1778 builder.SetCustomAttribute (cab);
1781 public void EmitAttribute (MethodBuilder builder)
1783 if (ResolveBuilder ())
1784 builder.SetCustomAttribute (cab);
1787 public void EmitAttribute (PropertyBuilder builder)
1789 if (ResolveBuilder ())
1790 builder.SetCustomAttribute (cab);
1793 public void EmitAttribute (FieldBuilder builder)
1795 if (ResolveBuilder ())
1796 builder.SetCustomAttribute (cab);
1799 public void EmitAttribute (TypeBuilder builder)
1801 if (ResolveBuilder ())
1802 builder.SetCustomAttribute (cab);
1805 public void EmitAttribute (AssemblyBuilder builder)
1807 if (ResolveBuilder ())
1808 builder.SetCustomAttribute (cab);
1811 public void EmitAttribute (ParameterBuilder builder)
1813 if (ResolveBuilder ())
1814 builder.SetCustomAttribute (cab);
1817 public bool IsDefined {
1818 get { return type != null && type != NotFound; }
1821 public void Initialize (CompilerContext ctx, bool canFail)
1823 this.compiler = ctx;
1827 public bool Resolve (bool canFail)
1836 type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
1845 bool ResolveBuilder ()
1851 // Handle all parameter-less attributes as optional
1853 if (!Resolve (true))
1856 var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
1860 cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
1864 public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
1867 throw new InternalErrorException ("Predefined ctor redefined");
1869 if (!Resolve (false))
1872 ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
1873 return ctor != null;
1876 public TypeSpec Type {
1877 get { return type; }