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
;
16 using System
.Collections
.Specialized
;
17 using System
.Reflection
;
18 using System
.Reflection
.Emit
;
19 using System
.Runtime
.InteropServices
;
20 using System
.Runtime
.CompilerServices
;
21 using System
.Security
;
22 using System
.Security
.Permissions
;
26 namespace Mono
.CSharp
{
29 /// Base class for objects that can have Attributes applied to them.
31 public abstract class Attributable
{
33 // Holds all attributes attached to this element
35 protected Attributes attributes
;
37 public void AddAttributes (Attributes attrs
, IMemberContext context
)
42 if (attributes
== null)
45 throw new NotImplementedException ();
47 attributes
.AttachTo (this, context
);
50 public Attributes OptAttributes
{
60 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
62 public abstract void ApplyAttributeBuilder (Attribute a
, CustomAttributeBuilder cb
, PredefinedAttributes pa
);
65 /// Returns one AttributeTarget for this element.
67 public abstract AttributeTargets AttributeTargets { get; }
69 public abstract bool IsClsComplianceRequired ();
72 /// Gets list of valid attribute targets for explicit target declaration.
73 /// The first array item is default target. Don't break this rule.
75 public abstract string[] ValidAttributeTargets { get; }
78 public class Attribute
: Expression
80 public readonly string ExplicitTarget
;
81 public AttributeTargets Target
;
82 readonly ATypeNameExpression expression
;
84 Arguments PosArguments
;
85 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 // non-null if named args present after Resolve () is called
106 PropertyInfo
[] prop_info_arr
;
107 FieldInfo
[] field_info_arr
;
108 object [] field_values_arr
;
109 object [] prop_values_arr
;
110 object [] pos_values
;
112 static PtrHashtable usage_attr_cache
;
113 // Cache for parameter-less attributes
114 static PtrHashtable att_cache
;
116 public Attribute (string target
, ATypeNameExpression expr
, Arguments
[] args
, Location loc
, bool nameEscaped
)
118 this.expression
= expr
;
120 PosArguments
= args
[0];
121 NamedArguments
= args
[1];
124 ExplicitTarget
= target
;
125 this.nameEscaped
= nameEscaped
;
128 public Attribute
Clone ()
130 Attribute a
= new Attribute (ExplicitTarget
, expression
, null, loc
, nameEscaped
);
131 a
.PosArguments
= PosArguments
;
132 a
.NamedArguments
= NamedArguments
;
141 public static void Reset ()
143 usage_attr_cache
= new PtrHashtable ();
144 att_cache
= new PtrHashtable ();
148 // When the same attribute is attached to multiple fiels
149 // we use @target field as a list of targets. The attribute
150 // has to be resolved only once but emitted for each target.
152 public virtual void AttachTo (Attributable target
, IMemberContext context
)
154 if (this.targets
== null) {
155 this.targets
= new Attributable
[] { target }
;
156 this.context
= context
;
160 // Resize target array
161 Attributable
[] new_array
= new Attributable
[this.targets
.Length
+ 1];
162 targets
.CopyTo (new_array
, 0);
163 new_array
[targets
.Length
] = target
;
164 this.targets
= new_array
;
166 // No need to update context, different targets cannot have
167 // different contexts, it's enough to remove same attributes
168 // from secondary members.
170 target
.OptAttributes
= null;
173 static void Error_InvalidNamedArgument (ResolveContext rc
, NamedArgument name
)
175 rc
.Report
.Error (617, name
.Name
.Location
, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
176 "must be fields which are not readonly, static, const or read-write properties which are " +
177 "public and not static",
181 static void Error_InvalidNamedArgumentType (ResolveContext rc
, NamedArgument name
)
183 rc
.Report
.Error (655, name
.Name
.Location
,
184 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
188 public static void Error_AttributeArgumentNotValid (ResolveContext rc
, Location loc
)
190 rc
.Report
.Error (182, loc
,
191 "An attribute argument must be a constant expression, typeof " +
192 "expression or array creation expression");
195 public void Error_MissingGuidAttribute ()
197 Report
.Error (596, Location
, "The Guid attribute must be specified with the ComImport attribute");
200 public void Error_MisusedExtensionAttribute ()
202 Report
.Error (1112, Location
, "Do not use `{0}' directly. Use parameter modifier `this' 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 ()
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
.Value
== CharSetEnumMember
)
360 NamedArguments
.Add (new NamedArgument (new LocatedToken (loc
, CharSetEnumMember
),
361 Constant
.CreateConstant (typeof (CharSet
), RootContext
.ToplevelTypes
.DefaultCharSet
, Location
)));
365 get { return context.Compiler.Report; }
368 public CustomAttributeBuilder
Resolve ()
373 resolve_error
= true;
376 ResolveAttributeType ();
381 if (Type
.IsAbstract
) {
382 Report
.Error (653, Location
, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
386 ObsoleteAttribute obsolete_attr
= AttributeTester
.GetObsoleteAttribute (Type
);
387 if (obsolete_attr
!= null) {
388 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, TypeManager
.CSharpName (Type
), Location
, Report
);
391 if (PosArguments
== null && NamedArguments
== null) {
392 object o
= att_cache
[Type
];
394 resolve_error
= false;
395 return (CustomAttributeBuilder
)o
;
399 ResolveContext rc
= new ResolveContext (context
, ResolveContext
.Options
.ConstantScope
);
400 ConstructorInfo ctor
= ResolveConstructor (rc
);
402 if (Type
is TypeBuilder
&&
403 TypeManager
.LookupDeclSpace (Type
).MemberCache
== null)
404 // The attribute type has been DefineType'd, but not Defined. Let's not treat it as an error.
405 // It'll be resolved again when the attached-to entity is emitted.
406 resolve_error
= false;
410 ApplyModuleCharSet ();
412 CustomAttributeBuilder cb
;
414 // SRE does not allow private ctor but we want to report all source code errors
418 if (NamedArguments
== null) {
419 cb
= new CustomAttributeBuilder (ctor
, pos_values
);
421 if (pos_values
.Length
== 0)
422 att_cache
.Add (Type
, cb
);
424 resolve_error
= false;
428 if (!ResolveNamedArguments (rc
)) {
432 cb
= new CustomAttributeBuilder (ctor
, pos_values
,
433 prop_info_arr
, prop_values_arr
,
434 field_info_arr
, field_values_arr
);
436 resolve_error
= false;
440 Error_AttributeArgumentNotValid (rc
, Location
);
445 protected virtual ConstructorInfo
ResolveConstructor (ResolveContext ec
)
447 if (PosArguments
!= null) {
449 PosArguments
.Resolve (ec
, out dynamic);
451 throw new NotImplementedException ("dynamic");
454 MethodGroupExpr mg
= MemberLookupFinal (ec
, ec
.CurrentType
,
455 Type
, ConstructorInfo
.ConstructorName
, MemberTypes
.Constructor
,
456 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
,
457 Location
) as MethodGroupExpr
;
460 throw new NotImplementedException ();
462 mg
= mg
.OverloadResolve (ec
, ref PosArguments
, false, Location
);
466 ConstructorInfo constructor
= (ConstructorInfo
)mg
;
467 if (PosArguments
== null) {
468 pos_values
= EmptyObject
;
472 AParametersCollection pd
= TypeManager
.GetParameterData (constructor
);
474 if (!PosArguments
.GetAttributableValue (ec
, out pos_values
))
477 // Here we do the checks which should be done by corlib or by runtime.
478 // However Zoltan doesn't like it and every Mono compiler has to do it again.
479 PredefinedAttributes pa
= PredefinedAttributes
.Get
;
480 if (Type
== pa
.Guid
) {
482 new Guid ((string)pos_values
[0]);
484 catch (Exception e
) {
485 Error_AttributeEmitError (e
.Message
);
490 if (Type
== pa
.AttributeUsage
&& (int)pos_values
[0] == 0) {
491 ec
.Report
.Error (591, Location
, "Invalid value for argument to `System.AttributeUsage' attribute");
495 if (Type
== pa
.IndexerName
|| Type
== pa
.Conditional
) {
496 string v
= pos_values
[0] as string;
497 if (!Tokenizer
.IsValidIdentifier (v
) || Tokenizer
.IsKeyword (v
)) {
498 ec
.Report
.Error (633, PosArguments
[0].Expr
.Location
,
499 "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
504 if (Type
== pa
.MethodImpl
&& pos_values
.Length
== 1 &&
505 pd
.Types
[0] == TypeManager
.short_type
&&
506 !System
.Enum
.IsDefined (typeof (MethodImplOptions
), pos_values
[0].ToString ())) {
507 Error_AttributeEmitError ("Incorrect argument value.");
514 protected virtual bool ResolveNamedArguments (ResolveContext ec
)
516 int named_arg_count
= NamedArguments
.Count
;
518 ArrayList field_infos
= new ArrayList (named_arg_count
);
519 ArrayList prop_infos
= new ArrayList (named_arg_count
);
520 ArrayList field_values
= new ArrayList (named_arg_count
);
521 ArrayList prop_values
= new ArrayList (named_arg_count
);
523 ArrayList seen_names
= new ArrayList (named_arg_count
);
525 foreach (NamedArgument a
in NamedArguments
) {
526 string name
= a
.Name
.Value
;
527 if (seen_names
.Contains (name
)) {
528 ec
.Report
.Error (643, a
.Name
.Location
, "Duplicate named attribute `{0}' argument", name
);
532 seen_names
.Add (name
);
536 Expression member
= Expression
.MemberLookup (ec
.Compiler
,
537 ec
.CurrentType
, Type
, name
,
539 BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.Static
,
542 if (member
== null) {
543 member
= Expression
.MemberLookup (ec
.Compiler
, ec
.CurrentType
, Type
, name
,
544 MemberTypes
.All
, BindingFlags
.NonPublic
| BindingFlags
.Instance
| BindingFlags
.Static
,
547 if (member
!= null) {
548 ec
.Report
.SymbolRelatedToPreviousError (member
.Type
);
549 Expression
.ErrorIsInaccesible (Location
, member
.GetSignatureForError (), ec
.Report
);
555 Expression
.Error_TypeDoesNotContainDefinition (ec
, Location
, Type
, name
);
559 if (!(member
is PropertyExpr
|| member
is FieldExpr
)) {
560 Error_InvalidNamedArgument (ec
, a
);
564 ObsoleteAttribute obsolete_attr
;
566 if (member
is PropertyExpr
) {
567 PropertyInfo pi
= ((PropertyExpr
) member
).PropertyInfo
;
569 if (!pi
.CanWrite
|| !pi
.CanRead
|| pi
.GetGetMethod ().IsStatic
) {
570 ec
.Report
.SymbolRelatedToPreviousError (pi
);
571 Error_InvalidNamedArgument (ec
, a
);
575 if (!IsValidArgumentType (member
.Type
)) {
576 ec
.Report
.SymbolRelatedToPreviousError (pi
);
577 Error_InvalidNamedArgumentType (ec
, a
);
582 if (!a
.Expr
.GetAttributableValue (ec
, member
.Type
, out value))
585 PropertyBase pb
= TypeManager
.GetProperty (pi
);
587 obsolete_attr
= pb
.GetObsoleteAttribute ();
589 obsolete_attr
= AttributeTester
.GetMemberObsoleteAttribute (pi
);
591 prop_values
.Add (value);
595 FieldInfo fi
= ((FieldExpr
) member
).FieldInfo
;
597 if (fi
.IsInitOnly
|| fi
.IsStatic
) {
598 Error_InvalidNamedArgument (ec
, a
);
602 if (!IsValidArgumentType (member
.Type
)) {
603 ec
.Report
.SymbolRelatedToPreviousError (fi
);
604 Error_InvalidNamedArgumentType (ec
, a
);
609 if (!a
.Expr
.GetAttributableValue (ec
, member
.Type
, out value))
612 FieldBase fb
= TypeManager
.GetField (fi
);
614 obsolete_attr
= fb
.GetObsoleteAttribute ();
616 obsolete_attr
= AttributeTester
.GetMemberObsoleteAttribute (fi
);
618 field_values
.Add (value);
619 field_infos
.Add (fi
);
622 if (obsolete_attr
!= null && !context
.IsObsolete
)
623 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, member
.GetSignatureForError (), member
.Location
, Report
);
626 prop_info_arr
= new PropertyInfo
[prop_infos
.Count
];
627 field_info_arr
= new FieldInfo
[field_infos
.Count
];
628 field_values_arr
= new object [field_values
.Count
];
629 prop_values_arr
= new object [prop_values
.Count
];
631 field_infos
.CopyTo (field_info_arr
, 0);
632 field_values
.CopyTo (field_values_arr
, 0);
634 prop_values
.CopyTo (prop_values_arr
, 0);
635 prop_infos
.CopyTo (prop_info_arr
, 0);
641 /// Get a string containing a list of valid targets for the attribute 'attr'
643 public string GetValidTargets ()
645 StringBuilder sb
= new StringBuilder ();
646 AttributeTargets targets
= GetAttributeUsage (Type
).ValidOn
;
648 if ((targets
& AttributeTargets
.Assembly
) != 0)
649 sb
.Append ("assembly, ");
651 if ((targets
& AttributeTargets
.Module
) != 0)
652 sb
.Append ("module, ");
654 if ((targets
& AttributeTargets
.Class
) != 0)
655 sb
.Append ("class, ");
657 if ((targets
& AttributeTargets
.Struct
) != 0)
658 sb
.Append ("struct, ");
660 if ((targets
& AttributeTargets
.Enum
) != 0)
661 sb
.Append ("enum, ");
663 if ((targets
& AttributeTargets
.Constructor
) != 0)
664 sb
.Append ("constructor, ");
666 if ((targets
& AttributeTargets
.Method
) != 0)
667 sb
.Append ("method, ");
669 if ((targets
& AttributeTargets
.Property
) != 0)
670 sb
.Append ("property, indexer, ");
672 if ((targets
& AttributeTargets
.Field
) != 0)
673 sb
.Append ("field, ");
675 if ((targets
& AttributeTargets
.Event
) != 0)
676 sb
.Append ("event, ");
678 if ((targets
& AttributeTargets
.Interface
) != 0)
679 sb
.Append ("interface, ");
681 if ((targets
& AttributeTargets
.Parameter
) != 0)
682 sb
.Append ("parameter, ");
684 if ((targets
& AttributeTargets
.Delegate
) != 0)
685 sb
.Append ("delegate, ");
687 if ((targets
& AttributeTargets
.ReturnValue
) != 0)
688 sb
.Append ("return, ");
691 if ((targets
& AttributeTargets
.GenericParameter
) != 0)
692 sb
.Append ("type parameter, ");
694 return sb
.Remove (sb
.Length
- 2, 2).ToString ();
698 /// Returns AttributeUsage attribute based on types hierarchy
700 static AttributeUsageAttribute
GetAttributeUsage (Type type
)
702 AttributeUsageAttribute ua
= usage_attr_cache
[type
] as AttributeUsageAttribute
;
706 Class attr_class
= TypeManager
.LookupClass (type
);
707 PredefinedAttribute pa
= PredefinedAttributes
.Get
.AttributeUsage
;
709 if (attr_class
== null) {
711 return new AttributeUsageAttribute (0);
713 object[] usage_attr
= type
.GetCustomAttributes (pa
.Type
, true);
714 ua
= (AttributeUsageAttribute
)usage_attr
[0];
715 usage_attr_cache
.Add (type
, ua
);
720 if (attr_class
.OptAttributes
!= null)
721 a
= attr_class
.OptAttributes
.Search (pa
);
724 if (attr_class
.TypeBuilder
.BaseType
!= TypeManager
.attribute_type
)
725 ua
= GetAttributeUsage (attr_class
.TypeBuilder
.BaseType
);
727 ua
= DefaultUsageAttribute
;
729 ua
= a
.GetAttributeUsageAttribute ();
732 usage_attr_cache
.Add (type
, ua
);
736 AttributeUsageAttribute
GetAttributeUsageAttribute ()
738 if (pos_values
== null)
739 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
740 // But because a lot of attribute class code must be rewritten will be better to wait...
744 return DefaultUsageAttribute
;
746 AttributeUsageAttribute usage_attribute
= new AttributeUsageAttribute ((AttributeTargets
)pos_values
[0]);
748 object field
= GetPropertyValue ("AllowMultiple");
750 usage_attribute
.AllowMultiple
= (bool)field
;
752 field
= GetPropertyValue ("Inherited");
754 usage_attribute
.Inherited
= (bool)field
;
756 return usage_attribute
;
760 /// Returns custom name of indexer
762 public string GetIndexerAttributeValue ()
764 if (pos_values
== null)
765 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
766 // But because a lot of attribute class code must be rewritten will be better to wait...
772 return pos_values
[0] as string;
776 /// Returns condition of ConditionalAttribute
778 public string GetConditionalAttributeValue ()
780 if (pos_values
== null)
781 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
782 // But because a lot of attribute class code must be rewritten will be better to wait...
788 return (string)pos_values
[0];
792 /// Creates the instance of ObsoleteAttribute from this attribute instance
794 public ObsoleteAttribute
GetObsoleteAttribute ()
796 if (pos_values
== null)
797 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
798 // But because a lot of attribute class code must be rewritten will be better to wait...
804 if (pos_values
== null || pos_values
.Length
== 0)
805 return new ObsoleteAttribute ();
807 if (pos_values
.Length
== 1)
808 return new ObsoleteAttribute ((string)pos_values
[0]);
810 return new ObsoleteAttribute ((string)pos_values
[0], (bool)pos_values
[1]);
814 /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
815 /// before ApplyAttribute. We need to resolve the arguments.
816 /// This situation occurs when class deps is differs from Emit order.
818 public bool GetClsCompliantAttributeValue ()
820 if (pos_values
== null)
821 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
822 // But because a lot of attribute class code must be rewritten will be better to wait...
828 return (bool)pos_values
[0];
831 public Type
GetCoClassAttributeValue ()
833 if (pos_values
== null)
839 return (Type
)pos_values
[0];
842 public bool CheckTarget ()
844 string[] valid_targets
= Owner
.ValidAttributeTargets
;
845 if (ExplicitTarget
== null || ExplicitTarget
== valid_targets
[0]) {
846 Target
= Owner
.AttributeTargets
;
850 // TODO: we can skip the first item
851 if (((IList
) valid_targets
).Contains (ExplicitTarget
)) {
852 switch (ExplicitTarget
) {
853 case "return": Target
= AttributeTargets
.ReturnValue
; return true;
854 case "param": Target
= AttributeTargets
.Parameter
; return true;
855 case "field": Target
= AttributeTargets
.Field
; return true;
856 case "method": Target
= AttributeTargets
.Method
; return true;
857 case "property": Target
= AttributeTargets
.Property
; return true;
859 throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget
);
862 StringBuilder sb
= new StringBuilder ();
863 foreach (string s
in valid_targets
) {
867 sb
.Remove (sb
.Length
- 2, 2);
868 Report
.Error (657, Location
, "`{0}' is not a valid attribute location for this declaration. " +
869 "Valid attribute locations for this declaration are `{1}'", ExplicitTarget
, sb
.ToString ());
874 /// Tests permitted SecurityAction for assembly or other types
876 protected virtual bool IsSecurityActionValid (bool for_assembly
)
878 SecurityAction action
= GetSecurityActionValue ();
881 case SecurityAction
.Demand
:
882 case SecurityAction
.Assert
:
883 case SecurityAction
.Deny
:
884 case SecurityAction
.PermitOnly
:
885 case SecurityAction
.LinkDemand
:
886 case SecurityAction
.InheritanceDemand
:
891 case SecurityAction
.RequestMinimum
:
892 case SecurityAction
.RequestOptional
:
893 case SecurityAction
.RequestRefuse
:
899 Error_AttributeEmitError ("SecurityAction is out of range");
903 Error_AttributeEmitError (String
.Concat ("SecurityAction `", action
, "' is not valid for this declaration"));
907 System
.Security
.Permissions
.SecurityAction
GetSecurityActionValue ()
909 return (SecurityAction
)pos_values
[0];
913 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
915 /// <returns></returns>
916 public void ExtractSecurityPermissionSet (ListDictionary permissions
)
918 Type orig_assembly_type
= null;
920 if (TypeManager
.LookupDeclSpace (Type
) != null) {
921 if (!RootContext
.StdLib
) {
922 orig_assembly_type
= Type
.GetType (Type
.FullName
);
924 string orig_version_path
= Environment
.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
925 if (orig_version_path
== null) {
926 Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
930 if (orig_sec_assembly
== null) {
931 string file
= Path
.Combine (orig_version_path
, Driver
.OutputFile
);
932 orig_sec_assembly
= Assembly
.LoadFile (file
);
935 orig_assembly_type
= orig_sec_assembly
.GetType (Type
.FullName
, true);
936 if (orig_assembly_type
== null) {
937 Report
.Warning (-112, 1, Location
, "Self-referenced security attribute `{0}' " +
938 "was not found in previous version of assembly");
944 SecurityAttribute sa
;
945 // For all non-selfreferencing security attributes we can avoid all hacks
946 if (orig_assembly_type
== null) {
947 sa
= (SecurityAttribute
) Activator
.CreateInstance (Type
, pos_values
);
949 if (prop_info_arr
!= null) {
950 for (int i
= 0; i
< prop_info_arr
.Length
; ++i
) {
951 PropertyInfo pi
= prop_info_arr
[i
];
952 pi
.SetValue (sa
, prop_values_arr
[i
], null);
956 // HACK: All security attributes have same ctor syntax
957 sa
= (SecurityAttribute
) Activator
.CreateInstance (orig_assembly_type
, new object[] { GetSecurityActionValue () }
);
959 // All types are from newly created assembly but for invocation with old one we need to convert them
960 if (prop_info_arr
!= null) {
961 for (int i
= 0; i
< prop_info_arr
.Length
; ++i
) {
962 PropertyInfo emited_pi
= prop_info_arr
[i
];
963 // FIXME: We are missing return type filter
964 // TODO: pi can be null
965 PropertyInfo pi
= orig_assembly_type
.GetProperty (emited_pi
.Name
);
967 object old_instance
= TypeManager
.IsEnumType (pi
.PropertyType
) ?
968 System
.Enum
.ToObject (pi
.PropertyType
, prop_values_arr
[i
]) :
971 pi
.SetValue (sa
, old_instance
, null);
977 perm
= sa
.CreatePermission ();
978 SecurityAction action
= GetSecurityActionValue ();
980 // IS is correct because for corlib we are using an instance from old corlib
981 if (!(perm
is System
.Security
.CodeAccessPermission
)) {
983 case SecurityAction
.Demand
:
984 action
= (SecurityAction
)13;
986 case SecurityAction
.LinkDemand
:
987 action
= (SecurityAction
)14;
989 case SecurityAction
.InheritanceDemand
:
990 action
= (SecurityAction
)15;
995 PermissionSet ps
= (PermissionSet
)permissions
[action
];
997 if (sa
is PermissionSetAttribute
)
998 ps
= new PermissionSet (sa
.Unrestricted
? PermissionState
.Unrestricted
: PermissionState
.None
);
1000 ps
= new PermissionSet (PermissionState
.None
);
1002 permissions
.Add (action
, ps
);
1003 } else if (!ps
.IsUnrestricted () && (sa
is PermissionSetAttribute
) && sa
.Unrestricted
) {
1004 ps
= ps
.Union (new PermissionSet (PermissionState
.Unrestricted
));
1005 permissions
[action
] = ps
;
1007 ps
.AddPermission (perm
);
1010 public object GetPropertyValue (string name
)
1012 if (prop_info_arr
== null)
1015 for (int i
= 0; i
< prop_info_arr
.Length
; ++i
) {
1016 if (prop_info_arr
[i
].Name
== name
)
1017 return prop_values_arr
[i
];
1024 // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
1025 // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
1026 // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
1029 public UnmanagedMarshal
GetMarshal (Attributable attr
)
1031 UnmanagedType UnmanagedType
;
1032 if (!RootContext
.StdLib
|| pos_values
[0].GetType () != typeof (UnmanagedType
))
1033 UnmanagedType
= (UnmanagedType
) System
.Enum
.ToObject (typeof (UnmanagedType
), pos_values
[0]);
1035 UnmanagedType
= (UnmanagedType
) pos_values
[0];
1037 object value = GetFieldValue ("SizeParamIndex");
1038 if (value != null && UnmanagedType
!= UnmanagedType
.LPArray
) {
1039 Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
1043 object o
= GetFieldValue ("ArraySubType");
1044 UnmanagedType array_sub_type
= o
== null ? (UnmanagedType
) 0x50 /* NATIVE_MAX */ : (UnmanagedType
) o
;
1046 switch (UnmanagedType
) {
1047 case UnmanagedType
.CustomMarshaler
: {
1048 MethodInfo define_custom
= typeof (UnmanagedMarshal
).GetMethod ("DefineCustom",
1049 BindingFlags
.Static
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
1050 if (define_custom
== null) {
1051 Report
.RuntimeMissingSupport (Location
, "set marshal info");
1055 object [] args
= new object [4];
1056 args
[0] = GetFieldValue ("MarshalTypeRef");
1057 args
[1] = GetFieldValue ("MarshalCookie");
1058 args
[2] = GetFieldValue ("MarshalType");
1059 args
[3] = Guid
.Empty
;
1060 return (UnmanagedMarshal
) define_custom
.Invoke (null, args
);
1062 case UnmanagedType
.LPArray
: {
1063 object size_const
= GetFieldValue ("SizeConst");
1064 object size_param_index
= GetFieldValue ("SizeParamIndex");
1066 if ((size_const
!= null) || (size_param_index
!= null)) {
1067 MethodInfo define_array
= typeof (UnmanagedMarshal
).GetMethod ("DefineLPArrayInternal",
1068 BindingFlags
.Static
| BindingFlags
.Public
| BindingFlags
.NonPublic
);
1069 if (define_array
== null) {
1070 Report
.RuntimeMissingSupport (Location
, "set marshal info");
1074 object [] args
= new object [3];
1075 args
[0] = array_sub_type
;
1076 args
[1] = size_const
== null ? -1 : size_const
;
1077 args
[2] = size_param_index
== null ? -1 : size_param_index
;
1078 return (UnmanagedMarshal
) define_array
.Invoke (null, args
);
1081 return UnmanagedMarshal
.DefineLPArray (array_sub_type
);
1083 case UnmanagedType
.SafeArray
:
1084 return UnmanagedMarshal
.DefineSafeArray (array_sub_type
);
1086 case UnmanagedType
.ByValArray
:
1087 FieldBase fm
= attr
as FieldBase
;
1089 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
1092 return UnmanagedMarshal
.DefineByValArray ((int) GetFieldValue ("SizeConst"));
1094 case UnmanagedType
.ByValTStr
:
1095 return UnmanagedMarshal
.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
1098 return UnmanagedMarshal
.DefineUnmanagedMarshal (UnmanagedType
);
1102 object GetFieldValue (string name
)
1105 if (field_info_arr
== null)
1108 foreach (FieldInfo fi
in field_info_arr
) {
1109 if (fi
.Name
== name
)
1110 return GetValue (field_values_arr
[i
]);
1116 static object GetValue (object value)
1118 if (value is EnumConstant
)
1119 return ((EnumConstant
) value).GetValue ();
1126 public CharSet
GetCharSetValue ()
1128 return (CharSet
)System
.Enum
.Parse (typeof (CharSet
), pos_values
[0].ToString ());
1131 public bool HasField (string fieldName
)
1133 if (field_info_arr
== null)
1136 foreach (FieldInfo fi
in field_info_arr
) {
1137 if (fi
.Name
== fieldName
)
1144 public bool IsInternalMethodImplAttribute
{
1146 if (Type
!= PredefinedAttributes
.Get
.MethodImpl
)
1149 MethodImplOptions options
;
1150 if (pos_values
[0].GetType () != typeof (MethodImplOptions
))
1151 options
= (MethodImplOptions
)System
.Enum
.ToObject (typeof (MethodImplOptions
), pos_values
[0]);
1153 options
= (MethodImplOptions
)pos_values
[0];
1155 return (options
& MethodImplOptions
.InternalCall
) != 0;
1159 public LayoutKind
GetLayoutKindValue ()
1161 if (!RootContext
.StdLib
|| pos_values
[0].GetType () != typeof (LayoutKind
))
1162 return (LayoutKind
)System
.Enum
.ToObject (typeof (LayoutKind
), pos_values
[0]);
1164 return (LayoutKind
)pos_values
[0];
1167 public object GetParameterDefaultValue ()
1169 return pos_values
[0];
1172 public override bool Equals (object obj
)
1174 Attribute a
= obj
as Attribute
;
1178 return Type
== a
.Type
&& Target
== a
.Target
;
1181 public override int GetHashCode ()
1183 return base.GetHashCode ();
1187 /// Emit attribute for Attributable symbol
1189 public void Emit (ListDictionary allEmitted
)
1191 CustomAttributeBuilder cb
= Resolve ();
1195 AttributeUsageAttribute usage_attr
= GetAttributeUsage (Type
);
1196 if ((usage_attr
.ValidOn
& Target
) == 0) {
1197 Report
.Error (592, Location
, "The attribute `{0}' is not valid on this declaration type. " +
1198 "It is valid on `{1}' declarations only",
1199 GetSignatureForError (), GetValidTargets ());
1204 foreach (Attributable target
in targets
)
1205 target
.ApplyAttributeBuilder (this, cb
, PredefinedAttributes
.Get
);
1206 } catch (Exception e
) {
1207 Error_AttributeEmitError (e
.Message
);
1211 if (!usage_attr
.AllowMultiple
&& allEmitted
!= null) {
1212 if (allEmitted
.Contains (this)) {
1213 ArrayList a
= allEmitted
[this] as ArrayList
;
1215 a
= new ArrayList (2);
1216 allEmitted
[this] = a
;
1220 allEmitted
.Add (this, null);
1224 if (!RootContext
.VerifyClsCompliance
)
1227 // Here we are testing attribute arguments for array usage (error 3016)
1228 if (Owner
.IsClsComplianceRequired ()) {
1229 if (PosArguments
!= null)
1230 PosArguments
.CheckArrayAsAttribute (context
.Compiler
);
1232 if (NamedArguments
== null)
1235 NamedArguments
.CheckArrayAsAttribute (context
.Compiler
);
1239 private Expression
GetValue ()
1241 if (PosArguments
== null || PosArguments
.Count
< 1)
1244 return PosArguments
[0].Expr
;
1247 public string GetString ()
1249 Expression e
= GetValue ();
1250 if (e
is StringConstant
)
1251 return ((StringConstant
)e
).Value
;
1255 public bool GetBoolean ()
1257 Expression e
= GetValue ();
1258 if (e
is BoolConstant
)
1259 return ((BoolConstant
)e
).Value
;
1263 public Type
GetArgumentType ()
1265 TypeOf e
= GetValue () as TypeOf
;
1268 return e
.TypeArgument
;
1271 public override Expression
CreateExpressionTree (ResolveContext ec
)
1273 throw new NotSupportedException ("ET");
1276 public override Expression
DoResolve (ResolveContext ec
)
1278 throw new NotImplementedException ();
1281 public override void Emit (EmitContext ec
)
1283 throw new NotImplementedException ();
1289 /// For global attributes (assembly, module) we need special handling.
1290 /// Attributes can be located in the several files
1292 public class GlobalAttribute
: Attribute
1294 public readonly NamespaceEntry ns
;
1296 public GlobalAttribute (NamespaceEntry ns
, string target
, ATypeNameExpression expression
,
1297 Arguments
[] args
, Location loc
, bool nameEscaped
):
1298 base (target
, expression
, args
, loc
, nameEscaped
)
1303 public override void AttachTo (Attributable target
, IMemberContext context
)
1305 if (ExplicitTarget
== "assembly") {
1306 base.AttachTo (CodeGen
.Assembly
, context
);
1310 if (ExplicitTarget
== "module") {
1311 base.AttachTo (RootContext
.ToplevelTypes
, context
);
1315 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget
);
1320 // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
1321 // each time a new file is parsed. However, we need to use the NamespaceEntry
1322 // in effect where the attribute was used. Since code elsewhere cannot assume
1323 // that the NamespaceEntry is right, just overwrite it.
1325 // Precondition: RootContext.ToplevelTypes == null
1327 if (RootContext
.ToplevelTypes
.NamespaceEntry
!= null)
1328 throw new InternalErrorException (Location
+ " non-null NamespaceEntry");
1330 RootContext
.ToplevelTypes
.NamespaceEntry
= ns
;
1333 protected override bool IsSecurityActionValid (bool for_assembly
)
1335 return base.IsSecurityActionValid (true);
1340 RootContext
.ToplevelTypes
.NamespaceEntry
= null;
1343 protected override TypeExpr
ResolveAsTypeTerminal (Expression expr
, IMemberContext ec
)
1347 return base.ResolveAsTypeTerminal (expr
, ec
);
1354 protected override ConstructorInfo
ResolveConstructor (ResolveContext ec
)
1358 return base.ResolveConstructor (ec
);
1365 protected override bool ResolveNamedArguments (ResolveContext ec
)
1369 return base.ResolveNamedArguments (ec
);
1377 public class Attributes
{
1378 public readonly ArrayList Attrs
;
1380 public Attributes (Attribute a
)
1382 Attrs
= new ArrayList ();
1386 public Attributes (ArrayList attrs
)
1391 public void AddAttributes (ArrayList attrs
)
1393 Attrs
.AddRange (attrs
);
1396 public void AttachTo (Attributable attributable
, IMemberContext context
)
1398 foreach (Attribute a
in Attrs
)
1399 a
.AttachTo (attributable
, context
);
1402 public Attributes
Clone ()
1404 ArrayList al
= new ArrayList (Attrs
.Count
);
1405 foreach (Attribute a
in Attrs
)
1406 al
.Add (a
.Clone ());
1408 return new Attributes (al
);
1412 /// Checks whether attribute target is valid for the current element
1414 public bool CheckTargets ()
1416 foreach (Attribute a
in Attrs
) {
1417 if (!a
.CheckTarget ())
1423 public Attribute
Search (PredefinedAttribute t
)
1425 foreach (Attribute a
in Attrs
) {
1426 if (a
.ResolveType () == t
)
1433 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1435 public Attribute
[] SearchMulti (PredefinedAttribute t
)
1437 ArrayList ar
= null;
1439 foreach (Attribute a
in Attrs
) {
1440 if (a
.ResolveType () == t
) {
1442 ar
= new ArrayList ();
1447 return ar
== null ? null : ar
.ToArray (typeof (Attribute
)) as Attribute
[];
1454 ListDictionary ld
= Attrs
.Count
> 1 ? new ListDictionary () : null;
1456 foreach (Attribute a
in Attrs
)
1459 if (ld
== null || ld
.Count
== 0)
1462 foreach (DictionaryEntry d
in ld
) {
1463 if (d
.Value
== null)
1466 Report report
= RootContext
.ToplevelTypes
.Compiler
.Report
;
1467 foreach (Attribute collision
in (ArrayList
)d
.Value
)
1468 report
.SymbolRelatedToPreviousError (collision
.Location
, "");
1470 Attribute a
= (Attribute
)d
.Key
;
1471 report
.Error (579, a
.Location
, "The attribute `{0}' cannot be applied multiple times",
1472 a
.GetSignatureForError ());
1476 public bool Contains (PredefinedAttribute t
)
1478 return Search (t
) != null;
1483 /// Helper class for attribute verification routine.
1485 sealed class AttributeTester
1487 static PtrHashtable analyzed_types
;
1488 static PtrHashtable analyzed_types_obsolete
;
1489 static PtrHashtable analyzed_member_obsolete
;
1490 static PtrHashtable analyzed_method_excluded
;
1491 static PtrHashtable fixed_buffer_cache
;
1493 static object TRUE
= new object ();
1494 static object FALSE
= new object ();
1496 static AttributeTester ()
1501 private AttributeTester ()
1505 public static void Reset ()
1507 analyzed_types
= new PtrHashtable ();
1508 analyzed_types_obsolete
= new PtrHashtable ();
1509 analyzed_member_obsolete
= new PtrHashtable ();
1510 analyzed_method_excluded
= new PtrHashtable ();
1511 fixed_buffer_cache
= new PtrHashtable ();
1514 public enum Result
{
1521 /// Returns true if parameters of two compared methods are CLS-Compliant.
1522 /// It tests differing only in ref or out, or in array rank.
1524 public static Result
AreOverloadedMethodParamsClsCompliant (AParametersCollection pa
, AParametersCollection pb
)
1526 Type
[] types_a
= pa
.Types
;
1527 Type
[] types_b
= pb
.Types
;
1528 if (types_a
== null || types_b
== null)
1531 if (types_a
.Length
!= types_b
.Length
)
1534 Result result
= Result
.Ok
;
1535 for (int i
= 0; i
< types_b
.Length
; ++i
) {
1536 Type aType
= types_a
[i
];
1537 Type bType
= types_b
[i
];
1539 if (aType
.IsArray
&& bType
.IsArray
) {
1540 Type a_el_type
= TypeManager
.GetElementType (aType
);
1541 Type b_el_type
= TypeManager
.GetElementType (bType
);
1542 if (aType
.GetArrayRank () != bType
.GetArrayRank () && a_el_type
== b_el_type
) {
1543 result
= Result
.RefOutArrayError
;
1547 if (a_el_type
.IsArray
|| b_el_type
.IsArray
) {
1548 result
= Result
.ArrayArrayError
;
1556 const Parameter
.Modifier out_ref_mod
= (Parameter
.Modifier
.OUTMASK
| Parameter
.Modifier
.REFMASK
);
1557 if ((pa
.FixedParameters
[i
].ModFlags
& out_ref_mod
) != (pb
.FixedParameters
[i
].ModFlags
& out_ref_mod
))
1558 result
= Result
.RefOutArrayError
;
1564 /// This method tests the CLS compliance of external types. It doesn't test type visibility.
1566 public static bool IsClsCompliant (Type type
)
1571 object type_compliance
= analyzed_types
[type
];
1572 if (type_compliance
!= null)
1573 return type_compliance
== TRUE
;
1575 if (type
.IsPointer
) {
1576 analyzed_types
.Add (type
, FALSE
);
1582 result
= IsClsCompliant (TypeManager
.GetElementType (type
));
1583 } else if (TypeManager
.IsNullableType (type
)) {
1584 result
= IsClsCompliant (TypeManager
.TypeToCoreType (TypeManager
.GetTypeArguments (type
) [0]));
1586 result
= AnalyzeTypeCompliance (type
);
1588 analyzed_types
.Add (type
, result
? TRUE
: FALSE
);
1593 /// Returns IFixedBuffer implementation if field is fixed buffer else null.
1595 public static IFixedBuffer
GetFixedBuffer (FieldInfo fi
)
1597 // Fixed buffer helper type is generated as value type
1598 if (TypeManager
.IsReferenceType (fi
.FieldType
))
1601 FieldBase fb
= TypeManager
.GetField (fi
);
1603 return fb
as IFixedBuffer
;
1606 if (TypeManager
.GetConstant (fi
) != null)
1609 object o
= fixed_buffer_cache
[fi
];
1611 PredefinedAttribute pa
= PredefinedAttributes
.Get
.FixedBuffer
;
1615 if (!fi
.IsDefined (pa
.Type
, false)) {
1616 fixed_buffer_cache
.Add (fi
, FALSE
);
1620 IFixedBuffer iff
= new FixedFieldExternal (fi
);
1621 fixed_buffer_cache
.Add (fi
, iff
);
1628 return (IFixedBuffer
)o
;
1631 public static void VerifyModulesClsCompliance (CompilerContext ctx
)
1633 Module
[] modules
= GlobalRootNamespace
.Instance
.Modules
;
1634 if (modules
== null)
1637 // The first module is generated assembly
1638 for (int i
= 1; i
< modules
.Length
; ++i
) {
1639 Module module
= modules
[i
];
1640 if (!GetClsCompliantAttributeValue (module
, null)) {
1641 ctx
.Report
.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
1642 "to match the assembly", module
.Name
);
1648 public static Type
GetImportedIgnoreCaseClsType (string name
)
1650 foreach (Assembly a
in GlobalRootNamespace
.Instance
.Assemblies
) {
1651 Type t
= a
.GetType (name
, false, true);
1655 if (IsClsCompliant (t
))
1661 static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider
, Assembly a
)
1663 PredefinedAttribute pa
= PredefinedAttributes
.Get
.CLSCompliant
;
1667 object[] cls_attr
= attribute_provider
.GetCustomAttributes (pa
.Type
, false);
1668 if (cls_attr
.Length
== 0) {
1672 return GetClsCompliantAttributeValue (a
, null);
1675 return ((CLSCompliantAttribute
)cls_attr
[0]).IsCompliant
;
1678 static bool AnalyzeTypeCompliance (Type type
)
1680 type
= TypeManager
.DropGenericTypeArguments (type
);
1681 DeclSpace ds
= TypeManager
.LookupDeclSpace (type
);
1683 return ds
.IsClsComplianceRequired ();
1686 if (TypeManager
.IsGenericParameter (type
))
1689 return GetClsCompliantAttributeValue (type
, type
.Assembly
);
1693 /// Returns instance of ObsoleteAttribute when type is obsolete
1695 public static ObsoleteAttribute
GetObsoleteAttribute (Type type
)
1697 object type_obsolete
= analyzed_types_obsolete
[type
];
1698 if (type_obsolete
== FALSE
)
1701 if (type_obsolete
!= null)
1702 return (ObsoleteAttribute
)type_obsolete
;
1704 ObsoleteAttribute result
= null;
1705 if (TypeManager
.HasElementType (type
)) {
1706 result
= GetObsoleteAttribute (TypeManager
.GetElementType (type
));
1707 } else if (TypeManager
.IsGenericParameter (type
))
1708 result
= null; // TODO: throw new NotSupportedException ()
1709 else if (TypeManager
.IsGenericType (type
) && !TypeManager
.IsGenericTypeDefinition (type
)) {
1710 return GetObsoleteAttribute (TypeManager
.DropGenericTypeArguments (type
));
1712 DeclSpace type_ds
= TypeManager
.LookupDeclSpace (type
);
1714 // Type is external, we can get attribute directly
1715 if (type_ds
== null) {
1716 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Obsolete
;
1718 object[] attribute
= type
.GetCustomAttributes (pa
.Type
, false);
1719 if (attribute
.Length
== 1)
1720 result
= (ObsoleteAttribute
) attribute
[0];
1723 result
= type_ds
.GetObsoleteAttribute ();
1727 // Cannot use .Add because of corlib bootstrap
1728 analyzed_types_obsolete
[type
] = result
== null ? FALSE
: result
;
1733 /// Returns instance of ObsoleteAttribute when method is obsolete
1735 public static ObsoleteAttribute
GetMethodObsoleteAttribute (MethodBase mb
)
1737 IMethodData mc
= TypeManager
.GetMethod (mb
);
1739 return mc
.GetObsoleteAttribute ();
1741 // compiler generated methods are not registered by AddMethod
1742 if (mb
.DeclaringType
is TypeBuilder
)
1745 MemberInfo mi
= TypeManager
.GetPropertyFromAccessor (mb
);
1747 return GetMemberObsoleteAttribute (mi
);
1749 mi
= TypeManager
.GetEventFromAccessor (mb
);
1751 return GetMemberObsoleteAttribute (mi
);
1753 return GetMemberObsoleteAttribute (mb
);
1757 /// Returns instance of ObsoleteAttribute when member is obsolete
1759 public static ObsoleteAttribute
GetMemberObsoleteAttribute (MemberInfo mi
)
1761 object type_obsolete
= analyzed_member_obsolete
[mi
];
1762 if (type_obsolete
== FALSE
)
1765 if (type_obsolete
!= null)
1766 return (ObsoleteAttribute
)type_obsolete
;
1768 if ((mi
.DeclaringType
is TypeBuilder
) || TypeManager
.IsGenericType (mi
.DeclaringType
))
1771 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Obsolete
;
1775 ObsoleteAttribute oa
= System
.Attribute
.GetCustomAttribute (mi
, pa
.Type
, false)
1776 as ObsoleteAttribute
;
1777 analyzed_member_obsolete
.Add (mi
, oa
== null ? FALSE
: oa
);
1782 /// Common method for Obsolete error/warning reporting.
1784 public static void Report_ObsoleteMessage (ObsoleteAttribute oa
, string member
, Location loc
, Report Report
)
1787 Report
.Error (619, loc
, "`{0}' is obsolete: `{1}'", member
, oa
.Message
);
1791 if (oa
.Message
== null || oa
.Message
.Length
== 0) {
1792 Report
.Warning (612, 1, loc
, "`{0}' is obsolete", member
);
1795 Report
.Warning (618, 2, loc
, "`{0}' is obsolete: `{1}'", member
, oa
.Message
);
1798 public static bool IsConditionalMethodExcluded (MethodBase mb
, Location loc
)
1800 object excluded
= analyzed_method_excluded
[mb
];
1801 if (excluded
!= null)
1802 return excluded
== TRUE
? true : false;
1804 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Conditional
;
1808 ConditionalAttribute
[] attrs
= mb
.GetCustomAttributes (pa
.Type
, true)
1809 as ConditionalAttribute
[];
1810 if (attrs
.Length
== 0) {
1811 analyzed_method_excluded
.Add (mb
, FALSE
);
1815 foreach (ConditionalAttribute a
in attrs
) {
1816 if (loc
.CompilationUnit
.IsConditionalDefined (a
.ConditionString
)) {
1817 analyzed_method_excluded
.Add (mb
, FALSE
);
1822 analyzed_method_excluded
.Add (mb
, TRUE
);
1827 /// Analyzes class whether it has attribute which has ConditionalAttribute
1828 /// and its condition is not defined.
1830 public static bool IsAttributeExcluded (Type type
, Location loc
)
1835 Class class_decl
= TypeManager
.LookupDeclSpace (type
) as Class
;
1837 // TODO: add caching
1838 // TODO: merge all Type bases attribute caching to one cache to save memory
1839 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Conditional
;
1840 if (class_decl
== null && pa
.IsDefined
) {
1841 object[] attributes
= type
.GetCustomAttributes (pa
.Type
, false);
1842 foreach (ConditionalAttribute ca
in attributes
) {
1843 if (loc
.CompilationUnit
.IsConditionalDefined (ca
.ConditionString
))
1846 return attributes
.Length
> 0;
1849 return class_decl
.IsExcluded ();
1852 public static Type
GetCoClassAttribute (Type type
)
1854 TypeContainer tc
= TypeManager
.LookupInterface (type
);
1855 PredefinedAttribute pa
= PredefinedAttributes
.Get
.CoClass
;
1860 object[] o
= type
.GetCustomAttributes (pa
.Type
, false);
1863 return ((System
.Runtime
.InteropServices
.CoClassAttribute
)o
[0]).CoClass
;
1866 if (tc
.OptAttributes
== null)
1869 Attribute a
= tc
.OptAttributes
.Search (pa
);
1873 return a
.GetCoClassAttributeValue ();
1877 public class PredefinedAttributes
1880 public readonly PredefinedAttribute ParamArray
;
1881 public readonly PredefinedAttribute Out
;
1884 public readonly PredefinedAttribute Obsolete
;
1885 public readonly PredefinedAttribute DllImport
;
1886 public readonly PredefinedAttribute MethodImpl
;
1887 public readonly PredefinedAttribute MarshalAs
;
1888 public readonly PredefinedAttribute In
;
1889 public readonly PredefinedAttribute IndexerName
;
1890 public readonly PredefinedAttribute Conditional
;
1891 public readonly PredefinedAttribute CLSCompliant
;
1892 public readonly PredefinedAttribute Security
;
1893 public readonly PredefinedAttribute Required
;
1894 public readonly PredefinedAttribute Guid
;
1895 public readonly PredefinedAttribute AssemblyCulture
;
1896 public readonly PredefinedAttribute AssemblyVersion
;
1897 public readonly PredefinedAttribute ComImport
;
1898 public readonly PredefinedAttribute CoClass
;
1899 public readonly PredefinedAttribute AttributeUsage
;
1900 public readonly PredefinedAttribute DefaultParameterValue
;
1901 public readonly PredefinedAttribute OptionalParameter
;
1904 public readonly PredefinedAttribute DefaultCharset
;
1905 public readonly PredefinedAttribute TypeForwarder
;
1906 public readonly PredefinedAttribute FixedBuffer
;
1907 public readonly PredefinedAttribute CompilerGenerated
;
1908 public readonly PredefinedAttribute InternalsVisibleTo
;
1909 public readonly PredefinedAttribute RuntimeCompatibility
;
1910 public readonly PredefinedAttribute DebuggerHidden
;
1911 public readonly PredefinedAttribute UnsafeValueType
;
1914 public readonly PredefinedAttribute Extension
;
1917 public readonly PredefinedAttribute Dynamic
;
1920 // Optional types which are used as types and for member lookup
1922 public readonly PredefinedAttribute DefaultMember
;
1923 public readonly PredefinedAttribute DecimalConstant
;
1924 public readonly PredefinedAttribute StructLayout
;
1925 public readonly PredefinedAttribute FieldOffset
;
1927 public static PredefinedAttributes Get
= new PredefinedAttributes ();
1929 private PredefinedAttributes ()
1931 ParamArray
= new PredefinedAttribute ("System", "ParamArrayAttribute");
1932 Out
= new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
1934 Obsolete
= new PredefinedAttribute ("System", "ObsoleteAttribute");
1935 DllImport
= new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
1936 MethodImpl
= new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
1937 MarshalAs
= new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
1938 In
= new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
1939 IndexerName
= new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
1940 Conditional
= new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
1941 CLSCompliant
= new PredefinedAttribute ("System", "CLSCompliantAttribute");
1942 Security
= new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
1943 Required
= new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1944 Guid
= new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
1945 AssemblyCulture
= new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
1946 AssemblyVersion
= new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
1947 ComImport
= new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
1948 CoClass
= new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
1949 AttributeUsage
= new PredefinedAttribute ("System", "AttributeUsageAttribute");
1950 DefaultParameterValue
= new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1951 OptionalParameter
= new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
1953 DefaultCharset
= new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
1954 TypeForwarder
= new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1955 FixedBuffer
= new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
1956 CompilerGenerated
= new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1957 InternalsVisibleTo
= new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1958 RuntimeCompatibility
= new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1959 DebuggerHidden
= new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
1960 UnsafeValueType
= new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1962 Extension
= new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
1964 Dynamic
= new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
1966 DefaultMember
= new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
1967 DecimalConstant
= new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
1968 StructLayout
= new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
1969 FieldOffset
= new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
1972 public void Initialize ()
1974 foreach (FieldInfo fi
in GetType ().GetFields (BindingFlags
.Public
| BindingFlags
.Instance
| BindingFlags
.DeclaredOnly
)) {
1975 ((PredefinedAttribute
) fi
.GetValue (this)).Resolve (true);
1979 public static void Reset ()
1981 Get
= new PredefinedAttributes ();
1985 public class PredefinedAttribute
1988 CustomAttributeBuilder cab
;
1989 ConstructorInfo ctor
;
1990 readonly string ns
, name
;
1992 public PredefinedAttribute (string ns
, string name
)
1998 public static bool operator == (Type type
, PredefinedAttribute pa
)
2000 return type
== pa
.type
;
2003 public static bool operator != (Type type
, PredefinedAttribute pa
)
2005 return type
!= pa
.type
;
2008 public ConstructorInfo Constructor
{
2009 get { return ctor; }
2012 public override int GetHashCode ()
2014 return base.GetHashCode ();
2017 public override bool Equals (object obj
)
2019 throw new NotSupportedException ();
2022 public void EmitAttribute (ConstructorBuilder builder
)
2024 if (ResolveBuilder ())
2025 builder
.SetCustomAttribute (cab
);
2028 public void EmitAttribute (MethodBuilder builder
)
2030 if (ResolveBuilder ())
2031 builder
.SetCustomAttribute (cab
);
2034 public void EmitAttribute (PropertyBuilder builder
)
2036 if (ResolveBuilder ())
2037 builder
.SetCustomAttribute (cab
);
2040 public void EmitAttribute (FieldBuilder builder
)
2042 if (ResolveBuilder ())
2043 builder
.SetCustomAttribute (cab
);
2046 public void EmitAttribute (TypeBuilder builder
)
2048 if (ResolveBuilder ())
2049 builder
.SetCustomAttribute (cab
);
2052 public void EmitAttribute (AssemblyBuilder builder
)
2054 if (ResolveBuilder ())
2055 builder
.SetCustomAttribute (cab
);
2058 public void EmitAttribute (ParameterBuilder builder
, Location loc
)
2060 if (ResolveBuilder ())
2061 builder
.SetCustomAttribute (cab
);
2064 public bool IsDefined
{
2065 get { return type != null && type != typeof (PredefinedAttribute); }
2068 public bool Resolve (bool canFail
)
2077 type
= TypeManager
.CoreLookupType (RootContext
.ToplevelTypes
.Compiler
, ns
, name
, Kind
.Class
, !canFail
);
2079 type
= typeof (PredefinedAttribute
);
2086 bool ResolveBuilder ()
2092 // Handle all parameter-less attributes as optional
2094 if (!Resolve (true))
2097 ConstructorInfo ci
= TypeManager
.GetPredefinedConstructor (type
, Location
.Null
, Type
.EmptyTypes
);
2101 cab
= new CustomAttributeBuilder (ci
, new object[0]);
2105 public bool ResolveConstructor (Location loc
, params Type
[] argType
)
2108 throw new InternalErrorException ("Predefined ctor redefined");
2110 if (!Resolve (false))
2113 ctor
= TypeManager
.GetPredefinedConstructor (type
, loc
, argType
);
2114 return ctor
!= null;
2118 get { return type; }