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, ConstructorInfo 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 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 static Dictionary<Type, AttributeUsageAttribute> usage_attr_cache;
108 // Cache for parameter-less attributes
109 static Dictionary<Type, ConstructorInfo> att_cache;
111 public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
113 this.expression = expr;
115 PosArguments = args [0];
116 NamedArguments = args [1];
119 ExplicitTarget = target;
120 this.nameEscaped = nameEscaped;
123 public Attribute Clone ()
125 Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
126 a.PosArguments = PosArguments;
127 a.NamedArguments = NamedArguments;
136 public static void Reset ()
138 usage_attr_cache = new Dictionary<Type, AttributeUsageAttribute> (ReferenceEquality<Type>.Default);
139 att_cache = new Dictionary<Type, ConstructorInfo> (ReferenceEquality<Type>.Default);
143 // When the same attribute is attached to multiple fiels
144 // we use @target field as a list of targets. The attribute
145 // has to be resolved only once but emitted for each target.
147 public virtual void AttachTo (Attributable target, IMemberContext context)
149 if (this.targets == null) {
150 this.targets = new Attributable[] { target };
151 this.context = context;
155 // Resize target array
156 Attributable[] new_array = new Attributable [this.targets.Length + 1];
157 targets.CopyTo (new_array, 0);
158 new_array [targets.Length] = target;
159 this.targets = new_array;
161 // No need to update context, different targets cannot have
162 // different contexts, it's enough to remove same attributes
163 // from secondary members.
165 target.OptAttributes = null;
168 static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
170 rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
171 "must be fields which are not readonly, static, const or read-write properties which are " +
172 "public and not static",
176 static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
178 rc.Report.Error (655, name.Location,
179 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
183 public static void Error_AttributeArgumentNotValid (IMemberContext rc, Location loc)
185 rc.Compiler.Report.Error (182, loc,
186 "An attribute argument must be a constant expression, typeof " +
187 "expression or array creation expression");
190 public void Error_MissingGuidAttribute ()
192 Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
195 public void Error_MisusedExtensionAttribute ()
197 Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
200 public void Error_MisusedDynamicAttribute ()
202 Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
206 /// This is rather hack. We report many emit attribute error with same error to be compatible with
207 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
209 public void Error_AttributeEmitError (string inner)
211 Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
212 TypeManager.CSharpName (Type), inner);
215 public void Error_InvalidSecurityParent ()
217 Error_AttributeEmitError ("it is attached to invalid parent");
226 protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
228 return expr.ResolveAsTypeTerminal (ec, false);
231 Type ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
233 TypeExpr te = ResolveAsTypeTerminal (expr, context);
238 if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
241 Report.SymbolRelatedToPreviousError (t);
242 Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
248 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
250 void ResolveAttributeType ()
252 SessionReportPrinter resolve_printer = new SessionReportPrinter ();
253 ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);
255 bool t1_is_attr = false;
256 bool t2_is_attr = false;
258 ATypeNameExpression expanded = null;
261 t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
266 expanded = (ATypeNameExpression) expression.Clone (null);
267 expanded.Name += "Attribute";
269 t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
272 resolve_printer.EndSession ();
274 context.Compiler.Report.SetPrinter (prev_recorder);
277 if (t1_is_attr && t2_is_attr) {
278 Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
279 GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
280 resolve_error = true;
294 resolve_printer.Merge (prev_recorder);
295 resolve_error = true;
298 public virtual Type ResolveType ()
300 if (Type == null && !resolve_error)
301 ResolveAttributeType ();
305 public override string GetSignatureForError ()
308 return TypeManager.CSharpName (Type);
310 return expression.GetSignatureForError ();
313 public bool HasSecurityAttribute {
315 PredefinedAttribute pa = PredefinedAttributes.Get.Security;
316 return pa.IsDefined && TypeManager.IsSubclassOf (type, pa.Type);
320 public bool IsValidSecurityAttribute ()
322 return HasSecurityAttribute && IsSecurityActionValid (false);
325 static bool IsValidArgumentType (Type t)
328 t = TypeManager.GetElementType (t);
330 return t == TypeManager.string_type ||
331 TypeManager.IsPrimitiveType (t) ||
332 TypeManager.IsEnumType (t) ||
333 t == TypeManager.object_type ||
334 t == TypeManager.type_type;
337 // TODO: Don't use this ambiguous value
339 get { return expression.Name; }
342 void ApplyModuleCharSet (ResolveContext rc)
344 if (Type != PredefinedAttributes.Get.DllImport)
347 if (!RootContext.ToplevelTypes.HasDefaultCharSet)
350 const string CharSetEnumMember = "CharSet";
351 if (NamedArguments == null) {
352 NamedArguments = new Arguments (1);
354 foreach (NamedArgument a in NamedArguments) {
355 if (a.Name == CharSetEnumMember)
360 NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
361 Constant.CreateConstant (rc, typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location)));
364 public Report Report {
365 get { return context.Compiler.Report; }
368 public ConstructorInfo Resolve ()
373 resolve_error = true;
377 ResolveAttributeType ();
382 if (Type.IsAbstract) {
383 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
387 ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);
388 if (obsolete_attr != null) {
389 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
392 ConstructorInfo ctor_meta;
394 // Try if the attribute is simple has been resolved before
395 if (PosArguments == null && NamedArguments == null) {
396 if (att_cache.TryGetValue (Type, out ctor_meta)) {
397 resolve_error = false;
402 ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
403 var ctor = ResolveConstructor (rc);
405 if (Type is TypeBuilder &&
406 TypeManager.LookupDeclSpace (Type).MemberCache == null)
407 // The attribute type has been DefineType'd, but not Defined. Let's not treat it as an error.
408 // It'll be resolved again when the attached-to entity is emitted.
409 resolve_error = false;
413 ApplyModuleCharSet (rc);
415 if (NamedArguments != null && !ResolveNamedArguments (rc)) {
419 resolve_error = false;
420 return (ConstructorInfo) ctor.MetaInfo;
423 protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
425 if (PosArguments != null) {
427 PosArguments.Resolve (ec, out dynamic);
429 Error_AttributeArgumentNotValid (ec, loc);
434 MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
435 Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
436 BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
437 Location) as MethodGroupExpr;
440 throw new NotImplementedException ();
442 mg = mg.OverloadResolve (ec, ref PosArguments, false, Location);
446 var constructor = (MethodSpec) mg;
450 protected virtual bool ResolveNamedArguments (ResolveContext ec)
452 int named_arg_count = NamedArguments.Count;
453 var seen_names = new List<string> (named_arg_count);
455 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
457 foreach (NamedArgument a in NamedArguments) {
458 string name = a.Name;
459 if (seen_names.Contains (name)) {
460 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
464 seen_names.Add (name);
468 Expression member = Expression.MemberLookup (ec.Compiler,
469 ec.CurrentType, Type, name,
471 BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
474 if (member == null) {
475 member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name,
476 MemberTypes.All, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
479 if (member != null) {
480 ec.Report.SymbolRelatedToPreviousError (member.Type);
481 Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
487 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
491 if (!(member is PropertyExpr || member is FieldExpr)) {
492 Error_InvalidNamedArgument (ec, a);
496 ObsoleteAttribute obsolete_attr;
498 if (member is PropertyExpr) {
499 PropertyInfo pi = ((PropertyExpr) member).PropertyInfo;
501 if (!pi.CanWrite || !pi.CanRead || pi.GetGetMethod ().IsStatic) {
502 ec.Report.SymbolRelatedToPreviousError (pi);
503 Error_InvalidNamedArgument (ec, a);
507 if (!IsValidArgumentType (member.Type)) {
508 ec.Report.SymbolRelatedToPreviousError (pi);
509 Error_InvalidNamedArgumentType (ec, a);
513 PropertyBase pb = TypeManager.GetProperty (pi);
515 obsolete_attr = pb.GetObsoleteAttribute ();
517 obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (pi);
520 var fi = ((FieldExpr) member).Spec;
522 if (fi.IsReadOnly || fi.IsStatic) {
523 Error_InvalidNamedArgument (ec, a);
527 if (!IsValidArgumentType (member.Type)) {
528 ec.Report.SymbolRelatedToPreviousError (fi.MetaInfo);
529 Error_InvalidNamedArgumentType (ec, a);
533 FieldBase fb = TypeManager.GetField (fi.MetaInfo);
535 obsolete_attr = fb.GetObsoleteAttribute ();
537 obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi.MetaInfo);
540 if (obsolete_attr != null && !context.IsObsolete)
541 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
543 if (a.Type != member.Type) {
544 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
548 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
555 /// Get a string containing a list of valid targets for the attribute 'attr'
557 public string GetValidTargets ()
559 StringBuilder sb = new StringBuilder ();
560 AttributeTargets targets = GetAttributeUsage (Type).ValidOn;
562 if ((targets & AttributeTargets.Assembly) != 0)
563 sb.Append ("assembly, ");
565 if ((targets & AttributeTargets.Module) != 0)
566 sb.Append ("module, ");
568 if ((targets & AttributeTargets.Class) != 0)
569 sb.Append ("class, ");
571 if ((targets & AttributeTargets.Struct) != 0)
572 sb.Append ("struct, ");
574 if ((targets & AttributeTargets.Enum) != 0)
575 sb.Append ("enum, ");
577 if ((targets & AttributeTargets.Constructor) != 0)
578 sb.Append ("constructor, ");
580 if ((targets & AttributeTargets.Method) != 0)
581 sb.Append ("method, ");
583 if ((targets & AttributeTargets.Property) != 0)
584 sb.Append ("property, indexer, ");
586 if ((targets & AttributeTargets.Field) != 0)
587 sb.Append ("field, ");
589 if ((targets & AttributeTargets.Event) != 0)
590 sb.Append ("event, ");
592 if ((targets & AttributeTargets.Interface) != 0)
593 sb.Append ("interface, ");
595 if ((targets & AttributeTargets.Parameter) != 0)
596 sb.Append ("parameter, ");
598 if ((targets & AttributeTargets.Delegate) != 0)
599 sb.Append ("delegate, ");
601 if ((targets & AttributeTargets.ReturnValue) != 0)
602 sb.Append ("return, ");
604 if ((targets & AttributeTargets.GenericParameter) != 0)
605 sb.Append ("type parameter, ");
607 return sb.Remove (sb.Length - 2, 2).ToString ();
611 /// Returns AttributeUsage attribute based on types hierarchy
613 static AttributeUsageAttribute GetAttributeUsage (Type type)
615 AttributeUsageAttribute ua;
616 if (usage_attr_cache.TryGetValue (type, out ua))
619 Class attr_class = TypeManager.LookupClass (type);
620 PredefinedAttribute pa = PredefinedAttributes.Get.AttributeUsage;
622 if (attr_class == null) {
624 return new AttributeUsageAttribute (0);
626 object[] usage_attr = type.GetCustomAttributes (pa.Type, true);
627 ua = (AttributeUsageAttribute)usage_attr [0];
628 usage_attr_cache.Add (type, ua);
633 if (attr_class.OptAttributes != null)
634 a = attr_class.OptAttributes.Search (pa);
637 if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type)
638 ua = GetAttributeUsage (attr_class.TypeBuilder.BaseType);
640 ua = DefaultUsageAttribute;
642 ua = a.GetAttributeUsageAttribute ();
645 usage_attr_cache.Add (type, ua);
649 AttributeUsageAttribute GetAttributeUsageAttribute ()
652 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
653 // But because a lot of attribute class code must be rewritten will be better to wait...
657 return DefaultUsageAttribute;
659 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
661 var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
663 usage_attribute.AllowMultiple = field.Value;
665 field = GetPropertyValue ("Inherited") as BoolConstant;
667 usage_attribute.Inherited = field.Value;
669 return usage_attribute;
673 /// Returns custom name of indexer
675 public string GetIndexerAttributeValue ()
678 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
679 // But because a lot of attribute class code must be rewritten will be better to wait...
685 return ((Constant) PosArguments [0].Expr).GetValue () as string;
689 /// Returns condition of ConditionalAttribute
691 public string GetConditionalAttributeValue ()
694 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
695 // But because a lot of attribute class code must be rewritten will be better to wait...
701 return ((Constant) PosArguments[0].Expr).GetValue () as string;
705 /// Creates the instance of ObsoleteAttribute from this attribute instance
707 public ObsoleteAttribute GetObsoleteAttribute ()
710 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
711 // But because a lot of attribute class code must be rewritten will be better to wait...
717 if (PosArguments == null)
718 return new ObsoleteAttribute ();
720 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
721 if (PosArguments.Count == 1)
722 return new ObsoleteAttribute (msg);
724 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
728 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
729 /// before ApplyAttribute. We need to resolve the arguments.
730 /// This situation occurs when class deps is differs from Emit order.
732 public bool GetClsCompliantAttributeValue ()
735 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
736 // But because a lot of attribute class code must be rewritten will be better to wait...
742 return ((BoolConstant) PosArguments[0].Expr).Value;
745 public Type GetCoClassAttributeValue ()
753 return ((Constant) PosArguments[0].Expr).GetValue () as Type;
756 public bool CheckTarget ()
758 string[] valid_targets = Owner.ValidAttributeTargets;
759 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
760 Target = Owner.AttributeTargets;
764 // TODO: we can skip the first item
765 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
766 switch (ExplicitTarget) {
767 case "return": Target = AttributeTargets.ReturnValue; return true;
768 case "param": Target = AttributeTargets.Parameter; return true;
769 case "field": Target = AttributeTargets.Field; return true;
770 case "method": Target = AttributeTargets.Method; return true;
771 case "property": Target = AttributeTargets.Property; return true;
773 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
776 StringBuilder sb = new StringBuilder ();
777 foreach (string s in valid_targets) {
781 sb.Remove (sb.Length - 2, 2);
782 Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
783 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
788 /// Tests permitted SecurityAction for assembly or other types
790 protected virtual bool IsSecurityActionValid (bool for_assembly)
792 SecurityAction action = GetSecurityActionValue ();
795 case SecurityAction.Demand:
796 case SecurityAction.Assert:
797 case SecurityAction.Deny:
798 case SecurityAction.PermitOnly:
799 case SecurityAction.LinkDemand:
800 case SecurityAction.InheritanceDemand:
805 case SecurityAction.RequestMinimum:
806 case SecurityAction.RequestOptional:
807 case SecurityAction.RequestRefuse:
813 Error_AttributeEmitError ("SecurityAction is out of range");
817 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
821 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
823 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
827 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
829 /// <returns></returns>
830 public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
832 Type orig_assembly_type = null;
834 if (TypeManager.LookupDeclSpace (Type) != null) {
835 if (!RootContext.StdLib) {
836 orig_assembly_type = Type.GetType (Type.FullName);
838 string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
839 if (orig_version_path == null) {
840 Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
844 if (orig_sec_assembly == null) {
845 string file = Path.Combine (orig_version_path, Driver.OutputFile);
846 orig_sec_assembly = Assembly.LoadFile (file);
849 orig_assembly_type = orig_sec_assembly.GetType (Type.FullName, true);
850 if (orig_assembly_type == null) {
851 Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
852 "was not found in previous version of assembly");
858 SecurityAttribute sa;
861 // For all non-selfreferencing security attributes we can avoid all hacks
862 if (orig_assembly_type == null) {
863 args = new object[PosArguments.Count];
864 for (int j = 0; j < args.Length; ++j) {
865 args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
868 sa = (SecurityAttribute) Activator.CreateInstance (Type, args);
870 if (named_values != null) {
871 for (int i = 0; i < named_values.Count; ++i) {
872 PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo;
873 pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
877 // HACK: All security attributes have same ctor syntax
878 args = new object[] { GetSecurityActionValue () };
879 sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, args);
881 // All types are from newly created assembly but for invocation with old one we need to convert them
882 if (named_values != null) {
883 for (int i = 0; i < named_values.Count; ++i) {
884 PropertyInfo emited_pi = ((PropertyExpr) named_values[i].Key).PropertyInfo;
885 // FIXME: We are missing return type filter
886 // TODO: pi can be null
887 PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
889 pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
895 perm = sa.CreatePermission ();
896 SecurityAction action = (SecurityAction) args [0];
898 // IS is correct because for corlib we are using an instance from old corlib
899 if (!(perm is System.Security.CodeAccessPermission)) {
901 case SecurityAction.Demand:
902 action = (SecurityAction)13;
904 case SecurityAction.LinkDemand:
905 action = (SecurityAction)14;
907 case SecurityAction.InheritanceDemand:
908 action = (SecurityAction)15;
914 if (!permissions.TryGetValue (action, out ps)) {
915 if (sa is PermissionSetAttribute)
916 ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
918 ps = new PermissionSet (PermissionState.None);
920 permissions.Add (action, ps);
921 } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
922 ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
923 permissions [action] = ps;
925 ps.AddPermission (perm);
928 public Constant GetPropertyValue (string name)
930 if (named_values == null)
933 for (int i = 0; i < named_values.Count; ++i) {
934 if (named_values [i].Value.Name == name)
935 return named_values [i].Value.Expr as Constant;
942 // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
943 // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
944 // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
947 public UnmanagedMarshal GetMarshal (Attributable attr)
949 UnmanagedType UnmanagedType;
950 if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
951 UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
953 UnmanagedType = (UnmanagedType) pos_values [0];
955 object value = GetFieldValue ("SizeParamIndex");
956 if (value != null && UnmanagedType != UnmanagedType.LPArray) {
957 Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
961 object o = GetFieldValue ("ArraySubType");
962 UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
964 switch (UnmanagedType) {
965 case UnmanagedType.CustomMarshaler: {
966 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
967 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
968 if (define_custom == null) {
969 Report.RuntimeMissingSupport (Location, "set marshal info");
973 object [] args = new object [4];
974 args [0] = GetFieldValue ("MarshalTypeRef");
975 args [1] = GetFieldValue ("MarshalCookie");
976 args [2] = GetFieldValue ("MarshalType");
977 args [3] = Guid.Empty;
978 return (UnmanagedMarshal) define_custom.Invoke (null, args);
980 case UnmanagedType.LPArray: {
981 object size_const = GetFieldValue ("SizeConst");
982 object size_param_index = GetFieldValue ("SizeParamIndex");
984 if ((size_const != null) || (size_param_index != null)) {
985 MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
986 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
987 if (define_array == null) {
988 Report.RuntimeMissingSupport (Location, "set marshal info");
992 object [] args = new object [3];
993 args [0] = array_sub_type;
994 args [1] = size_const == null ? -1 : size_const;
995 args [2] = size_param_index == null ? -1 : size_param_index;
996 return (UnmanagedMarshal) define_array.Invoke (null, args);
999 return UnmanagedMarshal.DefineLPArray (array_sub_type);
1001 case UnmanagedType.SafeArray:
1002 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
1004 case UnmanagedType.ByValArray:
1005 FieldBase fm = attr as FieldBase;
1007 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
1010 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
1012 case UnmanagedType.ByValTStr:
1013 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
1016 return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
1020 object GetFieldValue (string name)
1023 if (field_info_arr == null)
1026 foreach (FieldInfo fi in field_info_arr) {
1027 if (fi.Name == name)
1028 return GetValue (field_values_arr [i]);
1034 static object GetValue (object value)
1036 if (value is EnumConstant)
1037 return ((EnumConstant) value).GetValue ();
1044 public CharSet GetCharSetValue ()
1046 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
1049 public bool HasField (string fieldName)
1051 if (named_values == null)
1054 foreach (var na in named_values) {
1055 if (na.Value.Name == fieldName)
1062 public bool IsInternalMethodImplAttribute {
1064 if (Type != PredefinedAttributes.Get.MethodImpl)
1067 MethodImplOptions options;
1068 if (PosArguments [0].Type != typeof (MethodImplOptions))
1069 options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
1071 options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
1073 return (options & MethodImplOptions.InternalCall) != 0;
1077 public LayoutKind GetLayoutKindValue ()
1079 if (!RootContext.StdLib || PosArguments [0].Type != typeof (LayoutKind))
1080 return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
1082 return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
1085 public Constant GetParameterDefaultValue (out Type type)
1087 var expr = PosArguments[0].Expr;
1090 if (expr is TypeCast)
1091 expr = ((TypeCast) expr).Child;
1093 return expr as Constant;
1096 public override bool Equals (object obj)
1098 Attribute a = obj as Attribute;
1102 return Type == a.Type && Target == a.Target;
1105 public override int GetHashCode ()
1107 return type.GetHashCode () ^ Target.GetHashCode ();
1111 /// Emit attribute for Attributable symbol
1113 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1115 var ctor = Resolve ();
1119 AttributeUsageAttribute usage_attr = GetAttributeUsage (Type);
1120 if ((usage_attr.ValidOn & Target) == 0) {
1121 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1122 "It is valid on `{1}' declarations only",
1123 GetSignatureForError (), GetValidTargets ());
1127 var predefined = PredefinedAttributes.Get;
1129 AttributeEncoder encoder = new AttributeEncoder (false);
1131 if (PosArguments != null) {
1132 var param_types = TypeManager.GetParameterData (ctor).Types;
1133 for (int j = 0; j < PosArguments.Count; ++j) {
1134 var arg_expr = PosArguments[j].Expr;
1136 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
1137 string v = ((StringConstant) arg_expr).Value;
1138 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
1139 context.Compiler.Report.Error (633, arg_expr.Location,
1140 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1142 } else if (Type == predefined.Guid) {
1144 string v = ((StringConstant) arg_expr).Value;
1146 } catch (Exception e) {
1147 Error_AttributeEmitError (e.Message);
1149 } else if (Type == predefined.AttributeUsage) {
1150 int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
1152 context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1153 "System.AttributeUsage");
1156 } else if (j == 1) {
1157 if (Type == predefined.MethodImpl && param_types[j] == TypeManager.short_type &&
1158 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetTypedValue ())) {
1159 Error_AttributeEmitError ("Incorrect argument value.");
1163 arg_expr.EncodeAttributeValue (context, encoder, param_types[j]);
1167 if (named_values != null) {
1168 encoder.Stream.Write ((ushort) named_values.Count);
1169 foreach (var na in named_values) {
1170 if (na.Key is FieldExpr)
1171 encoder.Stream.Write ((byte) 0x53);
1173 encoder.Stream.Write ((byte) 0x54);
1175 encoder.Encode (na.Key.Type);
1176 encoder.Encode (na.Value.Name);
1177 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1180 encoder.Stream.Write ((ushort) 0);
1183 byte[] cdata = encoder.ToArray ();
1186 foreach (Attributable target in targets)
1187 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1188 } catch (Exception e) {
1189 Error_AttributeEmitError (e.Message);
1193 if (!usage_attr.AllowMultiple && allEmitted != null) {
1194 if (allEmitted.ContainsKey (this)) {
1195 var a = allEmitted [this];
1197 a = new List<Attribute> (2);
1198 allEmitted [this] = a;
1202 allEmitted.Add (this, null);
1206 if (!RootContext.VerifyClsCompliance)
1209 // Here we are testing attribute arguments for array usage (error 3016)
1210 if (Owner.IsClsComplianceRequired ()) {
1211 if (PosArguments != null)
1212 PosArguments.CheckArrayAsAttribute (context.Compiler);
1214 if (NamedArguments == null)
1217 NamedArguments.CheckArrayAsAttribute (context.Compiler);
1221 private Expression GetValue ()
1223 if (PosArguments == null || PosArguments.Count < 1)
1226 return PosArguments [0].Expr;
1229 public string GetString ()
1231 Expression e = GetValue ();
1232 if (e is StringConstant)
1233 return ((StringConstant)e).Value;
1237 public bool GetBoolean ()
1239 Expression e = GetValue ();
1240 if (e is BoolConstant)
1241 return ((BoolConstant)e).Value;
1245 public Type GetArgumentType ()
1247 TypeOf e = GetValue () as TypeOf;
1250 return e.TypeArgument;
1253 public override Expression CreateExpressionTree (ResolveContext ec)
1255 throw new NotSupportedException ("ET");
1258 protected override Expression DoResolve (ResolveContext ec)
1260 throw new NotImplementedException ();
1263 public override void Emit (EmitContext ec)
1265 throw new NotImplementedException ();
1271 /// For global attributes (assembly, module) we need special handling.
1272 /// Attributes can be located in the several files
1274 public class GlobalAttribute : Attribute
1276 public readonly NamespaceEntry ns;
1278 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1279 Arguments[] args, Location loc, bool nameEscaped):
1280 base (target, expression, args, loc, nameEscaped)
1285 public override void AttachTo (Attributable target, IMemberContext context)
1287 if (ExplicitTarget == "assembly") {
1288 base.AttachTo (CodeGen.Assembly, context);
1292 if (ExplicitTarget == "module") {
1293 base.AttachTo (RootContext.ToplevelTypes, context);
1297 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
1302 // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1303 // each time a new file is parsed. However, we need to use the NamespaceEntry
1304 // in effect where the attribute was used. Since code elsewhere cannot assume
1305 // that the NamespaceEntry is right, just overwrite it.
1307 // Precondition: RootContext.ToplevelTypes == null
1309 if (RootContext.ToplevelTypes.NamespaceEntry != null)
1310 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1312 RootContext.ToplevelTypes.NamespaceEntry = ns;
1315 protected override bool IsSecurityActionValid (bool for_assembly)
1317 return base.IsSecurityActionValid (true);
1322 RootContext.ToplevelTypes.NamespaceEntry = null;
1325 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1329 return base.ResolveAsTypeTerminal (expr, ec);
1336 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1340 return base.ResolveConstructor (ec);
1347 protected override bool ResolveNamedArguments (ResolveContext ec)
1351 return base.ResolveNamedArguments (ec);
1359 public class Attributes {
1360 public readonly List<Attribute> Attrs;
1362 public Attributes (Attribute a)
1364 Attrs = new List<Attribute> ();
1368 public Attributes (List<Attribute> attrs)
1373 public void AddAttributes (List<Attribute> attrs)
1375 Attrs.AddRange (attrs);
1378 public void AttachTo (Attributable attributable, IMemberContext context)
1380 foreach (Attribute a in Attrs)
1381 a.AttachTo (attributable, context);
1384 public Attributes Clone ()
1386 var al = new List<Attribute> (Attrs.Count);
1387 foreach (Attribute a in Attrs)
1388 al.Add (a.Clone ());
1390 return new Attributes (al);
1394 /// Checks whether attribute target is valid for the current element
1396 public bool CheckTargets ()
1398 foreach (Attribute a in Attrs) {
1399 if (!a.CheckTarget ())
1405 public Attribute Search (PredefinedAttribute t)
1407 foreach (Attribute a in Attrs) {
1408 if (a.ResolveType () == t)
1415 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1417 public Attribute[] SearchMulti (PredefinedAttribute t)
1419 List<Attribute> ar = null;
1421 foreach (Attribute a in Attrs) {
1422 if (a.ResolveType () == t) {
1424 ar = new List<Attribute> (Attrs.Count);
1429 return ar == null ? null : ar.ToArray ();
1436 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1438 foreach (Attribute a in Attrs)
1441 if (ld == null || ld.Count == 0)
1444 foreach (var d in ld) {
1445 if (d.Value == null)
1448 Attribute a = d.Key;
1450 foreach (Attribute collision in d.Value)
1451 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1453 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1454 a.GetSignatureForError ());
1458 public bool Contains (PredefinedAttribute t)
1460 return Search (t) != null;
1464 public struct AttributeEncoder
1466 public readonly BinaryWriter Stream;
1468 public AttributeEncoder (bool empty)
1475 Stream = new BinaryWriter (new MemoryStream ());
1476 const ushort version = 1;
1477 Stream.Write (version);
1480 public void Encode (string value)
1483 throw new ArgumentNullException ();
1485 var buf = Encoding.UTF8.GetBytes(value);
1486 WriteCompressedValue (buf.Length);
1490 public void Encode (Type type)
1492 if (type == TypeManager.bool_type) {
1493 Stream.Write ((byte) 0x02);
1494 } else if (type == TypeManager.char_type) {
1495 Stream.Write ((byte) 0x03);
1496 } else if (type == TypeManager.sbyte_type) {
1497 Stream.Write ((byte) 0x04);
1498 } else if (type == TypeManager.byte_type) {
1499 Stream.Write ((byte) 0x05);
1500 } else if (type == TypeManager.short_type) {
1501 Stream.Write ((byte) 0x06);
1502 } else if (type == TypeManager.ushort_type) {
1503 Stream.Write ((byte) 0x07);
1504 } else if (type == TypeManager.int32_type) {
1505 Stream.Write ((byte) 0x08);
1506 } else if (type == TypeManager.uint32_type) {
1507 Stream.Write ((byte) 0x09);
1508 } else if (type == TypeManager.int64_type) {
1509 Stream.Write ((byte) 0x0A);
1510 } else if (type == TypeManager.uint64_type) {
1511 Stream.Write ((byte) 0x0B);
1512 } else if (type == TypeManager.float_type) {
1513 Stream.Write ((byte) 0x0C);
1514 } else if (type == TypeManager.double_type) {
1515 Stream.Write ((byte) 0x0D);
1516 } else if (type == TypeManager.string_type) {
1517 Stream.Write ((byte) 0x0E);
1518 } else if (type == TypeManager.type_type) {
1519 Stream.Write ((byte) 0x50);
1520 } else if (type == TypeManager.object_type) {
1521 Stream.Write ((byte) 0x51);
1522 } else if (TypeManager.IsEnumType (type)) {
1523 Stream.Write ((byte) 0x55);
1524 EncodeTypeName (type);
1525 } else if (type.IsArray) {
1526 Stream.Write ((byte) 0x1D);
1527 Encode (TypeManager.GetElementType (type));
1529 throw new NotImplementedException (type.ToString ());
1533 public bool EncodeTypeName (Type type)
1535 if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
1538 Encode (CodeGen.Assembly.Builder == type.Assembly ? type.FullName : type.AssemblyQualifiedName);
1542 void WriteCompressedValue (int value)
1545 Stream.Write ((byte) value);
1549 if (value < 0x4000) {
1550 Stream.Write ((byte) (0x80 | (value >> 8)));
1551 Stream.Write ((byte) value);
1555 Stream.Write (value);
1558 public byte[] ToArray ()
1560 return ((MemoryStream) Stream.BaseStream).ToArray ();
1566 /// Helper class for attribute verification routine.
1568 sealed class AttributeTester
1570 static Dictionary<Type, bool> analyzed_types;
1571 static Dictionary<Type, ObsoleteAttribute> analyzed_types_obsolete;
1572 static Dictionary<MemberInfo, ObsoleteAttribute> analyzed_member_obsolete;
1573 static Dictionary<MethodBase, bool> analyzed_method_excluded;
1574 // static Dictionary<FieldInfo, IFixedBuffer> fixed_buffer_cache;
1576 static AttributeTester ()
1581 private AttributeTester ()
1585 public static void Reset ()
1587 analyzed_types = new Dictionary<Type, bool> (ReferenceEquality<Type>.Default);
1588 analyzed_types_obsolete = new Dictionary<Type, ObsoleteAttribute> (ReferenceEquality<Type>.Default);
1589 analyzed_member_obsolete = new Dictionary<MemberInfo, ObsoleteAttribute> (ReferenceEquality<MemberInfo>.Default);
1590 analyzed_method_excluded = new Dictionary<MethodBase, bool> (ReferenceEquality<MethodBase>.Default);
1591 // fixed_buffer_cache = new Dictionary<FieldInfo, IFixedBuffer> (ReferenceEquality<FieldInfo>.Default);
1594 public enum Result {
1601 /// Returns true if parameters of two compared methods are CLS-Compliant.
1602 /// It tests differing only in ref or out, or in array rank.
1604 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1606 Type [] types_a = pa.Types;
1607 Type [] types_b = pb.Types;
1608 if (types_a == null || types_b == null)
1611 if (types_a.Length != types_b.Length)
1614 Result result = Result.Ok;
1615 for (int i = 0; i < types_b.Length; ++i) {
1616 Type aType = types_a [i];
1617 Type bType = types_b [i];
1619 if (aType.IsArray && bType.IsArray) {
1620 Type a_el_type = TypeManager.GetElementType (aType);
1621 Type b_el_type = TypeManager.GetElementType (bType);
1622 if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) {
1623 result = Result.RefOutArrayError;
1627 if (a_el_type.IsArray || b_el_type.IsArray) {
1628 result = Result.ArrayArrayError;
1636 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1637 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1638 result = Result.RefOutArrayError;
1644 /// This method tests the CLS compliance of external types. It doesn't test type visibility.
1646 public static bool IsClsCompliant (Type type)
1652 if (analyzed_types.TryGetValue (type, out result))
1655 if (type.IsPointer) {
1656 analyzed_types.Add (type, false);
1661 result = IsClsCompliant (TypeManager.GetElementType (type));
1662 } else if (TypeManager.IsNullableType (type)) {
1663 result = IsClsCompliant (TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (type) [0]));
1665 result = AnalyzeTypeCompliance (type);
1667 analyzed_types.Add (type, result);
1671 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1673 Module[] modules = GlobalRootNamespace.Instance.Modules;
1674 if (modules == null)
1677 // The first module is generated assembly
1678 for (int i = 1; i < modules.Length; ++i) {
1679 Module module = modules [i];
1680 if (!GetClsCompliantAttributeValue (module, null)) {
1681 ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1682 "to match the assembly", module.Name);
1688 public static Type GetImportedIgnoreCaseClsType (string name)
1690 foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
1691 Type t = a.GetType (name, false, true);
1695 if (IsClsCompliant (t))
1701 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
1703 PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
1707 object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
1708 if (cls_attr.Length == 0) {
1712 return GetClsCompliantAttributeValue (a, null);
1715 return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1718 static bool AnalyzeTypeCompliance (Type type)
1720 type = TypeManager.DropGenericTypeArguments (type);
1721 DeclSpace ds = TypeManager.LookupDeclSpace (type);
1723 return ds.IsClsComplianceRequired ();
1726 if (TypeManager.IsGenericParameter (type))
1729 return GetClsCompliantAttributeValue (type, type.Assembly);
1733 /// Returns instance of ObsoleteAttribute when type is obsolete
1735 public static ObsoleteAttribute GetObsoleteAttribute (Type type)
1737 ObsoleteAttribute result;
1738 if (analyzed_types_obsolete.TryGetValue (type, out result))
1741 if (TypeManager.HasElementType (type)) {
1742 result = GetObsoleteAttribute (TypeManager.GetElementType (type));
1743 } else if (TypeManager.IsGenericParameter (type))
1744 result = null; // TODO: throw new NotSupportedException ()
1745 else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
1746 return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
1748 DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
1750 // Type is external, we can get attribute directly
1751 if (type_ds == null) {
1752 PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1754 object[] attribute = type.GetCustomAttributes (pa.Type, false);
1755 if (attribute.Length == 1)
1756 result = (ObsoleteAttribute) attribute[0];
1759 result = type_ds.GetObsoleteAttribute ();
1763 // Cannot use .Add because of corlib bootstrap
1764 analyzed_types_obsolete [type] = result;
1769 /// Returns instance of ObsoleteAttribute when method is obsolete
1771 public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
1773 IMethodData mc = TypeManager.GetMethod (mb);
1775 return mc.GetObsoleteAttribute ();
1777 // compiler generated methods are not registered by AddMethod
1778 if (mb.DeclaringType is TypeBuilder)
1781 MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
1783 return GetMemberObsoleteAttribute (mi);
1785 mi = TypeManager.GetEventFromAccessor (mb);
1787 return GetMemberObsoleteAttribute (mi);
1789 return GetMemberObsoleteAttribute (mb);
1793 /// Returns instance of ObsoleteAttribute when member is obsolete
1795 public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
1797 ObsoleteAttribute oa;
1798 if (analyzed_member_obsolete.TryGetValue (mi, out oa))
1801 if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
1804 PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
1808 oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false) as ObsoleteAttribute;
1809 analyzed_member_obsolete.Add (mi, oa);
1814 /// Common method for Obsolete error/warning reporting.
1816 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1819 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1823 if (oa.Message == null || oa.Message.Length == 0) {
1824 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1827 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1830 public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
1833 if (analyzed_method_excluded.TryGetValue (mb, out excluded))
1836 PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1840 ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
1841 as ConditionalAttribute[];
1842 if (attrs.Length == 0) {
1843 analyzed_method_excluded.Add (mb, false);
1847 foreach (ConditionalAttribute a in attrs) {
1848 if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
1849 analyzed_method_excluded.Add (mb, false);
1854 analyzed_method_excluded.Add (mb, true);
1859 /// Analyzes class whether it has attribute which has ConditionalAttribute
1860 /// and its condition is not defined.
1862 public static bool IsAttributeExcluded (Type type, Location loc)
1867 Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
1869 // TODO: add caching
1870 // TODO: merge all Type bases attribute caching to one cache to save memory
1871 PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
1872 if (class_decl == null && pa.IsDefined) {
1873 object[] attributes = type.GetCustomAttributes (pa.Type, false);
1874 foreach (ConditionalAttribute ca in attributes) {
1875 if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
1878 return attributes.Length > 0;
1881 return class_decl.IsExcluded ();
1884 public static Type GetCoClassAttribute (Type type)
1886 TypeContainer tc = TypeManager.LookupInterface (type);
1887 PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
1892 object[] o = type.GetCustomAttributes (pa.Type, false);
1895 return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
1898 if (tc.OptAttributes == null)
1901 Attribute a = tc.OptAttributes.Search (pa);
1905 return a.GetCoClassAttributeValue ();
1909 public class PredefinedAttributes
1912 public readonly PredefinedAttribute ParamArray;
1913 public readonly PredefinedAttribute Out;
1916 public readonly PredefinedAttribute Obsolete;
1917 public readonly PredefinedAttribute DllImport;
1918 public readonly PredefinedAttribute MethodImpl;
1919 public readonly PredefinedAttribute MarshalAs;
1920 public readonly PredefinedAttribute In;
1921 public readonly PredefinedAttribute IndexerName;
1922 public readonly PredefinedAttribute Conditional;
1923 public readonly PredefinedAttribute CLSCompliant;
1924 public readonly PredefinedAttribute Security;
1925 public readonly PredefinedAttribute Required;
1926 public readonly PredefinedAttribute Guid;
1927 public readonly PredefinedAttribute AssemblyCulture;
1928 public readonly PredefinedAttribute AssemblyVersion;
1929 public readonly PredefinedAttribute ComImport;
1930 public readonly PredefinedAttribute CoClass;
1931 public readonly PredefinedAttribute AttributeUsage;
1932 public readonly PredefinedAttribute DefaultParameterValue;
1933 public readonly PredefinedAttribute OptionalParameter;
1936 public readonly PredefinedAttribute DefaultCharset;
1937 public readonly PredefinedAttribute TypeForwarder;
1938 public readonly PredefinedAttribute FixedBuffer;
1939 public readonly PredefinedAttribute CompilerGenerated;
1940 public readonly PredefinedAttribute InternalsVisibleTo;
1941 public readonly PredefinedAttribute RuntimeCompatibility;
1942 public readonly PredefinedAttribute DebuggerHidden;
1943 public readonly PredefinedAttribute UnsafeValueType;
1946 public readonly PredefinedAttribute Extension;
1949 public readonly PredefinedAttribute Dynamic;
1950 public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
1953 // Optional types which are used as types and for member lookup
1955 public readonly PredefinedAttribute DefaultMember;
1956 public readonly PredefinedAttribute DecimalConstant;
1957 public readonly PredefinedAttribute StructLayout;
1958 public readonly PredefinedAttribute FieldOffset;
1960 public static PredefinedAttributes Get = new PredefinedAttributes ();
1962 private PredefinedAttributes ()
1964 ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1965 Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1967 Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1968 DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1969 MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1970 MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1971 In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1972 IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1973 Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1974 CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1975 Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1976 Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1977 Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1978 AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1979 AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1980 ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1981 CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1982 AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1983 DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1984 OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1986 DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1987 TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1988 FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1989 CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1990 InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1991 RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1992 DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1993 UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1995 Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1997 Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1998 DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
2000 DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
2001 DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
2002 StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
2003 FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
2006 public void Initialize (CompilerContext ctx)
2008 foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
2009 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
2013 public static void Reset ()
2015 Get = new PredefinedAttributes ();
2019 public class PredefinedAttribute
2022 CustomAttributeBuilder cab;
2023 ConstructorInfo ctor;
2024 readonly string ns, name;
2025 CompilerContext compiler;
2027 static readonly Type NotFound = typeof (PredefinedAttribute);
2029 public PredefinedAttribute (string ns, string name)
2035 public static bool operator == (Type type, PredefinedAttribute pa)
2037 return type == pa.type;
2040 public static bool operator != (Type type, PredefinedAttribute pa)
2042 return type != pa.type;
2045 public ConstructorInfo Constructor {
2046 get { return ctor; }
2049 public override int GetHashCode ()
2051 return base.GetHashCode ();
2054 public string GetSignatureForError ()
2056 return ns + "." + name;
2059 public override bool Equals (object obj)
2061 throw new NotSupportedException ();
2064 public void EmitAttribute (ConstructorBuilder builder)
2066 if (ResolveBuilder ())
2067 builder.SetCustomAttribute (cab);
2070 public void EmitAttribute (MethodBuilder builder)
2072 if (ResolveBuilder ())
2073 builder.SetCustomAttribute (cab);
2076 public void EmitAttribute (PropertyBuilder builder)
2078 if (ResolveBuilder ())
2079 builder.SetCustomAttribute (cab);
2082 public void EmitAttribute (FieldBuilder builder)
2084 if (ResolveBuilder ())
2085 builder.SetCustomAttribute (cab);
2088 public void EmitAttribute (TypeBuilder builder)
2090 if (ResolveBuilder ())
2091 builder.SetCustomAttribute (cab);
2094 public void EmitAttribute (AssemblyBuilder builder)
2096 if (ResolveBuilder ())
2097 builder.SetCustomAttribute (cab);
2100 public void EmitAttribute (ParameterBuilder builder)
2102 if (ResolveBuilder ())
2103 builder.SetCustomAttribute (cab);
2106 public bool IsDefined {
2107 get { return type != null && type != NotFound; }
2110 public void Initialize (CompilerContext ctx, bool canFail)
2112 this.compiler = ctx;
2116 public bool Resolve (bool canFail)
2125 type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
2134 bool ResolveBuilder ()
2140 // Handle all parameter-less attributes as optional
2142 if (!Resolve (true))
2145 ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
2149 cab = new CustomAttributeBuilder (ci, new object[0]);
2153 public bool ResolveConstructor (Location loc, params Type[] argType)
2156 throw new InternalErrorException ("Predefined ctor redefined");
2158 if (!Resolve (false))
2161 ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
2162 return ctor != null;
2166 get { return type; }