2 // attribute.cs: Attribute Handler
4 // Author: Ravi Pratap (ravi@ximian.com)
5 // Marek Safar (marek.safar@seznam.cz)
7 // Dual licensed under the terms of the MIT X11 or GNU GPL
9 // Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 // Copyright 2003-2008 Novell, Inc.
14 using System
.Diagnostics
;
15 using System
.Collections
.Generic
;
16 using System
.Reflection
;
17 using System
.Reflection
.Emit
;
18 using System
.Runtime
.InteropServices
;
19 using System
.Runtime
.CompilerServices
;
20 using System
.Security
;
21 using System
.Security
.Permissions
;
25 namespace Mono
.CSharp
{
28 /// Base class for objects that can have Attributes applied to them.
30 public abstract class Attributable
{
32 // Holds all attributes attached to this element
34 protected Attributes attributes
;
36 public void AddAttributes (Attributes attrs
, IMemberContext context
)
41 if (attributes
== null)
44 throw new NotImplementedException ();
46 attributes
.AttachTo (this, context
);
49 public Attributes OptAttributes
{
59 /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
61 public abstract void ApplyAttributeBuilder (Attribute a
, MethodSpec ctor
, byte[] cdata
, PredefinedAttributes pa
);
64 /// Returns one AttributeTarget for this element.
66 public abstract AttributeTargets AttributeTargets { get; }
68 public abstract bool IsClsComplianceRequired ();
71 /// Gets list of valid attribute targets for explicit target declaration.
72 /// The first array item is default target. Don't break this rule.
74 public abstract string[] ValidAttributeTargets { get; }
77 public class Attribute
: Expression
79 public readonly string ExplicitTarget
;
80 public AttributeTargets Target
;
81 readonly ATypeNameExpression expression
;
83 Arguments PosArguments
;
84 Arguments NamedArguments
;
88 readonly bool nameEscaped
;
91 // An attribute can be attached to multiple targets (e.g. multiple fields)
93 protected Attributable
[] targets
;
96 // A member context for the attribute, it's much easier to hold it here
97 // than trying to pull it during resolve
99 IMemberContext context
;
101 public static readonly AttributeUsageAttribute DefaultUsageAttribute
= new AttributeUsageAttribute (AttributeTargets
.All
);
102 static Assembly orig_sec_assembly
;
103 public static readonly object[] EmptyObject
= new object [0];
105 IList
<KeyValuePair
<MemberExpr
, NamedArgument
>> named_values
;
107 // Cache for parameter-less attributes
108 static Dictionary
<TypeSpec
, MethodSpec
> att_cache
;
110 public Attribute (string target
, ATypeNameExpression expr
, Arguments
[] args
, Location loc
, bool nameEscaped
)
112 this.expression
= expr
;
114 PosArguments
= args
[0];
115 NamedArguments
= args
[1];
118 ExplicitTarget
= target
;
119 this.nameEscaped
= nameEscaped
;
122 public Attribute
Clone ()
124 Attribute a
= new Attribute (ExplicitTarget
, expression
, null, loc
, nameEscaped
);
125 a
.PosArguments
= PosArguments
;
126 a
.NamedArguments
= NamedArguments
;
135 public static void Reset ()
137 att_cache
= new Dictionary
<TypeSpec
, MethodSpec
> ();
141 // When the same attribute is attached to multiple fiels
142 // we use @target field as a list of targets. The attribute
143 // has to be resolved only once but emitted for each target.
145 public virtual void AttachTo (Attributable target
, IMemberContext context
)
147 if (this.targets
== null) {
148 this.targets
= new Attributable
[] { target }
;
149 this.context
= context
;
153 // Resize target array
154 Attributable
[] new_array
= new Attributable
[this.targets
.Length
+ 1];
155 targets
.CopyTo (new_array
, 0);
156 new_array
[targets
.Length
] = target
;
157 this.targets
= new_array
;
159 // No need to update context, different targets cannot have
160 // different contexts, it's enough to remove same attributes
161 // from secondary members.
163 target
.OptAttributes
= null;
166 static void Error_InvalidNamedArgument (ResolveContext rc
, NamedArgument name
)
168 rc
.Report
.Error (617, name
.Location
, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
169 "must be fields which are not readonly, static, const or read-write properties which are " +
170 "public and not static",
174 static void Error_InvalidNamedArgumentType (ResolveContext rc
, NamedArgument name
)
176 rc
.Report
.Error (655, name
.Location
,
177 "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
181 public static void Error_AttributeArgumentNotValid (IMemberContext rc
, Location loc
)
183 rc
.Compiler
.Report
.Error (182, loc
,
184 "An attribute argument must be a constant expression, typeof " +
185 "expression or array creation expression");
188 public void Error_MissingGuidAttribute ()
190 Report
.Error (596, Location
, "The Guid attribute must be specified with the ComImport attribute");
193 public void Error_MisusedExtensionAttribute ()
195 Report
.Error (1112, Location
, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
198 public void Error_MisusedDynamicAttribute ()
200 Report
.Error (1970, loc
, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
204 /// This is rather hack. We report many emit attribute error with same error to be compatible with
205 /// csc. But because csc has to report them this way because error came from ilasm we needn't.
207 public void Error_AttributeEmitError (string inner
)
209 Report
.Error (647, Location
, "Error during emitting `{0}' attribute. The reason is `{1}'",
210 TypeManager
.CSharpName (Type
), inner
);
213 public void Error_InvalidSecurityParent ()
215 Error_AttributeEmitError ("it is attached to invalid parent");
224 protected virtual TypeExpr
ResolveAsTypeTerminal (Expression expr
, IMemberContext ec
)
226 return expr
.ResolveAsTypeTerminal (ec
, false);
229 TypeSpec
ResolvePossibleAttributeType (ATypeNameExpression expr
, ref bool is_attr
)
231 TypeExpr te
= ResolveAsTypeTerminal (expr
, context
);
235 TypeSpec t
= te
.Type
;
239 Report
.SymbolRelatedToPreviousError (t
);
240 Report
.Error (616, Location
, "`{0}': is not an attribute class", TypeManager
.CSharpName (t
));
246 /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
248 void ResolveAttributeType ()
250 SessionReportPrinter resolve_printer
= new SessionReportPrinter ();
251 ReportPrinter prev_recorder
= context
.Compiler
.Report
.SetPrinter (resolve_printer
);
253 bool t1_is_attr
= false;
254 bool t2_is_attr
= false;
256 ATypeNameExpression expanded
= null;
259 t1
= ResolvePossibleAttributeType (expression
, ref t1_is_attr
);
264 expanded
= (ATypeNameExpression
) expression
.Clone (null);
265 expanded
.Name
+= "Attribute";
267 t2
= ResolvePossibleAttributeType (expanded
, ref t2_is_attr
);
270 resolve_printer
.EndSession ();
272 context
.Compiler
.Report
.SetPrinter (prev_recorder
);
275 if (t1_is_attr
&& t2_is_attr
) {
276 Report
.Error (1614, Location
, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
277 GetSignatureForError (), expression
.GetSignatureForError (), expanded
.GetSignatureForError ());
278 resolve_error
= true;
292 resolve_printer
.Merge (prev_recorder
);
293 resolve_error
= true;
296 public virtual TypeSpec
ResolveType ()
298 if (Type
== null && !resolve_error
)
299 ResolveAttributeType ();
303 public override string GetSignatureForError ()
306 return TypeManager
.CSharpName (Type
);
308 return expression
.GetSignatureForError ();
311 public bool HasSecurityAttribute
{
313 PredefinedAttribute pa
= PredefinedAttributes
.Get
.Security
;
314 return pa
.IsDefined
&& TypeManager
.IsSubclassOf (type
, pa
.Type
);
318 public bool IsValidSecurityAttribute ()
320 return HasSecurityAttribute
&& IsSecurityActionValid (false);
323 static bool IsValidArgumentType (TypeSpec t
)
326 t
= TypeManager
.GetElementType (t
);
328 return t
== TypeManager
.string_type
||
329 TypeManager
.IsPrimitiveType (t
) ||
330 TypeManager
.IsEnumType (t
) ||
331 t
== TypeManager
.object_type
||
332 t
== TypeManager
.type_type
;
335 // TODO: Don't use this ambiguous value
337 get { return expression.Name; }
340 void ApplyModuleCharSet (ResolveContext rc
)
342 if (Type
!= PredefinedAttributes
.Get
.DllImport
)
345 if (!RootContext
.ToplevelTypes
.HasDefaultCharSet
)
348 const string CharSetEnumMember
= "CharSet";
349 if (NamedArguments
== null) {
350 NamedArguments
= new Arguments (1);
352 foreach (NamedArgument a
in NamedArguments
) {
353 if (a
.Name
== CharSetEnumMember
)
358 var char_set
= Import
.ImportType (typeof (CharSet
));
359 NamedArguments
.Add (new NamedArgument (CharSetEnumMember
, loc
,
360 Constant
.CreateConstant (rc
, char_set
, RootContext
.ToplevelTypes
.DefaultCharSet
, Location
)));
363 public Report Report
{
364 get { return context.Compiler.Report; }
367 public MethodSpec
Resolve ()
372 resolve_error
= true;
376 ResolveAttributeType ();
381 if (Type
.IsAbstract
) {
382 Report
.Error (653, Location
, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
386 ObsoleteAttribute obsolete_attr
= Type
.GetAttributeObsolete ();
387 if (obsolete_attr
!= null) {
388 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, TypeManager
.CSharpName (Type
), Location
, Report
);
392 // Try if the attribute is simple has been resolved before
393 if (PosArguments
== null && NamedArguments
== null) {
394 if (att_cache
.TryGetValue (Type
, out ctor
)) {
395 resolve_error
= false;
400 ResolveContext rc
= new ResolveContext (context
, ResolveContext
.Options
.ConstantScope
);
401 ctor
= ResolveConstructor (rc
);
406 ApplyModuleCharSet (rc
);
408 if (NamedArguments
!= null && !ResolveNamedArguments (rc
)) {
412 resolve_error
= false;
416 protected virtual MethodSpec
ResolveConstructor (ResolveContext ec
)
418 if (PosArguments
!= null) {
420 PosArguments
.Resolve (ec
, out dynamic);
422 Error_AttributeArgumentNotValid (ec
, loc
);
427 MethodGroupExpr mg
= MemberLookupFinal (ec
, ec
.CurrentType
,
428 Type
, ConstructorInfo
.ConstructorName
, 0, MemberKind
.Constructor
,
429 BindingRestriction
.AccessibleOnly
| BindingRestriction
.DeclaredOnly
,
430 Location
) as MethodGroupExpr
;
433 throw new NotImplementedException ();
435 mg
= mg
.OverloadResolve (ec
, ref PosArguments
, false, Location
);
439 var constructor
= (MethodSpec
) mg
;
443 protected virtual bool ResolveNamedArguments (ResolveContext ec
)
445 int named_arg_count
= NamedArguments
.Count
;
446 var seen_names
= new List
<string> (named_arg_count
);
448 named_values
= new List
<KeyValuePair
<MemberExpr
, NamedArgument
>> (named_arg_count
);
450 foreach (NamedArgument a
in NamedArguments
) {
451 string name
= a
.Name
;
452 if (seen_names
.Contains (name
)) {
453 ec
.Report
.Error (643, a
.Location
, "Duplicate named attribute `{0}' argument", name
);
457 seen_names
.Add (name
);
461 Expression member
= Expression
.MemberLookup (ec
.Compiler
,
462 ec
.CurrentType
, Type
, name
, 0,
464 BindingRestriction
.AccessibleOnly
,
467 if (member
== null) {
468 member
= Expression
.MemberLookup (ec
.Compiler
, ec
.CurrentType
, Type
, name
, 0,
469 MemberKind
.All
, BindingRestriction
.None
,
472 if (member
!= null) {
473 ec
.Report
.SymbolRelatedToPreviousError (member
.Type
);
474 Expression
.ErrorIsInaccesible (Location
, member
.GetSignatureForError (), ec
.Report
);
480 Expression
.Error_TypeDoesNotContainDefinition (ec
, Location
, Type
, name
);
484 if (!(member
is PropertyExpr
|| member
is FieldExpr
)) {
485 Error_InvalidNamedArgument (ec
, a
);
489 ObsoleteAttribute obsolete_attr
;
491 if (member
is PropertyExpr
) {
492 var pi
= ((PropertyExpr
) member
).PropertyInfo
;
494 if (!pi
.HasSet
|| !pi
.HasGet
|| pi
.IsStatic
) {
495 ec
.Report
.SymbolRelatedToPreviousError (pi
);
496 Error_InvalidNamedArgument (ec
, a
);
500 if (!IsValidArgumentType (member
.Type
)) {
501 ec
.Report
.SymbolRelatedToPreviousError (pi
);
502 Error_InvalidNamedArgumentType (ec
, a
);
506 obsolete_attr
= pi
.GetAttributeObsolete ();
508 var fi
= ((FieldExpr
) member
).Spec
;
510 if (fi
.IsReadOnly
|| fi
.IsStatic
) {
511 Error_InvalidNamedArgument (ec
, a
);
515 if (!IsValidArgumentType (member
.Type
)) {
516 ec
.Report
.SymbolRelatedToPreviousError (fi
);
517 Error_InvalidNamedArgumentType (ec
, a
);
521 obsolete_attr
= fi
.GetAttributeObsolete ();
524 if (obsolete_attr
!= null && !context
.IsObsolete
)
525 AttributeTester
.Report_ObsoleteMessage (obsolete_attr
, member
.GetSignatureForError (), member
.Location
, Report
);
527 if (a
.Type
!= member
.Type
) {
528 a
.Expr
= Convert
.ImplicitConversionRequired (ec
, a
.Expr
, member
.Type
, a
.Expr
.Location
);
532 named_values
.Add (new KeyValuePair
<MemberExpr
, NamedArgument
> ((MemberExpr
) member
, a
));
539 /// Get a string containing a list of valid targets for the attribute 'attr'
541 public string GetValidTargets ()
543 StringBuilder sb
= new StringBuilder ();
544 AttributeTargets targets
= Type
.GetAttributeUsage (PredefinedAttributes
.Get
.AttributeUsage
).ValidOn
;
546 if ((targets
& AttributeTargets
.Assembly
) != 0)
547 sb
.Append ("assembly, ");
549 if ((targets
& AttributeTargets
.Module
) != 0)
550 sb
.Append ("module, ");
552 if ((targets
& AttributeTargets
.Class
) != 0)
553 sb
.Append ("class, ");
555 if ((targets
& AttributeTargets
.Struct
) != 0)
556 sb
.Append ("struct, ");
558 if ((targets
& AttributeTargets
.Enum
) != 0)
559 sb
.Append ("enum, ");
561 if ((targets
& AttributeTargets
.Constructor
) != 0)
562 sb
.Append ("constructor, ");
564 if ((targets
& AttributeTargets
.Method
) != 0)
565 sb
.Append ("method, ");
567 if ((targets
& AttributeTargets
.Property
) != 0)
568 sb
.Append ("property, indexer, ");
570 if ((targets
& AttributeTargets
.Field
) != 0)
571 sb
.Append ("field, ");
573 if ((targets
& AttributeTargets
.Event
) != 0)
574 sb
.Append ("event, ");
576 if ((targets
& AttributeTargets
.Interface
) != 0)
577 sb
.Append ("interface, ");
579 if ((targets
& AttributeTargets
.Parameter
) != 0)
580 sb
.Append ("parameter, ");
582 if ((targets
& AttributeTargets
.Delegate
) != 0)
583 sb
.Append ("delegate, ");
585 if ((targets
& AttributeTargets
.ReturnValue
) != 0)
586 sb
.Append ("return, ");
588 if ((targets
& AttributeTargets
.GenericParameter
) != 0)
589 sb
.Append ("type parameter, ");
591 return sb
.Remove (sb
.Length
- 2, 2).ToString ();
594 public AttributeUsageAttribute
GetAttributeUsageAttribute ()
597 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
598 // But because a lot of attribute class code must be rewritten will be better to wait...
602 return DefaultUsageAttribute
;
604 AttributeUsageAttribute usage_attribute
= new AttributeUsageAttribute ((AttributeTargets
)((Constant
) PosArguments
[0].Expr
).GetValue ());
606 var field
= GetPropertyValue ("AllowMultiple") as BoolConstant
;
608 usage_attribute
.AllowMultiple
= field
.Value
;
610 field
= GetPropertyValue ("Inherited") as BoolConstant
;
612 usage_attribute
.Inherited
= field
.Value
;
614 return usage_attribute
;
618 /// Returns custom name of indexer
620 public string GetIndexerAttributeValue ()
623 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
624 // But because a lot of attribute class code must be rewritten will be better to wait...
630 return ((Constant
) PosArguments
[0].Expr
).GetValue () as string;
634 /// Returns condition of ConditionalAttribute
636 public string GetConditionalAttributeValue ()
639 // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
640 // But because a lot of attribute class code must be rewritten will be better to wait...
646 return ((Constant
) PosArguments
[0].Expr
).GetValue () as string;
650 /// Creates the instance of ObsoleteAttribute from this attribute instance
652 public ObsoleteAttribute
GetObsoleteAttribute ()
655 // corlib only case when obsolete is used before is resolved
656 var c
= type
.MemberDefinition
as Class
;
657 if (c
!= null && !c
.HasMembersDefined
)
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...
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
);
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.
683 public bool GetClsCompliantAttributeValue ()
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...
693 return ((BoolConstant
) PosArguments
[0].Expr
).Value
;
696 public TypeSpec
GetCoClassAttributeValue ()
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
;
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
) {
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 ());
739 /// Tests permitted SecurityAction for assembly or other types
741 protected virtual bool IsSecurityActionValid (bool for_assembly
)
743 SecurityAction action
= GetSecurityActionValue ();
746 case SecurityAction
.Demand
:
747 case SecurityAction
.Assert
:
748 case SecurityAction
.Deny
:
749 case SecurityAction
.PermitOnly
:
750 case SecurityAction
.LinkDemand
:
751 case SecurityAction
.InheritanceDemand
:
756 case SecurityAction
.RequestMinimum
:
757 case SecurityAction
.RequestOptional
:
758 case SecurityAction
.RequestRefuse
:
764 Error_AttributeEmitError ("SecurityAction is out of range");
768 Error_AttributeEmitError (String
.Concat ("SecurityAction `", action
, "' is not valid for this declaration"));
772 System
.Security
.Permissions
.SecurityAction
GetSecurityActionValue ()
774 return (SecurityAction
) ((Constant
) PosArguments
[0].Expr
).GetTypedValue ();
778 /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
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
);
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");
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");
809 SecurityAttribute sa
;
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);
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);
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
)) {
852 case SecurityAction
.Demand
:
853 action
= (SecurityAction
)13;
855 case SecurityAction
.LinkDemand
:
856 action
= (SecurityAction
)14;
858 case SecurityAction
.InheritanceDemand
:
859 action
= (SecurityAction
)15;
865 if (!permissions
.TryGetValue (action
, out ps
)) {
866 if (sa
is PermissionSetAttribute
)
867 ps
= new PermissionSet (sa
.Unrestricted
? PermissionState
.Unrestricted
: PermissionState
.None
);
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)
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
;
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.
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]);
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");
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");
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");
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
);
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
;
958 Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
961 return UnmanagedMarshal
.DefineByValArray ((int) GetFieldValue ("SizeConst"));
963 case UnmanagedType
.ByValTStr
:
964 return UnmanagedMarshal
.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
967 return UnmanagedMarshal
.DefineUnmanagedMarshal (UnmanagedType
);
971 object GetFieldValue (string name
)
974 if (field_info_arr
== null)
977 foreach (FieldInfo fi
in field_info_arr
) {
979 return GetValue (field_values_arr
[i
]);
985 static object GetValue (object value)
987 if (value is EnumConstant
)
988 return ((EnumConstant
) value).GetValue ();
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)
1005 foreach (var na
in named_values
) {
1006 if (na
.Value
.Name
== fieldName
)
1013 public bool IsInternalMethodImplAttribute
{
1015 if (Type
!= PredefinedAttributes
.Get
.MethodImpl
)
1018 MethodImplOptions options
;
1019 if (PosArguments
[0].Type
.GetMetaInfo () != typeof (MethodImplOptions
))
1020 options
= (MethodImplOptions
) System
.Enum
.ToObject (typeof (MethodImplOptions
), ((Constant
) PosArguments
[0].Expr
).GetValue ());
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
;
1044 return expr
as Constant
;
1047 public override bool Equals (object obj
)
1049 Attribute a
= obj
as Attribute
;
1053 return Type
== a
.Type
&& Target
== a
.Target
;
1056 public override int GetHashCode ()
1058 return type
.GetHashCode () ^ Target
.GetHashCode ();
1062 /// Emit attribute for Attributable symbol
1064 public void Emit (Dictionary
<Attribute
, List
<Attribute
>> allEmitted
)
1066 var ctor
= Resolve ();
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 ());
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
);
1091 var arg_expr
= PosArguments
[j
].Expr
;
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
) {
1101 string v
= ((StringConstant
) arg_expr
).Value
;
1103 } catch (Exception e
) {
1104 Error_AttributeEmitError (e
.Message
);
1107 } else if (Type
== predefined
.AttributeUsage
) {
1108 int v
= ((IntConstant
)((EnumConstant
) arg_expr
).Child
).Value
;
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.");
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);
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
);
1137 encoder
.Stream
.Write ((ushort) 0);
1140 byte[] cdata
= encoder
.ToArray ();
1143 foreach (Attributable target
in targets
)
1144 target
.ApplyAttributeBuilder (this, ctor
, cdata
, predefined
);
1145 } catch (Exception e
) {
1146 Error_AttributeEmitError (e
.Message
);
1150 if (!usage_attr
.AllowMultiple
&& allEmitted
!= null) {
1151 if (allEmitted
.ContainsKey (this)) {
1152 var a
= allEmitted
[this];
1154 a
= new List
<Attribute
> (2);
1155 allEmitted
[this] = a
;
1159 allEmitted
.Add (this, null);
1163 if (!RootContext
.VerifyClsCompliance
)
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)
1174 NamedArguments
.CheckArrayAsAttribute (context
.Compiler
);
1178 private Expression
GetValue ()
1180 if (PosArguments
== null || PosArguments
.Count
< 1)
1183 return PosArguments
[0].Expr
;
1186 public string GetString ()
1188 Expression e
= GetValue ();
1189 if (e
is StringConstant
)
1190 return ((StringConstant
)e
).Value
;
1194 public bool GetBoolean ()
1196 Expression e
= GetValue ();
1197 if (e
is BoolConstant
)
1198 return ((BoolConstant
)e
).Value
;
1202 public TypeSpec
GetArgumentType ()
1204 TypeOf e
= GetValue () as TypeOf
;
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 ();
1228 /// For global attributes (assembly, module) we need special handling.
1229 /// Attributes can be located in the several files
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
)
1242 public override void AttachTo (Attributable target
, IMemberContext context
)
1244 if (ExplicitTarget
== "assembly") {
1245 base.AttachTo (CodeGen
.Assembly
, context
);
1249 if (ExplicitTarget
== "module") {
1250 base.AttachTo (RootContext
.ToplevelTypes
, context
);
1254 throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget
);
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);
1279 RootContext
.ToplevelTypes
.NamespaceEntry
= null;
1282 protected override TypeExpr
ResolveAsTypeTerminal (Expression expr
, IMemberContext ec
)
1286 return base.ResolveAsTypeTerminal (expr
, ec
);
1293 protected override MethodSpec
ResolveConstructor (ResolveContext ec
)
1297 return base.ResolveConstructor (ec
);
1304 protected override bool ResolveNamedArguments (ResolveContext ec
)
1308 return base.ResolveNamedArguments (ec
);
1316 public class Attributes
{
1317 public readonly List
<Attribute
> Attrs
;
1319 public Attributes (Attribute a
)
1321 Attrs
= new List
<Attribute
> ();
1325 public Attributes (List
<Attribute
> 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
);
1351 /// Checks whether attribute target is valid for the current element
1353 public bool CheckTargets ()
1355 foreach (Attribute a
in Attrs
) {
1356 if (!a
.CheckTarget ())
1362 public Attribute
Search (PredefinedAttribute t
)
1364 foreach (Attribute a
in Attrs
) {
1365 if (a
.ResolveType () == t
)
1372 /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1374 public Attribute
[] SearchMulti (PredefinedAttribute t
)
1376 List
<Attribute
> ar
= null;
1378 foreach (Attribute a
in Attrs
) {
1379 if (a
.ResolveType () == t
) {
1381 ar
= new List
<Attribute
> (Attrs
.Count
);
1386 return ar
== null ? null : ar
.ToArray ();
1393 Dictionary
<Attribute
, List
<Attribute
>> ld
= Attrs
.Count
> 1 ? new Dictionary
<Attribute
, List
<Attribute
>> () : null;
1395 foreach (Attribute a
in Attrs
)
1398 if (ld
== null || ld
.Count
== 0)
1401 foreach (var d
in ld
) {
1402 if (d
.Value
== null)
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
)
1432 Stream
= new BinaryWriter (new MemoryStream ());
1433 const ushort version
= 1;
1434 Stream
.Write (version
);
1437 public void Encode (string value)
1440 throw new ArgumentNullException ();
1442 var buf
= Encoding
.UTF8
.GetBytes(value);
1443 WriteCompressedValue (buf
.Length
);
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
));
1486 throw new NotImplementedException (type
.ToString ());
1490 public bool EncodeTypeName (TypeSpec type
)
1492 // if (TypeManager.ContainsGenericParameters (type) && !TypeManager.IsGenericTypeDefinition (type))
1495 var old_type
= type
.GetMetaInfo ();
1496 Encode (type
.MemberDefinition
.IsImported
? old_type
.AssemblyQualifiedName
: old_type
.FullName
);
1500 void WriteCompressedValue (int value)
1503 Stream
.Write ((byte) value);
1507 if (value < 0x4000) {
1508 Stream
.Write ((byte) (0x80 | (value >> 8)));
1509 Stream
.Write ((byte) value);
1513 Stream
.Write (value);
1516 public byte[] ToArray ()
1518 return ((MemoryStream
) Stream
.BaseStream
).ToArray ();
1524 /// Helper class for attribute verification routine.
1526 static class AttributeTester
1528 public enum Result
{
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.
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)
1545 if (types_a
.Length
!= types_b
.Length
)
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
;
1562 if (ac_a
.Element
.IsArray
|| ac_b
.Element
.IsArray
) {
1563 result
= Result
.ArrayArrayError
;
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
;
1578 public static void VerifyModulesClsCompliance (CompilerContext ctx
)
1580 Module
[] modules
= GlobalRootNamespace
.Instance
.Modules
;
1581 if (modules
== null)
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
);
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) {
1602 return GetClsCompliantAttributeValue (a
, null);
1605 return ((CLSCompliantAttribute
)cls_attr
[0]).IsCompliant
;
1609 /// Common method for Obsolete error/warning reporting.
1611 public static void Report_ObsoleteMessage (ObsoleteAttribute oa
, string member
, Location loc
, Report Report
)
1614 Report
.Error (619, loc
, "`{0}' is obsolete: `{1}'", member
, oa
.Message
);
1618 if (oa
.Message
== null || oa
.Message
.Length
== 0) {
1619 Report
.Warning (612, 1, loc
, "`{0}' is obsolete", member
);
1622 Report
.Warning (618, 2, loc
, "`{0}' is obsolete: `{1}'", member
, oa
.Message
);
1626 public class PredefinedAttributes
1629 public readonly PredefinedAttribute ParamArray
;
1630 public readonly PredefinedAttribute Out
;
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
;
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
;
1665 public readonly PredefinedAttribute Extension
;
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
1743 CustomAttributeBuilder cab
;
1745 readonly string ns
, name
;
1746 CompilerContext compiler
;
1748 static readonly TypeSpec NotFound
= InternalType
.Null
;
1750 public PredefinedAttribute (string ns
, string 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
;
1837 public bool Resolve (bool canFail
)
1846 type
= TypeManager
.CoreLookupType (compiler
, ns
, name
, MemberKind
.Class
, !canFail
);
1855 bool ResolveBuilder ()
1861 // Handle all parameter-less attributes as optional
1863 if (!Resolve (true))
1866 var ci
= TypeManager
.GetPredefinedConstructor (type
, Location
.Null
, TypeSpec
.EmptyTypes
);
1870 cab
= new CustomAttributeBuilder ((ConstructorInfo
) ci
.GetMetaInfo (), new object[0]);
1874 public bool ResolveConstructor (Location loc
, params TypeSpec
[] argType
)
1877 throw new InternalErrorException ("Predefined ctor redefined");
1879 if (!Resolve (false))
1882 ctor
= TypeManager
.GetPredefinedConstructor (type
, loc
, argType
);
1883 return ctor
!= null;
1886 public TypeSpec Type
{
1887 get { return type; }