2010-05-27 Jb Evain <jbevain@novell.com>
[mcs.git] / mcs / attribute.cs
blob2d52af131cd4e3041373aebc92091375b27a409e
1 //
2 // attribute.cs: Attribute Handler
3 //
4 // Author: Ravi Pratap (ravi@ximian.com)
5 // Marek Safar (marek.safar@seznam.cz)
6 //
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
8 //
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
13 using System;
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;
22 using System.Text;
23 using System.IO;
25 namespace Mono.CSharp {
27 /// <summary>
28 /// Base class for objects that can have Attributes applied to them.
29 /// </summary>
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)
38 if (attrs == null)
39 return;
41 if (attributes == null)
42 attributes = attrs;
43 else
44 throw new NotImplementedException ();
46 attributes.AttachTo (this, context);
49 public Attributes OptAttributes {
50 get {
51 return attributes;
53 set {
54 attributes = value;
58 /// <summary>
59 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
60 /// </summary>
61 public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
63 /// <summary>
64 /// Returns one AttributeTarget for this element.
65 /// </summary>
66 public abstract AttributeTargets AttributeTargets { get; }
68 public abstract bool IsClsComplianceRequired ();
70 /// <summary>
71 /// Gets list of valid attribute targets for explicit target declaration.
72 /// The first array item is default target. Don't break this rule.
73 /// </summary>
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;
86 bool resolve_error;
87 bool arg_resolved;
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;
113 if (args != null) {
114 PosArguments = args [0];
115 NamedArguments = args [1];
117 this.loc = loc;
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;
127 return a;
130 static Attribute ()
132 Reset ();
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;
150 return;
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",
171 name.Name);
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",
178 name.Name);
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 ());
203 /// <summary>
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.
206 /// </summary>
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");
218 Attributable Owner {
219 get {
220 return targets [0];
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);
232 if (te == null)
233 return null;
235 TypeSpec t = te.Type;
236 if (t.IsAttribute) {
237 is_attr = true;
238 } else {
239 Report.SymbolRelatedToPreviousError (t);
240 Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
242 return t;
245 /// <summary>
246 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
247 /// </summary>
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;
255 TypeSpec t1, t2;
256 ATypeNameExpression expanded = null;
258 try {
259 t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
261 if (nameEscaped) {
262 t2 = null;
263 } else {
264 expanded = (ATypeNameExpression) expression.Clone (null);
265 expanded.Name += "Attribute";
267 t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
270 resolve_printer.EndSession ();
271 } finally {
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;
279 return;
282 if (t1_is_attr) {
283 Type = t1;
284 return;
287 if (t2_is_attr) {
288 Type = t2;
289 return;
292 resolve_printer.Merge (prev_recorder);
293 resolve_error = true;
296 public virtual TypeSpec ResolveType ()
298 if (Type == null && !resolve_error)
299 ResolveAttributeType ();
300 return Type;
303 public override string GetSignatureForError ()
305 if (Type != null)
306 return TypeManager.CSharpName (Type);
308 return expression.GetSignatureForError ();
311 public bool HasSecurityAttribute {
312 get {
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)
325 if (t.IsArray)
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
336 public string Name {
337 get { return expression.Name; }
340 void ApplyModuleCharSet (ResolveContext rc)
342 if (Type != PredefinedAttributes.Get.DllImport)
343 return;
345 if (!RootContext.ToplevelTypes.HasDefaultCharSet)
346 return;
348 const string CharSetEnumMember = "CharSet";
349 if (NamedArguments == null) {
350 NamedArguments = new Arguments (1);
351 } else {
352 foreach (NamedArgument a in NamedArguments) {
353 if (a.Name == CharSetEnumMember)
354 return;
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 ()
369 if (resolve_error)
370 return null;
372 resolve_error = true;
373 arg_resolved = true;
375 if (Type == null) {
376 ResolveAttributeType ();
377 if (Type == null)
378 return null;
381 if (Type.IsAbstract) {
382 Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
383 return null;
386 ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
387 if (obsolete_attr != null) {
388 AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
391 MethodSpec ctor;
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;
396 return ctor;
400 ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
401 ctor = ResolveConstructor (rc);
402 if (ctor == null) {
403 return null;
406 ApplyModuleCharSet (rc);
408 if (NamedArguments != null && !ResolveNamedArguments (rc)) {
409 return null;
412 resolve_error = false;
413 return ctor;
416 protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
418 if (PosArguments != null) {
419 bool dynamic;
420 PosArguments.Resolve (ec, out dynamic);
421 if (dynamic) {
422 Error_AttributeArgumentNotValid (ec, loc);
423 return null;
427 MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
428 Type, ConstructorInfo.ConstructorName, 0, MemberKind.Constructor,
429 BindingRestriction.AccessibleOnly | BindingRestriction.DeclaredOnly,
430 Location) as MethodGroupExpr;
432 if (mg == null)
433 throw new NotImplementedException ();
435 mg = mg.OverloadResolve (ec, ref PosArguments, false, Location);
436 if (mg == null)
437 return null;
439 var constructor = (MethodSpec) mg;
440 return constructor;
443 protected virtual bool ResolveNamedArguments (ResolveContext ec)
445 int named_arg_count = NamedArguments.Count;
446 var seen_names = new List<string> (named_arg_count);
448 named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
450 foreach (NamedArgument a in NamedArguments) {
451 string name = a.Name;
452 if (seen_names.Contains (name)) {
453 ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
454 continue;
457 seen_names.Add (name);
459 a.Resolve (ec);
461 Expression member = Expression.MemberLookup (ec.Compiler,
462 ec.CurrentType, Type, name, 0,
463 MemberKind.All,
464 BindingRestriction.AccessibleOnly,
465 Location);
467 if (member == null) {
468 member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name, 0,
469 MemberKind.All, BindingRestriction.None,
470 Location);
472 if (member != null) {
473 ec.Report.SymbolRelatedToPreviousError (member.Type);
474 Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
475 return false;
479 if (member == null){
480 Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
481 return false;
484 if (!(member is PropertyExpr || member is FieldExpr)) {
485 Error_InvalidNamedArgument (ec, a);
486 return false;
489 ObsoleteAttribute obsolete_attr;
491 if (member is PropertyExpr) {
492 var pi = ((PropertyExpr) member).PropertyInfo;
494 if (!pi.HasSet || !pi.HasGet || pi.IsStatic) {
495 ec.Report.SymbolRelatedToPreviousError (pi);
496 Error_InvalidNamedArgument (ec, a);
497 return false;
500 if (!IsValidArgumentType (member.Type)) {
501 ec.Report.SymbolRelatedToPreviousError (pi);
502 Error_InvalidNamedArgumentType (ec, a);
503 return false;
506 obsolete_attr = pi.GetAttributeObsolete ();
507 } else {
508 var fi = ((FieldExpr) member).Spec;
510 if (fi.IsReadOnly || fi.IsStatic) {
511 Error_InvalidNamedArgument (ec, a);
512 return false;
515 if (!IsValidArgumentType (member.Type)) {
516 ec.Report.SymbolRelatedToPreviousError (fi);
517 Error_InvalidNamedArgumentType (ec, a);
518 return false;
521 obsolete_attr = fi.GetAttributeObsolete ();
524 if (obsolete_attr != null && !context.IsObsolete)
525 AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
527 if (a.Type != member.Type) {
528 a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
531 if (a.Expr != null)
532 named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
535 return true;
538 /// <summary>
539 /// Get a string containing a list of valid targets for the attribute 'attr'
540 /// </summary>
541 public string GetValidTargets ()
543 StringBuilder sb = new StringBuilder ();
544 AttributeTargets targets = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage).ValidOn;
546 if ((targets & AttributeTargets.Assembly) != 0)
547 sb.Append ("assembly, ");
549 if ((targets & AttributeTargets.Module) != 0)
550 sb.Append ("module, ");
552 if ((targets & AttributeTargets.Class) != 0)
553 sb.Append ("class, ");
555 if ((targets & AttributeTargets.Struct) != 0)
556 sb.Append ("struct, ");
558 if ((targets & AttributeTargets.Enum) != 0)
559 sb.Append ("enum, ");
561 if ((targets & AttributeTargets.Constructor) != 0)
562 sb.Append ("constructor, ");
564 if ((targets & AttributeTargets.Method) != 0)
565 sb.Append ("method, ");
567 if ((targets & AttributeTargets.Property) != 0)
568 sb.Append ("property, indexer, ");
570 if ((targets & AttributeTargets.Field) != 0)
571 sb.Append ("field, ");
573 if ((targets & AttributeTargets.Event) != 0)
574 sb.Append ("event, ");
576 if ((targets & AttributeTargets.Interface) != 0)
577 sb.Append ("interface, ");
579 if ((targets & AttributeTargets.Parameter) != 0)
580 sb.Append ("parameter, ");
582 if ((targets & AttributeTargets.Delegate) != 0)
583 sb.Append ("delegate, ");
585 if ((targets & AttributeTargets.ReturnValue) != 0)
586 sb.Append ("return, ");
588 if ((targets & AttributeTargets.GenericParameter) != 0)
589 sb.Append ("type parameter, ");
591 return sb.Remove (sb.Length - 2, 2).ToString ();
594 public AttributeUsageAttribute GetAttributeUsageAttribute ()
596 if (!arg_resolved)
597 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
598 // But because a lot of attribute class code must be rewritten will be better to wait...
599 Resolve ();
601 if (resolve_error)
602 return DefaultUsageAttribute;
604 AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
606 var field = GetPropertyValue ("AllowMultiple") as BoolConstant;
607 if (field != null)
608 usage_attribute.AllowMultiple = field.Value;
610 field = GetPropertyValue ("Inherited") as BoolConstant;
611 if (field != null)
612 usage_attribute.Inherited = field.Value;
614 return usage_attribute;
617 /// <summary>
618 /// Returns custom name of indexer
619 /// </summary>
620 public string GetIndexerAttributeValue ()
622 if (!arg_resolved)
623 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
624 // But because a lot of attribute class code must be rewritten will be better to wait...
625 Resolve ();
627 if (resolve_error)
628 return null;
630 return ((Constant) PosArguments [0].Expr).GetValue () as string;
633 /// <summary>
634 /// Returns condition of ConditionalAttribute
635 /// </summary>
636 public string GetConditionalAttributeValue ()
638 if (!arg_resolved)
639 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
640 // But because a lot of attribute class code must be rewritten will be better to wait...
641 Resolve ();
643 if (resolve_error)
644 return null;
646 return ((Constant) PosArguments[0].Expr).GetValue () as string;
649 /// <summary>
650 /// Creates the instance of ObsoleteAttribute from this attribute instance
651 /// </summary>
652 public ObsoleteAttribute GetObsoleteAttribute ()
654 if (!arg_resolved) {
655 // corlib only case when obsolete is used before is resolved
656 var c = type.MemberDefinition as Class;
657 if (c != null && !c.HasMembersDefined)
658 c.Define ();
660 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
661 // But because a lot of attribute class code must be rewritten will be better to wait...
662 Resolve ();
665 if (resolve_error)
666 return null;
668 if (PosArguments == null)
669 return new ObsoleteAttribute ();
671 string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
672 if (PosArguments.Count == 1)
673 return new ObsoleteAttribute (msg);
675 return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
678 /// <summary>
679 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
680 /// before ApplyAttribute. We need to resolve the arguments.
681 /// This situation occurs when class deps is differs from Emit order.
682 /// </summary>
683 public bool GetClsCompliantAttributeValue ()
685 if (!arg_resolved)
686 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
687 // But because a lot of attribute class code must be rewritten will be better to wait...
688 Resolve ();
690 if (resolve_error)
691 return false;
693 return ((BoolConstant) PosArguments[0].Expr).Value;
696 public TypeSpec GetCoClassAttributeValue ()
698 if (!arg_resolved)
699 Resolve ();
701 if (resolve_error)
702 return null;
704 return GetArgumentType ();
707 public bool CheckTarget ()
709 string[] valid_targets = Owner.ValidAttributeTargets;
710 if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
711 Target = Owner.AttributeTargets;
712 return true;
715 // TODO: we can skip the first item
716 if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
717 switch (ExplicitTarget) {
718 case "return": Target = AttributeTargets.ReturnValue; return true;
719 case "param": Target = AttributeTargets.Parameter; return true;
720 case "field": Target = AttributeTargets.Field; return true;
721 case "method": Target = AttributeTargets.Method; return true;
722 case "property": Target = AttributeTargets.Property; return true;
724 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
727 StringBuilder sb = new StringBuilder ();
728 foreach (string s in valid_targets) {
729 sb.Append (s);
730 sb.Append (", ");
732 sb.Remove (sb.Length - 2, 2);
733 Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
734 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
735 return false;
738 /// <summary>
739 /// Tests permitted SecurityAction for assembly or other types
740 /// </summary>
741 protected virtual bool IsSecurityActionValid (bool for_assembly)
743 SecurityAction action = GetSecurityActionValue ();
745 switch (action) {
746 case SecurityAction.Demand:
747 case SecurityAction.Assert:
748 case SecurityAction.Deny:
749 case SecurityAction.PermitOnly:
750 case SecurityAction.LinkDemand:
751 case SecurityAction.InheritanceDemand:
752 if (!for_assembly)
753 return true;
754 break;
756 case SecurityAction.RequestMinimum:
757 case SecurityAction.RequestOptional:
758 case SecurityAction.RequestRefuse:
759 if (for_assembly)
760 return true;
761 break;
763 default:
764 Error_AttributeEmitError ("SecurityAction is out of range");
765 return false;
768 Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
769 return false;
772 System.Security.Permissions.SecurityAction GetSecurityActionValue ()
774 return (SecurityAction) ((Constant) PosArguments[0].Expr).GetTypedValue ();
777 /// <summary>
778 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
779 /// </summary>
780 /// <returns></returns>
781 public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
783 Type orig_assembly_type = null;
785 if (Type.MemberDefinition is TypeContainer) {
786 if (!RootContext.StdLib) {
787 orig_assembly_type = System.Type.GetType (Type.GetMetaInfo ().FullName);
788 } else {
789 string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
790 if (orig_version_path == null) {
791 Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
792 return;
795 if (orig_sec_assembly == null) {
796 string file = Path.Combine (orig_version_path, Driver.OutputFile);
797 orig_sec_assembly = Assembly.LoadFile (file);
800 orig_assembly_type = orig_sec_assembly.GetType (Type.GetMetaInfo ().FullName, true);
801 if (orig_assembly_type == null) {
802 Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
803 "was not found in previous version of assembly");
804 return;
809 SecurityAttribute sa;
810 object[] args;
812 // For all non-selfreferencing security attributes we can avoid all hacks
813 if (orig_assembly_type == null) {
814 args = new object[PosArguments.Count];
815 for (int j = 0; j < args.Length; ++j) {
816 args[j] = ((Constant) PosArguments[j].Expr).GetTypedValue ();
819 sa = (SecurityAttribute) Activator.CreateInstance (Type.GetMetaInfo (), args);
821 if (named_values != null) {
822 for (int i = 0; i < named_values.Count; ++i) {
823 PropertyInfo pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
824 pi.SetValue (sa, ((Constant) named_values [i].Value.Expr).GetTypedValue (), null);
827 } else {
828 // HACK: All security attributes have same ctor syntax
829 args = new object[] { GetSecurityActionValue () };
830 sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, args);
832 // All types are from newly created assembly but for invocation with old one we need to convert them
833 if (named_values != null) {
834 for (int i = 0; i < named_values.Count; ++i) {
835 PropertyInfo emited_pi = ((PropertyExpr) named_values[i].Key).PropertyInfo.MetaInfo;
836 // FIXME: We are missing return type filter
837 // TODO: pi can be null
838 PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
840 pi.SetValue (sa, ((Constant) named_values[i].Value.Expr).GetTypedValue (), null);
845 IPermission perm;
846 perm = sa.CreatePermission ();
847 SecurityAction action = (SecurityAction) args [0];
849 // IS is correct because for corlib we are using an instance from old corlib
850 if (!(perm is System.Security.CodeAccessPermission)) {
851 switch (action) {
852 case SecurityAction.Demand:
853 action = (SecurityAction)13;
854 break;
855 case SecurityAction.LinkDemand:
856 action = (SecurityAction)14;
857 break;
858 case SecurityAction.InheritanceDemand:
859 action = (SecurityAction)15;
860 break;
864 PermissionSet ps;
865 if (!permissions.TryGetValue (action, out ps)) {
866 if (sa is PermissionSetAttribute)
867 ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
868 else
869 ps = new PermissionSet (PermissionState.None);
871 permissions.Add (action, ps);
872 } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
873 ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
874 permissions [action] = ps;
876 ps.AddPermission (perm);
879 public Constant GetPropertyValue (string name)
881 if (named_values == null)
882 return null;
884 for (int i = 0; i < named_values.Count; ++i) {
885 if (named_values [i].Value.Name == name)
886 return named_values [i].Value.Expr as Constant;
889 return null;
893 // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
894 // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
895 // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
897 #if false
898 public UnmanagedMarshal GetMarshal (Attributable attr)
900 UnmanagedType UnmanagedType;
901 if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
902 UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
903 else
904 UnmanagedType = (UnmanagedType) pos_values [0];
906 object value = GetFieldValue ("SizeParamIndex");
907 if (value != null && UnmanagedType != UnmanagedType.LPArray) {
908 Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
909 return null;
912 object o = GetFieldValue ("ArraySubType");
913 UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
915 switch (UnmanagedType) {
916 case UnmanagedType.CustomMarshaler: {
917 MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
918 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
919 if (define_custom == null) {
920 Report.RuntimeMissingSupport (Location, "set marshal info");
921 return null;
924 object [] args = new object [4];
925 args [0] = GetFieldValue ("MarshalTypeRef");
926 args [1] = GetFieldValue ("MarshalCookie");
927 args [2] = GetFieldValue ("MarshalType");
928 args [3] = Guid.Empty;
929 return (UnmanagedMarshal) define_custom.Invoke (null, args);
931 case UnmanagedType.LPArray: {
932 object size_const = GetFieldValue ("SizeConst");
933 object size_param_index = GetFieldValue ("SizeParamIndex");
935 if ((size_const != null) || (size_param_index != null)) {
936 MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
937 BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
938 if (define_array == null) {
939 Report.RuntimeMissingSupport (Location, "set marshal info");
940 return null;
943 object [] args = new object [3];
944 args [0] = array_sub_type;
945 args [1] = size_const == null ? -1 : size_const;
946 args [2] = size_param_index == null ? -1 : size_param_index;
947 return (UnmanagedMarshal) define_array.Invoke (null, args);
949 else
950 return UnmanagedMarshal.DefineLPArray (array_sub_type);
952 case UnmanagedType.SafeArray:
953 return UnmanagedMarshal.DefineSafeArray (array_sub_type);
955 case UnmanagedType.ByValArray:
956 FieldBase fm = attr as FieldBase;
957 if (fm == null) {
958 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
959 return null;
961 return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
963 case UnmanagedType.ByValTStr:
964 return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
966 default:
967 return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
971 object GetFieldValue (string name)
973 int i;
974 if (field_info_arr == null)
975 return null;
976 i = 0;
977 foreach (FieldInfo fi in field_info_arr) {
978 if (fi.Name == name)
979 return GetValue (field_values_arr [i]);
980 i++;
982 return null;
985 static object GetValue (object value)
987 if (value is EnumConstant)
988 return ((EnumConstant) value).GetValue ();
989 else
990 return value;
993 #endif
995 public CharSet GetCharSetValue ()
997 return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
1000 public bool HasField (string fieldName)
1002 if (named_values == null)
1003 return false;
1005 foreach (var na in named_values) {
1006 if (na.Value.Name == fieldName)
1007 return true;
1010 return false;
1013 public bool IsInternalMethodImplAttribute {
1014 get {
1015 if (Type != PredefinedAttributes.Get.MethodImpl)
1016 return false;
1018 MethodImplOptions options;
1019 if (PosArguments[0].Type.GetMetaInfo () != typeof (MethodImplOptions))
1020 options = (MethodImplOptions) System.Enum.ToObject (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ());
1021 else
1022 options = (MethodImplOptions) ((Constant) PosArguments [0].Expr).GetValue ();
1024 return (options & MethodImplOptions.InternalCall) != 0;
1028 public LayoutKind GetLayoutKindValue ()
1030 if (!RootContext.StdLib || PosArguments[0].Type.GetMetaInfo () != typeof (LayoutKind))
1031 return (LayoutKind) System.Enum.ToObject (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ());
1033 return (LayoutKind) ((Constant) PosArguments[0].Expr).GetValue ();
1036 public Constant GetParameterDefaultValue (out TypeSpec type)
1038 var expr = PosArguments[0].Expr;
1040 if (expr is TypeCast)
1041 expr = ((TypeCast) expr).Child;
1043 type = expr.Type;
1044 return expr as Constant;
1047 public override bool Equals (object obj)
1049 Attribute a = obj as Attribute;
1050 if (a == null)
1051 return false;
1053 return Type == a.Type && Target == a.Target;
1056 public override int GetHashCode ()
1058 return type.GetHashCode () ^ Target.GetHashCode ();
1061 /// <summary>
1062 /// Emit attribute for Attributable symbol
1063 /// </summary>
1064 public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1066 var ctor = Resolve ();
1067 if (ctor == null)
1068 return;
1070 AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (PredefinedAttributes.Get.AttributeUsage);
1071 if ((usage_attr.ValidOn & Target) == 0) {
1072 Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1073 "It is valid on `{1}' declarations only",
1074 GetSignatureForError (), GetValidTargets ());
1075 return;
1078 var predefined = PredefinedAttributes.Get;
1080 AttributeEncoder encoder = new AttributeEncoder (false);
1082 if (PosArguments != null) {
1083 var param_types = ctor.Parameters.Types;
1084 for (int j = 0; j < PosArguments.Count; ++j) {
1085 var pt = param_types[j];
1086 if (!IsValidArgumentType (pt)) {
1087 Error_AttributeArgumentNotValid (context, loc);
1088 return;
1091 var arg_expr = PosArguments[j].Expr;
1092 if (j == 0) {
1093 if (Type == predefined.IndexerName || Type == predefined.Conditional) {
1094 string v = ((StringConstant) arg_expr).Value;
1095 if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
1096 context.Compiler.Report.Error (633, arg_expr.Location,
1097 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1099 } else if (Type == predefined.Guid) {
1100 try {
1101 string v = ((StringConstant) arg_expr).Value;
1102 new Guid (v);
1103 } catch (Exception e) {
1104 Error_AttributeEmitError (e.Message);
1105 return;
1107 } else if (Type == predefined.AttributeUsage) {
1108 int v = ((IntConstant)((EnumConstant) arg_expr).Child).Value;
1109 if (v == 0) {
1110 context.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1111 "System.AttributeUsage");
1113 } else if (Type == predefined.MethodImpl && pt == TypeManager.short_type &&
1114 !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
1115 Error_AttributeEmitError ("Incorrect argument value.");
1116 return;
1120 arg_expr.EncodeAttributeValue (context, encoder, pt);
1124 if (named_values != null) {
1125 encoder.Stream.Write ((ushort) named_values.Count);
1126 foreach (var na in named_values) {
1127 if (na.Key is FieldExpr)
1128 encoder.Stream.Write ((byte) 0x53);
1129 else
1130 encoder.Stream.Write ((byte) 0x54);
1132 encoder.Encode (na.Key.Type);
1133 encoder.Encode (na.Value.Name);
1134 na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1136 } else {
1137 encoder.Stream.Write ((ushort) 0);
1140 byte[] cdata = encoder.ToArray ();
1142 try {
1143 foreach (Attributable target in targets)
1144 target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1145 } catch (Exception e) {
1146 Error_AttributeEmitError (e.Message);
1147 return;
1150 if (!usage_attr.AllowMultiple && allEmitted != null) {
1151 if (allEmitted.ContainsKey (this)) {
1152 var a = allEmitted [this];
1153 if (a == null) {
1154 a = new List<Attribute> (2);
1155 allEmitted [this] = a;
1157 a.Add (this);
1158 } else {
1159 allEmitted.Add (this, null);
1163 if (!RootContext.VerifyClsCompliance)
1164 return;
1166 // Here we are testing attribute arguments for array usage (error 3016)
1167 if (Owner.IsClsComplianceRequired ()) {
1168 if (PosArguments != null)
1169 PosArguments.CheckArrayAsAttribute (context.Compiler);
1171 if (NamedArguments == null)
1172 return;
1174 NamedArguments.CheckArrayAsAttribute (context.Compiler);
1178 private Expression GetValue ()
1180 if (PosArguments == null || PosArguments.Count < 1)
1181 return null;
1183 return PosArguments [0].Expr;
1186 public string GetString ()
1188 Expression e = GetValue ();
1189 if (e is StringConstant)
1190 return ((StringConstant)e).Value;
1191 return null;
1194 public bool GetBoolean ()
1196 Expression e = GetValue ();
1197 if (e is BoolConstant)
1198 return ((BoolConstant)e).Value;
1199 return false;
1202 public TypeSpec GetArgumentType ()
1204 TypeOf e = GetValue () as TypeOf;
1205 if (e == null)
1206 return null;
1207 return e.TypeArgument;
1210 public override Expression CreateExpressionTree (ResolveContext ec)
1212 throw new NotSupportedException ("ET");
1215 protected override Expression DoResolve (ResolveContext ec)
1217 throw new NotImplementedException ();
1220 public override void Emit (EmitContext ec)
1222 throw new NotImplementedException ();
1227 /// <summary>
1228 /// For global attributes (assembly, module) we need special handling.
1229 /// Attributes can be located in the several files
1230 /// </summary>
1231 public class GlobalAttribute : Attribute
1233 public readonly NamespaceEntry ns;
1235 public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
1236 Arguments[] args, Location loc, bool nameEscaped):
1237 base (target, expression, args, loc, nameEscaped)
1239 this.ns = ns;
1242 public override void AttachTo (Attributable target, IMemberContext context)
1244 if (ExplicitTarget == "assembly") {
1245 base.AttachTo (CodeGen.Assembly, context);
1246 return;
1249 if (ExplicitTarget == "module") {
1250 base.AttachTo (RootContext.ToplevelTypes, context);
1251 return;
1254 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
1257 void Enter ()
1259 // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1260 // each time a new file is parsed. However, we need to use the NamespaceEntry
1261 // in effect where the attribute was used. Since code elsewhere cannot assume
1262 // that the NamespaceEntry is right, just overwrite it.
1264 // Precondition: RootContext.ToplevelTypes == null
1266 if (RootContext.ToplevelTypes.NamespaceEntry != null)
1267 throw new InternalErrorException (Location + " non-null NamespaceEntry");
1269 RootContext.ToplevelTypes.NamespaceEntry = ns;
1272 protected override bool IsSecurityActionValid (bool for_assembly)
1274 return base.IsSecurityActionValid (true);
1277 void Leave ()
1279 RootContext.ToplevelTypes.NamespaceEntry = null;
1282 protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
1284 try {
1285 Enter ();
1286 return base.ResolveAsTypeTerminal (expr, ec);
1288 finally {
1289 Leave ();
1293 protected override MethodSpec ResolveConstructor (ResolveContext ec)
1295 try {
1296 Enter ();
1297 return base.ResolveConstructor (ec);
1299 finally {
1300 Leave ();
1304 protected override bool ResolveNamedArguments (ResolveContext ec)
1306 try {
1307 Enter ();
1308 return base.ResolveNamedArguments (ec);
1310 finally {
1311 Leave ();
1316 public class Attributes {
1317 public readonly List<Attribute> Attrs;
1319 public Attributes (Attribute a)
1321 Attrs = new List<Attribute> ();
1322 Attrs.Add (a);
1325 public Attributes (List<Attribute> attrs)
1327 Attrs = attrs;
1330 public void AddAttributes (List<Attribute> attrs)
1332 Attrs.AddRange (attrs);
1335 public void AttachTo (Attributable attributable, IMemberContext context)
1337 foreach (Attribute a in Attrs)
1338 a.AttachTo (attributable, context);
1341 public Attributes Clone ()
1343 var al = new List<Attribute> (Attrs.Count);
1344 foreach (Attribute a in Attrs)
1345 al.Add (a.Clone ());
1347 return new Attributes (al);
1350 /// <summary>
1351 /// Checks whether attribute target is valid for the current element
1352 /// </summary>
1353 public bool CheckTargets ()
1355 foreach (Attribute a in Attrs) {
1356 if (!a.CheckTarget ())
1357 return false;
1359 return true;
1362 public Attribute Search (PredefinedAttribute t)
1364 foreach (Attribute a in Attrs) {
1365 if (a.ResolveType () == t)
1366 return a;
1368 return null;
1371 /// <summary>
1372 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1373 /// </summary>
1374 public Attribute[] SearchMulti (PredefinedAttribute t)
1376 List<Attribute> ar = null;
1378 foreach (Attribute a in Attrs) {
1379 if (a.ResolveType () == t) {
1380 if (ar == null)
1381 ar = new List<Attribute> (Attrs.Count);
1382 ar.Add (a);
1386 return ar == null ? null : ar.ToArray ();
1389 public void Emit ()
1391 CheckTargets ();
1393 Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1395 foreach (Attribute a in Attrs)
1396 a.Emit (ld);
1398 if (ld == null || ld.Count == 0)
1399 return;
1401 foreach (var d in ld) {
1402 if (d.Value == null)
1403 continue;
1405 Attribute a = d.Key;
1407 foreach (Attribute collision in d.Value)
1408 a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1410 a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1411 a.GetSignatureForError ());
1415 public bool Contains (PredefinedAttribute t)
1417 return Search (t) != null;
1421 public struct AttributeEncoder
1423 public readonly BinaryWriter Stream;
1425 public AttributeEncoder (bool empty)
1427 if (empty) {
1428 Stream = null;
1429 return;
1432 Stream = new BinaryWriter (new MemoryStream ());
1433 const ushort version = 1;
1434 Stream.Write (version);
1437 public void Encode (string value)
1439 if (value == null)
1440 throw new ArgumentNullException ();
1442 var buf = Encoding.UTF8.GetBytes(value);
1443 WriteCompressedValue (buf.Length);
1444 Stream.Write (buf);
1447 public void Encode (TypeSpec type)
1449 if (type == TypeManager.bool_type) {
1450 Stream.Write ((byte) 0x02);
1451 } else if (type == TypeManager.char_type) {
1452 Stream.Write ((byte) 0x03);
1453 } else if (type == TypeManager.sbyte_type) {
1454 Stream.Write ((byte) 0x04);
1455 } else if (type == TypeManager.byte_type) {
1456 Stream.Write ((byte) 0x05);
1457 } else if (type == TypeManager.short_type) {
1458 Stream.Write ((byte) 0x06);
1459 } else if (type == TypeManager.ushort_type) {
1460 Stream.Write ((byte) 0x07);
1461 } else if (type == TypeManager.int32_type) {
1462 Stream.Write ((byte) 0x08);
1463 } else if (type == TypeManager.uint32_type) {
1464 Stream.Write ((byte) 0x09);
1465 } else if (type == TypeManager.int64_type) {
1466 Stream.Write ((byte) 0x0A);
1467 } else if (type == TypeManager.uint64_type) {
1468 Stream.Write ((byte) 0x0B);
1469 } else if (type == TypeManager.float_type) {
1470 Stream.Write ((byte) 0x0C);
1471 } else if (type == TypeManager.double_type) {
1472 Stream.Write ((byte) 0x0D);
1473 } else if (type == TypeManager.string_type) {
1474 Stream.Write ((byte) 0x0E);
1475 } else if (type == TypeManager.type_type) {
1476 Stream.Write ((byte) 0x50);
1477 } else if (type == TypeManager.object_type) {
1478 Stream.Write ((byte) 0x51);
1479 } else if (TypeManager.IsEnumType (type)) {
1480 Stream.Write ((byte) 0x55);
1481 EncodeTypeName (type);
1482 } else if (type.IsArray) {
1483 Stream.Write ((byte) 0x1D);
1484 Encode (TypeManager.GetElementType (type));
1485 } else {
1486 throw new NotImplementedException (type.ToString ());
1490 public bool EncodeTypeName (TypeSpec type)
1492 // if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
1493 // return false;
1495 var old_type = type.GetMetaInfo ();
1496 Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1497 return true;
1500 void WriteCompressedValue (int value)
1502 if (value < 0x80) {
1503 Stream.Write ((byte) value);
1504 return;
1507 if (value < 0x4000) {
1508 Stream.Write ((byte) (0x80 | (value >> 8)));
1509 Stream.Write ((byte) value);
1510 return;
1513 Stream.Write (value);
1516 public byte[] ToArray ()
1518 return ((MemoryStream) Stream.BaseStream).ToArray ();
1523 /// <summary>
1524 /// Helper class for attribute verification routine.
1525 /// </summary>
1526 static class AttributeTester
1528 public enum Result {
1530 RefOutArrayError,
1531 ArrayArrayError
1534 /// <summary>
1535 /// Returns true if parameters of two compared methods are CLS-Compliant.
1536 /// It tests differing only in ref or out, or in array rank.
1537 /// </summary>
1538 public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
1540 TypeSpec [] types_a = pa.Types;
1541 TypeSpec [] types_b = pb.Types;
1542 if (types_a == null || types_b == null)
1543 return Result.Ok;
1545 if (types_a.Length != types_b.Length)
1546 return Result.Ok;
1548 Result result = Result.Ok;
1549 for (int i = 0; i < types_b.Length; ++i) {
1550 TypeSpec aType = types_a [i];
1551 TypeSpec bType = types_b [i];
1553 var ac_a = aType as ArrayContainer;
1554 var ac_b = aType as ArrayContainer;
1556 if (ac_a != null && ac_b != null) {
1557 if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
1558 result = Result.RefOutArrayError;
1559 continue;
1562 if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
1563 result = Result.ArrayArrayError;
1564 continue;
1568 if (aType != bType)
1569 return Result.Ok;
1571 const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
1572 if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
1573 result = Result.RefOutArrayError;
1575 return result;
1578 public static void VerifyModulesClsCompliance (CompilerContext ctx)
1580 Module[] modules = GlobalRootNamespace.Instance.Modules;
1581 if (modules == null)
1582 return;
1584 // The first module is generated assembly
1585 for (int i = 1; i < modules.Length; ++i) {
1586 Module module = modules [i];
1587 if (!GetClsCompliantAttributeValue (module, null)) {
1588 ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1589 "to match the assembly", module.Name);
1590 return;
1595 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
1597 object[] cls_attr = attribute_provider.GetCustomAttributes (typeof (CLSCompliantAttribute), false);
1598 if (cls_attr.Length == 0) {
1599 if (a == null)
1600 return false;
1602 return GetClsCompliantAttributeValue (a, null);
1605 return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
1608 /// <summary>
1609 /// Common method for Obsolete error/warning reporting.
1610 /// </summary>
1611 public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1613 if (oa.IsError) {
1614 Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1615 return;
1618 if (oa.Message == null || oa.Message.Length == 0) {
1619 Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1620 return;
1622 Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1626 public class PredefinedAttributes
1628 // Core types
1629 public readonly PredefinedAttribute ParamArray;
1630 public readonly PredefinedAttribute Out;
1632 // Optional types
1633 public readonly PredefinedAttribute Obsolete;
1634 public readonly PredefinedAttribute DllImport;
1635 public readonly PredefinedAttribute MethodImpl;
1636 public readonly PredefinedAttribute MarshalAs;
1637 public readonly PredefinedAttribute In;
1638 public readonly PredefinedAttribute IndexerName;
1639 public readonly PredefinedAttribute Conditional;
1640 public readonly PredefinedAttribute CLSCompliant;
1641 public readonly PredefinedAttribute Security;
1642 public readonly PredefinedAttribute Required;
1643 public readonly PredefinedAttribute Guid;
1644 public readonly PredefinedAttribute AssemblyCulture;
1645 public readonly PredefinedAttribute AssemblyVersion;
1646 public readonly PredefinedAttribute AssemblyAlgorithmId;
1647 public readonly PredefinedAttribute AssemblyFlags;
1648 public readonly PredefinedAttribute ComImport;
1649 public readonly PredefinedAttribute CoClass;
1650 public readonly PredefinedAttribute AttributeUsage;
1651 public readonly PredefinedAttribute DefaultParameterValue;
1652 public readonly PredefinedAttribute OptionalParameter;
1654 // New in .NET 2.0
1655 public readonly PredefinedAttribute DefaultCharset;
1656 public readonly PredefinedAttribute TypeForwarder;
1657 public readonly PredefinedAttribute FixedBuffer;
1658 public readonly PredefinedAttribute CompilerGenerated;
1659 public readonly PredefinedAttribute InternalsVisibleTo;
1660 public readonly PredefinedAttribute RuntimeCompatibility;
1661 public readonly PredefinedAttribute DebuggerHidden;
1662 public readonly PredefinedAttribute UnsafeValueType;
1664 // New in .NET 3.5
1665 public readonly PredefinedAttribute Extension;
1667 // New in .NET 4.0
1668 public readonly PredefinedAttribute Dynamic;
1669 public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
1672 // Optional types which are used as types and for member lookup
1674 public readonly PredefinedAttribute DefaultMember;
1675 public readonly PredefinedAttribute DecimalConstant;
1676 public readonly PredefinedAttribute StructLayout;
1677 public readonly PredefinedAttribute FieldOffset;
1679 public static PredefinedAttributes Get = new PredefinedAttributes ();
1681 private PredefinedAttributes ()
1683 ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
1684 Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1686 Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
1687 DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1688 MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1689 MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1690 In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1691 IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1692 Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1693 CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
1694 Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1695 Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1696 Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1697 AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1698 AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1699 AssemblyAlgorithmId = new PredefinedAttribute ("System.Reflection", "AssemblyAlgorithmIdAttribute");
1700 AssemblyFlags = new PredefinedAttribute ("System.Reflection", "AssemblyFlagsAttribute");
1701 ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1702 CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1703 AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
1704 DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1705 OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1707 DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1708 TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1709 FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1710 CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1711 InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1712 RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1713 DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1714 UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1716 Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1718 Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1719 DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1721 DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
1722 DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1723 StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
1724 FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1727 public void Initialize (CompilerContext ctx)
1729 foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
1730 ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
1734 public static void Reset ()
1736 Get = new PredefinedAttributes ();
1740 public class PredefinedAttribute
1742 TypeSpec type;
1743 CustomAttributeBuilder cab;
1744 MethodSpec ctor;
1745 readonly string ns, name;
1746 CompilerContext compiler;
1748 static readonly TypeSpec NotFound = InternalType.Null;
1750 public PredefinedAttribute (string ns, string name)
1752 this.ns = ns;
1753 this.name = name;
1756 public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1758 return type == pa.type;
1761 public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1763 return type != pa.type;
1766 public ConstructorInfo Constructor {
1767 get { return ctor == null ? null : (ConstructorInfo) ctor.GetMetaInfo (); }
1770 public override int GetHashCode ()
1772 return base.GetHashCode ();
1775 public string GetSignatureForError ()
1777 return ns + "." + name;
1780 public override bool Equals (object obj)
1782 throw new NotSupportedException ();
1785 public void EmitAttribute (ConstructorBuilder builder)
1787 if (ResolveBuilder ())
1788 builder.SetCustomAttribute (cab);
1791 public void EmitAttribute (MethodBuilder builder)
1793 if (ResolveBuilder ())
1794 builder.SetCustomAttribute (cab);
1797 public void EmitAttribute (PropertyBuilder builder)
1799 if (ResolveBuilder ())
1800 builder.SetCustomAttribute (cab);
1803 public void EmitAttribute (FieldBuilder builder)
1805 if (ResolveBuilder ())
1806 builder.SetCustomAttribute (cab);
1809 public void EmitAttribute (TypeBuilder builder)
1811 if (ResolveBuilder ())
1812 builder.SetCustomAttribute (cab);
1815 public void EmitAttribute (AssemblyBuilder builder)
1817 if (ResolveBuilder ())
1818 builder.SetCustomAttribute (cab);
1821 public void EmitAttribute (ParameterBuilder builder)
1823 if (ResolveBuilder ())
1824 builder.SetCustomAttribute (cab);
1827 public bool IsDefined {
1828 get { return type != null && type != NotFound; }
1831 public void Initialize (CompilerContext ctx, bool canFail)
1833 this.compiler = ctx;
1834 Resolve (canFail);
1837 public bool Resolve (bool canFail)
1839 if (type != null) {
1840 if (IsDefined)
1841 return true;
1842 if (canFail)
1843 return false;
1846 type = TypeManager.CoreLookupType (compiler, ns, name, MemberKind.Class, !canFail);
1847 if (type == null) {
1848 type = NotFound;
1849 return false;
1852 return true;
1855 bool ResolveBuilder ()
1857 if (cab != null)
1858 return true;
1861 // Handle all parameter-less attributes as optional
1863 if (!Resolve (true))
1864 return false;
1866 var ci = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
1867 if (ci == null)
1868 return false;
1870 cab = new CustomAttributeBuilder ((ConstructorInfo) ci.GetMetaInfo (), new object[0]);
1871 return true;
1874 public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
1876 if (ctor != null)
1877 throw new InternalErrorException ("Predefined ctor redefined");
1879 if (!Resolve (false))
1880 return false;
1882 ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
1883 return ctor != null;
1886 public TypeSpec Type {
1887 get { return type; }