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 return mg.BestCandidate;
442 protected virtual bool ResolveNamedArguments (ResolveContext ec)
444 int named_arg_count = NamedArguments.Count;
445 var seen_names = new List<string> (named_arg_count);
447 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
449 foreach (NamedArgument a in NamedArguments) {
450 string name = a.Name;
451 if (seen_names.Contains (name)) {
452 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
456 seen_names.Add (name);
460 Expression member = Expression.MemberLookup (ec.Compiler,
461 ec.CurrentType, Type, name, 0,
463 BindingRestriction.AccessibleOnly | BindingRestriction.DefaultMemberLookup,
466 if (member == null) {
467 member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name, 0,
468 MemberKind.All, BindingRestriction.None,
471 if (member != null) {
472 ec.Report.SymbolRelatedToPreviousError (member.Type);
473 Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
479 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
483 if (!(member is PropertyExpr || member is FieldExpr)) {
484 Error_InvalidNamedArgument (ec, a);
488 ObsoleteAttribute obsolete_attr;
490 if (member is PropertyExpr) {
491 var pi = ((PropertyExpr) member).PropertyInfo;
493 if (!pi.HasSet || !pi.HasGet || pi.IsStatic) {
494 ec.Report.SymbolRelatedToPreviousError (pi);
495 Error_InvalidNamedArgument (ec, a);
499 if (!IsValidArgumentType (member.Type)) {
500 ec.Report.SymbolRelatedToPreviousError (pi);
501 Error_InvalidNamedArgumentType (ec, a);
505 obsolete_attr = pi.GetAttributeObsolete ();
507 var fi = ((FieldExpr) member).Spec;
509 if (fi.IsReadOnly || fi.IsStatic) {
510 Error_InvalidNamedArgument (ec, a);
514 if (!IsValidArgumentType (member.Type)) {
515 ec.Report.SymbolRelatedToPreviousError (fi);
516 Error_InvalidNamedArgumentType (ec, a);
520 obsolete_attr = fi.GetAttributeObsolete ();
523 if (obsolete_attr != null && !context.IsObsolete)
524 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
526 if (a.Type != member.Type) {
527 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
531 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
538 /// Get a string containing a list of valid targets for the attribute 'attr'
540 public string GetValidTargets ()
542 StringBuilder sb = new StringBuilder ();
543 AttributeTargets targets = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage).ValidOn;
545 if ((targets & AttributeTargets.Assembly) != 0)
546 sb.Append ("assembly, ");
548 if ((targets & AttributeTargets.Module) != 0)
549 sb.Append ("module, ");
551 if ((targets & AttributeTargets.Class) != 0)
552 sb.Append ("class, ");
554 if ((targets & AttributeTargets.Struct) != 0)
555 sb.Append ("struct, ");
557 if ((targets & AttributeTargets.Enum) != 0)
558 sb.Append ("enum, ");
560 if ((targets & AttributeTargets.Constructor) != 0)
561 sb.Append ("constructor, ");
563 if ((targets & AttributeTargets.Method) != 0)
564 sb.Append ("method, ");
566 if ((targets & AttributeTargets.Property) != 0)
567 sb.Append ("property, indexer, ");
569 if ((targets & AttributeTargets.Field) != 0)
570 sb.Append ("field, ");
572 if ((targets & AttributeTargets.Event) != 0)
573 sb.Append ("event, ");
575 if ((targets & AttributeTargets.Interface) != 0)
576 sb.Append ("interface, ");
578 if ((targets & AttributeTargets.Parameter) != 0)
579 sb.Append ("parameter, ");
581 if ((targets & AttributeTargets.Delegate) != 0)
582 sb.Append ("delegate, ");
584 if ((targets & AttributeTargets.ReturnValue) != 0)
585 sb.Append ("return, ");
587 if ((targets & AttributeTargets.GenericParameter) != 0)
588 sb.Append ("type parameter, ");
590 return sb.Remove (sb.Length - 2, 2).ToString ();
593 public AttributeUsageAttribute GetAttributeUsageAttribute ()
596 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
597 // But because a lot of attribute class code must be rewritten will be better to wait...
601 return DefaultUsageAttribute;
603 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
605 var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
607 usage_attribute.AllowMultiple = field.Value;
609 field = GetPropertyValue ("Inherited") as BoolConstant;
611 usage_attribute.Inherited = field.Value;
613 return usage_attribute;
617 /// Returns custom name of indexer
619 public string GetIndexerAttributeValue ()
622 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
623 // But because a lot of attribute class code must be rewritten will be better to wait...
629 return ((Constant) PosArguments [0].Expr).GetValue () as string;
633 /// Returns condition of ConditionalAttribute
635 public string GetConditionalAttributeValue ()
638 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
639 // But because a lot of attribute class code must be rewritten will be better to wait...
645 return ((Constant) PosArguments[0].Expr).GetValue () as string;
649 /// Creates the instance of ObsoleteAttribute from this attribute instance
651 public ObsoleteAttribute GetObsoleteAttribute ()
654 // corlib only case when obsolete is used before is resolved
655 var c = type.MemberDefinition as Class;
656 if (c != null && !c.HasMembersDefined)
659 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
660 // But because a lot of attribute class code must be rewritten will be better to wait...
667 if (PosArguments == null)
668 return new ObsoleteAttribute ();
670 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
671 if (PosArguments.Count == 1)
672 return new ObsoleteAttribute (msg);
674 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
678 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
679 /// before ApplyAttribute. We need to resolve the arguments.
680 /// This situation occurs when class deps is differs from Emit order.
682 public bool GetClsCompliantAttributeValue ()
685 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
686 // But because a lot of attribute class code must be rewritten will be better to wait...
692 return ((BoolConstant) PosArguments[0].Expr).Value;
695 public TypeSpec GetCoClassAttributeValue ()
703 return GetArgumentType ();
706 public bool CheckTarget ()
708 string[] valid_targets = Owner.ValidAttributeTargets;
709 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
710 Target = Owner.AttributeTargets;
714 // TODO: we can skip the first item
715 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
716 switch (ExplicitTarget) {
717 case "return": Target = AttributeTargets.ReturnValue; return true;
718 case "param": Target = AttributeTargets.Parameter; return true;
719 case "field": Target = AttributeTargets.Field; return true;
720 case "method": Target = AttributeTargets.Method; return true;
721 case "property": Target = AttributeTargets.Property; return true;
723 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
726 StringBuilder sb = new StringBuilder ();
727 foreach (string s in valid_targets) {
731 sb.Remove (sb.Length - 2, 2);
732 Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
733 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
738 /// Tests permitted SecurityAction for assembly or other types
740 protected virtual bool IsSecurityActionValid (bool for_assembly)
742 SecurityAction action = GetSecurityActionValue ();
745 case SecurityAction.Demand:
746 case SecurityAction.Assert:
747 case SecurityAction.Deny:
748 case SecurityAction.PermitOnly:
749 case SecurityAction.LinkDemand:
750 case SecurityAction.InheritanceDemand:
755 case SecurityAction.RequestMinimum:
756 case SecurityAction.RequestOptional:
757 case SecurityAction.RequestRefuse:
763 Error_AttributeEmitError ("SecurityAction is out of range");
767 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
771 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
773 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
777 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
779 /// <returns></returns>
780 public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
782 Type orig_assembly_type = null;
784 if (Type.MemberDefinition is TypeContainer) {
785 if (!RootContext.StdLib) {
786 orig_assembly_type = System.Type.GetType (Type.GetMetaInfo ().FullName);
788 string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
789 if (orig_version_path == null) {
790 Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
794 if (orig_sec_assembly == null) {
795 string file = Path.Combine (orig_version_path, Driver.OutputFile);
796 orig_sec_assembly = Assembly.LoadFile (file);
799 orig_assembly_type = orig_sec_assembly.GetType (Type.GetMetaInfo ().FullName, true);
800 if (orig_assembly_type == null) {
801 Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
802 "was not found in previous version of assembly");
808 SecurityAttribute sa;
811 // For all non-selfreferencing security attributes we can avoid all hacks
812 if (orig_assembly_type == null) {
813 args = new object[PosArguments.Count];
814 for (int j = 0; j < args.Length; ++j) {
815 args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
818 sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
820 if (named_values != null) {
821 for (int i = 0; i < named_values.Count; ++i) {
822 PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
823 pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
827 // HACK: All security attributes have same ctor syntax
828 args = new object[] { GetSecurityActionValue () };
829 sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, args);
831 // All types are from newly created assembly but for invocation with old one we need to convert them
832 if (named_values != null) {
833 for (int i = 0; i < named_values.Count; ++i) {
834 PropertyInfo emited_pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
835 // FIXME: We are missing return type filter
836 // TODO: pi can be null
837 PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
839 pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
845 perm = sa.CreatePermission ();
846 SecurityAction action = (SecurityAction) args [0];
848 // IS is correct because for corlib we are using an instance from old corlib
849 if (!(perm is System.Security.CodeAccessPermission)) {
851 case SecurityAction.Demand:
852 action = (SecurityAction)13;
854 case SecurityAction.LinkDemand:
855 action = (SecurityAction)14;
857 case SecurityAction.InheritanceDemand:
858 action = (SecurityAction)15;
864 if (!permissions.TryGetValue (action, out ps)) {
865 if (sa is PermissionSetAttribute)
866 ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
868 ps = new PermissionSet (PermissionState.None);
870 permissions.Add (action, ps);
871 } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
872 ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
873 permissions [action] = ps;
875 ps.AddPermission (perm);
878 public Constant GetPropertyValue (string name)
880 if (named_values == null)
883 for (int i = 0; i < named_values.Count; ++i) {
884 if (named_values [i].Value.Name == name)
885 return named_values [i].Value.Expr as Constant;
892 // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
893 // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
894 // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
897 public UnmanagedMarshal GetMarshal (Attributable attr)
899 UnmanagedType UnmanagedType;
900 if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
901 UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
903 UnmanagedType = (UnmanagedType) pos_values [0];
905 object value = GetFieldValue ("SizeParamIndex");
906 if (value != null && UnmanagedType != UnmanagedType.LPArray) {
907 Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
911 object o = GetFieldValue ("ArraySubType");
912 UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
914 switch (UnmanagedType) {
915 case UnmanagedType.CustomMarshaler: {
916 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
917 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
918 if (define_custom == null) {
919 Report.RuntimeMissingSupport (Location, "set marshal info");
923 object [] args = new object [4];
924 args [0] = GetFieldValue ("MarshalTypeRef");
925 args [1] = GetFieldValue ("MarshalCookie");
926 args [2] = GetFieldValue ("MarshalType");
927 args [3] = Guid.Empty;
928 return (UnmanagedMarshal) define_custom.Invoke (null, args);
930 case UnmanagedType.LPArray: {
931 object size_const = GetFieldValue ("SizeConst");
932 object size_param_index = GetFieldValue ("SizeParamIndex");
934 if ((size_const != null) || (size_param_index != null)) {
935 MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
936 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
937 if (define_array == null) {
938 Report.RuntimeMissingSupport (Location, "set marshal info");
942 object [] args = new object [3];
943 args [0] = array_sub_type;
944 args [1] = size_const == null ? -1 : size_const;
945 args [2] = size_param_index == null ? -1 : size_param_index;
946 return (UnmanagedMarshal) define_array.Invoke (null, args);
949 return UnmanagedMarshal.DefineLPArray (array_sub_type);
951 case UnmanagedType.SafeArray:
952 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
954 case UnmanagedType.ByValArray:
955 FieldBase fm = attr as FieldBase;
957 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
960 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
962 case UnmanagedType.ByValTStr:
963 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
966 return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
970 object GetFieldValue (string name)
973 if (field_info_arr == null)
976 foreach (FieldInfo fi in field_info_arr) {
978 return GetValue (field_values_arr [i]);
984 static object GetValue (object value)
986 if (value is EnumConstant)
987 return ((EnumConstant) value).GetValue ();
994 public CharSet GetCharSetValue ()
996 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
999 public bool HasField (string fieldName)
1001 if (named_values == null)
1004 foreach (var na in named_values) {
1005 if (na.Value.Name == fieldName)
1012 public bool IsInternalMethodImplAttribute {
1014 if (Type != PredefinedAttributes.Get.MethodImpl)
1017 MethodImplOptions options;
1018 if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
1019 options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
1021 options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
1023 return (options & MethodImplOptions.InternalCall) != 0;
1027 public LayoutKind GetLayoutKindValue ()
1029 if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
1030 return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
1032 return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
1035 public Constant GetParameterDefaultValue (out TypeSpec type)
1037 var expr = PosArguments[0].Expr;
1039 if (expr is TypeCast)
1040 expr = ((TypeCast) expr).Child;
1043 return expr as Constant;
1046 public override bool Equals (object obj)
1048 Attribute a = obj as Attribute;
1052 return Type == a.Type && Target == a.Target;
1055 public override int GetHashCode ()
1057 return type.GetHashCode () ^ Target.GetHashCode ();
1061 /// Emit attribute for Attributable symbol
1063 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1065 var ctor = Resolve ();
1069 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage);
1070 if ((usage_attr.ValidOn & Target) == 0) {
1071 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1072 "It is valid on `{1}' declarations only",
1073 GetSignatureForError (), GetValidTargets ());
1077 var predefined = PredefinedAttributes.Get;
1079 AttributeEncoder encoder = new AttributeEncoder (false);
1081 if (PosArguments != null) {
1082 var param_types = ctor.Parameters.Types;
1083 for (int j = 0; j < PosArguments.Count; ++j) {
1084 var pt = param_types[j];
1085 if (!IsValidArgumentType (pt)) {
1086 Error_AttributeArgumentNotValid (context, loc);
1090 var arg_expr = PosArguments[j].Expr;
1092 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
1093 string v = ((StringConstant) arg_expr).Value;
1094 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
1095 context.Compiler.Report.Error (633, arg_expr.Location,
1096 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1098 } else if (Type == predefined.Guid) {
1100 string v = ((StringConstant) arg_expr).Value;
1102 } catch (Exception e) {
1103 Error_AttributeEmitError (e.Message);
1106 } else if (Type == predefined.AttributeUsage) {
1107 int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
1109 context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1110 "System.AttributeUsage");
1112 } else if (Type == predefined.MethodImpl && pt == TypeManager.short_type &&
1113 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
1114 Error_AttributeEmitError ("Incorrect argument value.");
1119 arg_expr.EncodeAttributeValue (context, encoder, pt);
1123 if (named_values != null) {
1124 encoder.Stream.Write ((ushort) named_values.Count);
1125 foreach (var na in named_values) {
1126 if (na.Key is FieldExpr)
1127 encoder.Stream.Write ((byte) 0x53);
1129 encoder.Stream.Write ((byte) 0x54);
1131 encoder.Encode (na.Key.Type);
1132 encoder.Encode (na.Value.Name);
1133 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1136 encoder.Stream.Write ((ushort) 0);
1139 byte[] cdata = encoder.ToArray ();
1142 foreach (Attributable target in targets)
1143 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1144 } catch (Exception e) {
1145 Error_AttributeEmitError (e.Message);
1149 if (!usage_attr.AllowMultiple && allEmitted != null) {
1150 if (allEmitted.ContainsKey (this)) {
1151 var a = allEmitted [this];
1153 a = new List<Attribute> (2);
1154 allEmitted [this] = a;
1158 allEmitted.Add (this, null);
1162 if (!RootContext.VerifyClsCompliance)
1165 // Here we are testing attribute arguments for array usage (error 3016)
1166 if (Owner.IsClsComplianceRequired ()) {
1167 if (PosArguments != null)
1168 PosArguments.CheckArrayAsAttribute (context.Compiler);
1170 if (NamedArguments == null)
1173 NamedArguments.CheckArrayAsAttribute (context.Compiler);
1177 private Expression GetValue ()
1179 if (PosArguments == null || PosArguments.Count < 1)
1182 return PosArguments [0].Expr;
1185 public string GetString ()
1187 Expression e = GetValue ();
1188 if (e is StringConstant)
1189 return ((StringConstant)e).Value;
1193 public bool GetBoolean ()
1195 Expression e = GetValue ();
1196 if (e is BoolConstant)
1197 return ((BoolConstant)e).Value;
1201 public TypeSpec GetArgumentType ()
1203 TypeOf e = GetValue () as TypeOf;
1206 return e.TypeArgument;
1209 public override Expression CreateExpressionTree (ResolveContext ec)
1211 throw new NotSupportedException ("ET");
1214 protected override Expression DoResolve (ResolveContext ec)
1216 throw new NotImplementedException ();
1219 public override void Emit (EmitContext ec)
1221 throw new NotImplementedException ();
1227 /// For global attributes (assembly, module) we need special handling.
1228 /// Attributes can be located in the several files
1230 public class GlobalAttribute : Attribute
1232 public readonly NamespaceEntry ns;
1234 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1235 Arguments[] args, Location loc, bool nameEscaped):
1236 base (target, expression, args, loc, nameEscaped)
1241 public override void AttachTo (Attributable target, IMemberContext context)
1243 if (ExplicitTarget == "assembly") {
1244 base.AttachTo (CodeGen.Assembly, context);
1248 if (ExplicitTarget == "module") {
1249 base.AttachTo (RootContext.ToplevelTypes, context);
1253 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
1258 // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1259 // each time a new file is parsed. However, we need to use the NamespaceEntry
1260 // in effect where the attribute was used. Since code elsewhere cannot assume
1261 // that the NamespaceEntry is right, just overwrite it.
1263 // Precondition: RootContext.ToplevelTypes == null
1265 if (RootContext.ToplevelTypes.NamespaceEntry != null)
1266 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1268 RootContext.ToplevelTypes.NamespaceEntry = ns;
1271 protected override bool IsSecurityActionValid (bool for_assembly)
1273 return base.IsSecurityActionValid (true);
1278 RootContext.ToplevelTypes.NamespaceEntry = null;
1281 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1285 return base.ResolveAsTypeTerminal (expr, ec);
1292 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1296 return base.ResolveConstructor (ec);
1303 protected override bool ResolveNamedArguments (ResolveContext ec)
1307 return base.ResolveNamedArguments (ec);
1315 public class Attributes {
1316 public readonly List<Attribute> Attrs;
1318 public Attributes (Attribute a)
1320 Attrs = new List<Attribute> ();
1324 public Attributes (List<Attribute> attrs)
1329 public void AddAttributes (List<Attribute> attrs)
1331 Attrs.AddRange (attrs);
1334 public void AttachTo (Attributable attributable, IMemberContext context)
1336 foreach (Attribute a in Attrs)
1337 a.AttachTo (attributable, context);
1340 public Attributes Clone ()
1342 var al = new List<Attribute> (Attrs.Count);
1343 foreach (Attribute a in Attrs)
1344 al.Add (a.Clone ());
1346 return new Attributes (al);
1350 /// Checks whether attribute target is valid for the current element
1352 public bool CheckTargets ()
1354 foreach (Attribute a in Attrs) {
1355 if (!a.CheckTarget ())
1361 public Attribute Search (PredefinedAttribute t)
1363 foreach (Attribute a in Attrs) {
1364 if (a.ResolveType () == t)
1371 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1373 public Attribute[] SearchMulti (PredefinedAttribute t)
1375 List<Attribute> ar = null;
1377 foreach (Attribute a in Attrs) {
1378 if (a.ResolveType () == t) {
1380 ar = new List<Attribute> (Attrs.Count);
1385 return ar == null ? null : ar.ToArray ();
1392 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1394 foreach (Attribute a in Attrs)
1397 if (ld == null || ld.Count == 0)
1400 foreach (var d in ld) {
1401 if (d.Value == null)
1404 Attribute a = d.Key;
1406 foreach (Attribute collision in d.Value)
1407 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1409 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1410 a.GetSignatureForError ());
1414 public bool Contains (PredefinedAttribute t)
1416 return Search (t) != null;
1420 public struct AttributeEncoder
1422 public readonly BinaryWriter Stream;
1424 public AttributeEncoder (bool empty)
1431 Stream = new BinaryWriter (new MemoryStream ());
1432 const ushort version = 1;
1433 Stream.Write (version);
1436 public void Encode (string value)
1439 throw new ArgumentNullException ();
1441 var buf = Encoding.UTF8.GetBytes(value);
1442 WriteCompressedValue (buf.Length);
1446 public void Encode (TypeSpec type)
1448 if (type == TypeManager.bool_type) {
1449 Stream.Write ((byte) 0x02);
1450 } else if (type == TypeManager.char_type) {
1451 Stream.Write ((byte) 0x03);
1452 } else if (type == TypeManager.sbyte_type) {
1453 Stream.Write ((byte) 0x04);
1454 } else if (type == TypeManager.byte_type) {
1455 Stream.Write ((byte) 0x05);
1456 } else if (type == TypeManager.short_type) {
1457 Stream.Write ((byte) 0x06);
1458 } else if (type == TypeManager.ushort_type) {
1459 Stream.Write ((byte) 0x07);
1460 } else if (type == TypeManager.int32_type) {
1461 Stream.Write ((byte) 0x08);
1462 } else if (type == TypeManager.uint32_type) {
1463 Stream.Write ((byte) 0x09);
1464 } else if (type == TypeManager.int64_type) {
1465 Stream.Write ((byte) 0x0A);
1466 } else if (type == TypeManager.uint64_type) {
1467 Stream.Write ((byte) 0x0B);
1468 } else if (type == TypeManager.float_type) {
1469 Stream.Write ((byte) 0x0C);
1470 } else if (type == TypeManager.double_type) {
1471 Stream.Write ((byte) 0x0D);
1472 } else if (type == TypeManager.string_type) {
1473 Stream.Write ((byte) 0x0E);
1474 } else if (type == TypeManager.type_type) {
1475 Stream.Write ((byte) 0x50);
1476 } else if (type == TypeManager.object_type) {
1477 Stream.Write ((byte) 0x51);
1478 } else if (TypeManager.IsEnumType (type)) {
1479 Stream.Write ((byte) 0x55);
1480 EncodeTypeName (type);
1481 } else if (type.IsArray) {
1482 Stream.Write ((byte) 0x1D);
1483 Encode (TypeManager.GetElementType (type));
1485 throw new NotImplementedException (type.ToString ());
1489 public void EncodeTypeName (TypeSpec type)
1491 var old_type = type.GetMetaInfo ();
1492 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1495 void WriteCompressedValue (int value)
1498 Stream.Write ((byte) value);
1502 if (value < 0x4000) {
1503 Stream.Write ((byte) (0x80 | (value >> 8)));
1504 Stream.Write ((byte) value);
1508 Stream.Write (value);
1511 public byte[] ToArray ()
1513 return ((MemoryStream) Stream.BaseStream).ToArray ();
1519 /// Helper class for attribute verification routine.
1521 static class AttributeTester
1523 public enum Result {
1530 /// Returns true if parameters of two compared methods are CLS-Compliant.
1531 /// It tests differing only in ref or out, or in array rank.
1533 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1535 TypeSpec [] types_a = pa.Types;
1536 TypeSpec [] types_b = pb.Types;
1537 if (types_a == null || types_b == null)
1540 if (types_a.Length != types_b.Length)
1543 Result result = Result.Ok;
1544 for (int i = 0; i < types_b.Length; ++i) {
1545 TypeSpec aType = types_a [i];
1546 TypeSpec bType = types_b [i];
1548 var ac_a = aType as ArrayContainer;
1549 var ac_b = aType as ArrayContainer;
1551 if (ac_a != null && ac_b != null) {
1552 if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1553 result = Result.RefOutArrayError;
1557 if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1558 result = Result.ArrayArrayError;
1566 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1567 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1568 result = Result.RefOutArrayError;
1573 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1575 Module[] modules = GlobalRootNamespace.Instance.Modules;
1576 if (modules == null)
1579 // The first module is generated assembly
1580 for (int i = 1; i < modules.Length; ++i) {
1581 Module module = modules [i];
1582 if (!GetClsCompliantAttributeValue (module, null)) {
1583 ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1584 "to match the assembly", module.Name);
1590 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
1592 object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
1593 if (cls_attr.Length == 0) {
1597 return GetClsCompliantAttributeValue (a, null);
1600 return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1604 /// Common method for Obsolete error/warning reporting.
1606 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1609 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1613 if (oa.Message == null || oa.Message.Length == 0) {
1614 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1617 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1621 public class PredefinedAttributes
1624 public readonly PredefinedAttribute ParamArray;
1625 public readonly PredefinedAttribute Out;
1628 public readonly PredefinedAttribute Obsolete;
1629 public readonly PredefinedAttribute DllImport;
1630 public readonly PredefinedAttribute MethodImpl;
1631 public readonly PredefinedAttribute MarshalAs;
1632 public readonly PredefinedAttribute In;
1633 public readonly PredefinedAttribute IndexerName;
1634 public readonly PredefinedAttribute Conditional;
1635 public readonly PredefinedAttribute CLSCompliant;
1636 public readonly PredefinedAttribute Security;
1637 public readonly PredefinedAttribute Required;
1638 public readonly PredefinedAttribute Guid;
1639 public readonly PredefinedAttribute AssemblyCulture;
1640 public readonly PredefinedAttribute AssemblyVersion;
1641 public readonly PredefinedAttribute AssemblyAlgorithmId;
1642 public readonly PredefinedAttribute AssemblyFlags;
1643 public readonly PredefinedAttribute ComImport;
1644 public readonly PredefinedAttribute CoClass;
1645 public readonly PredefinedAttribute AttributeUsage;
1646 public readonly PredefinedAttribute DefaultParameterValue;
1647 public readonly PredefinedAttribute OptionalParameter;
1650 public readonly PredefinedAttribute DefaultCharset;
1651 public readonly PredefinedAttribute TypeForwarder;
1652 public readonly PredefinedAttribute FixedBuffer;
1653 public readonly PredefinedAttribute CompilerGenerated;
1654 public readonly PredefinedAttribute InternalsVisibleTo;
1655 public readonly PredefinedAttribute RuntimeCompatibility;
1656 public readonly PredefinedAttribute DebuggerHidden;
1657 public readonly PredefinedAttribute UnsafeValueType;
1660 public readonly PredefinedAttribute Extension;
1663 public readonly PredefinedAttribute Dynamic;
1664 public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
1667 // Optional types which are used as types and for member lookup
1669 public readonly PredefinedAttribute DefaultMember;
1670 public readonly PredefinedAttribute DecimalConstant;
1671 public readonly PredefinedAttribute StructLayout;
1672 public readonly PredefinedAttribute FieldOffset;
1674 public static PredefinedAttributes Get = new PredefinedAttributes ();
1676 private PredefinedAttributes ()
1678 ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1679 Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1681 Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1682 DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1683 MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1684 MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1685 In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1686 IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1687 Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1688 CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1689 Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1690 Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1691 Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1692 AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1693 AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1694 AssemblyAlgorithmId = new PredefinedAttribute ("System.Reflection", "AssemblyAlgorithmIdAttribute");
1695 AssemblyFlags = new PredefinedAttribute ("System.Reflection", "AssemblyFlagsAttribute");
1696 ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1697 CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1698 AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1699 DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1700 OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1702 DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1703 TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1704 FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1705 CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1706 InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1707 RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1708 DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1709 UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1711 Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1713 Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1714 DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1716 DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
1717 DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1718 StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
1719 FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1722 public void Initialize (CompilerContext ctx)
1724 foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
1725 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
1729 public static void Reset ()
1731 Get = new PredefinedAttributes ();
1735 public class PredefinedAttribute
1738 CustomAttributeBuilder cab;
1740 readonly string ns, name;
1741 CompilerContext compiler;
1743 static readonly TypeSpec NotFound = InternalType.Null;
1745 public PredefinedAttribute (string ns, string name)
1751 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1753 return type == pa.type;
1756 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1758 return type != pa.type;
1761 public ConstructorInfo Constructor {
1762 get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
1765 public override int GetHashCode ()
1767 return base.GetHashCode ();
1770 public string GetSignatureForError ()
1772 return ns + "." + name;
1775 public override bool Equals (object obj)
1777 throw new NotSupportedException ();
1780 public void EmitAttribute (ConstructorBuilder builder)
1782 if (ResolveBuilder ())
1783 builder.SetCustomAttribute (cab);
1786 public void EmitAttribute (MethodBuilder builder)
1788 if (ResolveBuilder ())
1789 builder.SetCustomAttribute (cab);
1792 public void EmitAttribute (PropertyBuilder builder)
1794 if (ResolveBuilder ())
1795 builder.SetCustomAttribute (cab);
1798 public void EmitAttribute (FieldBuilder builder)
1800 if (ResolveBuilder ())
1801 builder.SetCustomAttribute (cab);
1804 public void EmitAttribute (TypeBuilder builder)
1806 if (ResolveBuilder ())
1807 builder.SetCustomAttribute (cab);
1810 public void EmitAttribute (AssemblyBuilder builder)
1812 if (ResolveBuilder ())
1813 builder.SetCustomAttribute (cab);
1816 public void EmitAttribute (ParameterBuilder builder)
1818 if (ResolveBuilder ())
1819 builder.SetCustomAttribute (cab);
1822 public bool IsDefined {
1823 get { return type != null && type != NotFound; }
1826 public void Initialize (CompilerContext ctx, bool canFail)
1828 this.compiler = ctx;
1832 public bool Resolve (bool canFail)
1841 type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
1850 bool ResolveBuilder ()
1856 // Handle all parameter-less attributes as optional
1858 if (!Resolve (true))
1861 var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
1865 cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
1869 public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
1872 throw new InternalErrorException ("Predefined ctor redefined");
1874 if (!Resolve (false))
1877 ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
1878 return ctor != null;
1881 public TypeSpec Type {
1882 get { return type; }