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.
11
// Copyright 2011 Xamarin Inc
15
using System.Collections.Generic;
16
using System.Runtime.InteropServices;
17
using System.Runtime.CompilerServices;
18
using System.Security;
19
using System.Security.Permissions;
24
using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
25
using BadImageFormat = IKVM.Reflection.BadImageFormatException;
26
using IKVM.Reflection;
27
using IKVM.Reflection.Emit;
29
using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
30
using BadImageFormat = System.BadImageFormatException;
31
using System.Reflection;
32
using System.Reflection.Emit;
35
namespace Mono.CSharp {
38
/// Base class for objects that can have Attributes applied to them.
40
public abstract class Attributable {
42
// Holds all attributes attached to this element
44
protected Attributes attributes;
46
public void AddAttributes (Attributes attrs, IMemberContext context)
51
if (attributes == null)
54
attributes.AddAttributes (attrs.Attrs);
55
attrs.AttachTo (this, context);
58
public Attributes OptAttributes {
68
/// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
70
public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
73
/// Returns one AttributeTarget for this element.
75
public abstract AttributeTargets AttributeTargets { get; }
77
public abstract bool IsClsComplianceRequired ();
80
/// Gets list of valid attribute targets for explicit target declaration.
81
/// The first array item is default target. Don't break this rule.
83
public abstract string[] ValidAttributeTargets { get; }
86
public class Attribute
88
public readonly string ExplicitTarget;
89
public AttributeTargets Target;
90
readonly ATypeNameExpression expression;
92
Arguments pos_args, named_args;
96
readonly bool nameEscaped;
97
readonly Location loc;
101
// An attribute can be attached to multiple targets (e.g. multiple fields)
103
Attributable[] targets;
106
// A member context for the attribute, it's much easier to hold it here
107
// than trying to pull it during resolve
109
IMemberContext context;
111
public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
112
public static readonly object[] EmptyObject = new object [0];
114
List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
116
public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
118
this.expression = expr;
121
named_args = args[1];
124
ExplicitTarget = target;
125
this.nameEscaped = nameEscaped;
128
public Location Location {
134
public Arguments NamedArguments {
140
public Arguments PositionalArguments {
146
public bool ResolveError {
148
return resolve_error;
152
public ATypeNameExpression TypeExpression {
158
void AddModuleCharSet (ResolveContext rc)
160
const string dll_import_char_set = "CharSet";
163
// Only when not customized by user
165
if (HasField (dll_import_char_set))
168
if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
172
if (NamedArguments == null)
173
named_args = new Arguments (1);
175
var value = Constant.CreateConstantFromValue (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
176
NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
179
public Attribute Clone ()
181
Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
182
a.pos_args = pos_args;
183
a.named_args = NamedArguments;
188
// When the same attribute is attached to multiple fiels
189
// we use @target field as a list of targets. The attribute
190
// has to be resolved only once but emitted for each target.
192
public void AttachTo (Attributable target, IMemberContext context)
194
if (this.targets == null) {
195
this.targets = new Attributable[] { target };
196
this.context = context;
200
// When re-attaching global attributes
201
if (context is NamespaceContainer) {
202
this.targets[0] = target;
203
this.context = context;
207
// Resize target array
208
Attributable[] new_array = new Attributable [this.targets.Length + 1];
209
targets.CopyTo (new_array, 0);
210
new_array [targets.Length] = target;
211
this.targets = new_array;
213
// No need to update context, different targets cannot have
214
// different contexts, it's enough to remove same attributes
215
// from secondary members.
217
target.OptAttributes = null;
220
public ResolveContext CreateResolveContext ()
222
return new ResolveContext (context, ResolveContext.Options.ConstantScope);
225
static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
227
rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
228
"must be fields which are not readonly, static, const or read-write properties which are " +
229
"public and not static",
233
static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
235
rc.Report.Error (655, name.Location,
236
"`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type",
240
public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
242
context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
245
public void Error_MissingGuidAttribute ()
247
Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
250
public void Error_MisusedExtensionAttribute ()
252
Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
255
public void Error_MisusedDynamicAttribute ()
257
Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
261
/// This is rather hack. We report many emit attribute error with same error to be compatible with
262
/// csc. But because csc has to report them this way because error came from ilasm we needn't.
264
public void Error_AttributeEmitError (string inner)
266
Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
267
TypeManager.CSharpName (Type), inner);
270
public void Error_InvalidSecurityParent ()
272
Error_AttributeEmitError ("it is attached to invalid parent");
282
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
284
void ResolveAttributeType (bool comparisonOnly)
286
SessionReportPrinter resolve_printer = new SessionReportPrinter ();
287
ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
289
bool t1_is_attr = false;
290
bool t2_is_attr = false;
292
ATypeNameExpression expanded = null;
294
// TODO: Additional warnings such as CS0436 are swallowed because we don't
298
t1 = expression.ResolveAsType (context);
300
t1_is_attr = t1.IsAttribute;
302
resolve_printer.EndSession ();
307
expanded = (ATypeNameExpression) expression.Clone (null);
308
expanded.Name += "Attribute";
310
t2 = expanded.ResolveAsType (context);
312
t2_is_attr = t2.IsAttribute;
315
context.Module.Compiler.Report.SetPrinter (prev_recorder);
318
if (t1_is_attr && t2_is_attr && t1 != t2) {
319
if (!comparisonOnly) {
320
Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
321
GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
322
resolve_error = true;
341
resolve_error = true;
344
resolve_printer.Merge (prev_recorder);
346
Report.SymbolRelatedToPreviousError (t1);
347
Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
352
Report.SymbolRelatedToPreviousError (t2);
353
Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
357
resolve_printer.Merge (prev_recorder);
360
public TypeSpec ResolveTypeForComparison ()
362
if (Type == null && !resolve_error)
363
ResolveAttributeType (true);
367
public string GetSignatureForError ()
370
return TypeManager.CSharpName (Type);
372
return expression.GetSignatureForError ();
375
public bool HasSecurityAttribute {
377
PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
378
return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
382
public bool IsValidSecurityAttribute ()
384
return HasSecurityAttribute && IsSecurityActionValid ();
387
static bool IsValidArgumentType (TypeSpec t)
390
var ac = (ArrayContainer) t;
397
switch (t.BuiltinType) {
398
case BuiltinTypeSpec.Type.Int:
399
case BuiltinTypeSpec.Type.UInt:
400
case BuiltinTypeSpec.Type.Long:
401
case BuiltinTypeSpec.Type.ULong:
402
case BuiltinTypeSpec.Type.Float:
403
case BuiltinTypeSpec.Type.Double:
404
case BuiltinTypeSpec.Type.Char:
405
case BuiltinTypeSpec.Type.Short:
406
case BuiltinTypeSpec.Type.Bool:
407
case BuiltinTypeSpec.Type.SByte:
408
case BuiltinTypeSpec.Type.Byte:
409
case BuiltinTypeSpec.Type.UShort:
411
case BuiltinTypeSpec.Type.String:
412
case BuiltinTypeSpec.Type.Object:
413
case BuiltinTypeSpec.Type.Dynamic:
414
case BuiltinTypeSpec.Type.Type:
421
// TODO: Don't use this ambiguous value
423
get { return expression.Name; }
426
public ATypeNameExpression TypeNameExpression {
432
public Report Report {
433
get { return context.Module.Compiler.Report; }
436
public MethodSpec Resolve ()
441
resolve_error = true;
445
ResolveAttributeType (false);
450
if (Type.IsAbstract) {
451
Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
455
ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
456
if (obsolete_attr != null) {
457
AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
460
ResolveContext rc = null;
463
// Try if the attribute is simple and has been resolved before
464
if (pos_args != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
465
rc = CreateResolveContext ();
466
ctor = ResolveConstructor (rc);
471
if (pos_args == null && ctor.Parameters.IsEmpty)
472
context.Module.AttributeConstructorCache.Add (Type, ctor);
476
// Add [module: DefaultCharSet] to all DllImport import attributes
478
var module = context.Module;
479
if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
481
rc = CreateResolveContext ();
483
AddModuleCharSet (rc);
486
if (NamedArguments != null) {
488
rc = CreateResolveContext ();
490
if (!ResolveNamedArguments (rc))
494
resolve_error = false;
498
MethodSpec ResolveConstructor (ResolveContext ec)
500
if (pos_args != null) {
502
pos_args.Resolve (ec, out dynamic);
504
Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
509
return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
512
bool ResolveNamedArguments (ResolveContext ec)
514
int named_arg_count = NamedArguments.Count;
515
var seen_names = new List<string> (named_arg_count);
517
named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
519
foreach (NamedArgument a in NamedArguments) {
520
string name = a.Name;
521
if (seen_names.Contains (name)) {
522
ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
526
seen_names.Add (name);
530
Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
532
if (member == null) {
533
member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
535
if (member != null) {
536
// TODO: ec.Report.SymbolRelatedToPreviousError (member);
537
Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
543
Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
547
if (!(member is PropertyExpr || member is FieldExpr)) {
548
Error_InvalidNamedArgument (ec, a);
552
ObsoleteAttribute obsolete_attr;
554
if (member is PropertyExpr) {
555
var pi = ((PropertyExpr) member).PropertyInfo;
557
if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
558
ec.Report.SymbolRelatedToPreviousError (pi);
559
Error_InvalidNamedArgument (ec, a);
563
if (!IsValidArgumentType (member.Type)) {
564
ec.Report.SymbolRelatedToPreviousError (pi);
565
Error_InvalidNamedArgumentType (ec, a);
569
obsolete_attr = pi.GetAttributeObsolete ();
570
pi.MemberDefinition.SetIsAssigned ();
572
var fi = ((FieldExpr) member).Spec;
574
if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
575
Error_InvalidNamedArgument (ec, a);
579
if (!IsValidArgumentType (member.Type)) {
580
ec.Report.SymbolRelatedToPreviousError (fi);
581
Error_InvalidNamedArgumentType (ec, a);
585
obsolete_attr = fi.GetAttributeObsolete ();
586
fi.MemberDefinition.SetIsAssigned ();
589
if (obsolete_attr != null && !context.IsObsolete)
590
AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
592
if (a.Type != member.Type) {
593
a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
597
named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
604
/// Get a string containing a list of valid targets for the attribute 'attr'
606
public string GetValidTargets ()
608
StringBuilder sb = new StringBuilder ();
609
AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
611
if ((targets & AttributeTargets.Assembly) != 0)
612
sb.Append ("assembly, ");
614
if ((targets & AttributeTargets.Module) != 0)
615
sb.Append ("module, ");
617
if ((targets & AttributeTargets.Class) != 0)
618
sb.Append ("class, ");
620
if ((targets & AttributeTargets.Struct) != 0)
621
sb.Append ("struct, ");
623
if ((targets & AttributeTargets.Enum) != 0)
624
sb.Append ("enum, ");
626
if ((targets & AttributeTargets.Constructor) != 0)
627
sb.Append ("constructor, ");
629
if ((targets & AttributeTargets.Method) != 0)
630
sb.Append ("method, ");
632
if ((targets & AttributeTargets.Property) != 0)
633
sb.Append ("property, indexer, ");
635
if ((targets & AttributeTargets.Field) != 0)
636
sb.Append ("field, ");
638
if ((targets & AttributeTargets.Event) != 0)
639
sb.Append ("event, ");
641
if ((targets & AttributeTargets.Interface) != 0)
642
sb.Append ("interface, ");
644
if ((targets & AttributeTargets.Parameter) != 0)
645
sb.Append ("parameter, ");
647
if ((targets & AttributeTargets.Delegate) != 0)
648
sb.Append ("delegate, ");
650
if ((targets & AttributeTargets.ReturnValue) != 0)
651
sb.Append ("return, ");
653
if ((targets & AttributeTargets.GenericParameter) != 0)
654
sb.Append ("type parameter, ");
656
return sb.Remove (sb.Length - 2, 2).ToString ();
659
public AttributeUsageAttribute GetAttributeUsageAttribute ()
662
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
663
// But because a lot of attribute class code must be rewritten will be better to wait...
667
return DefaultUsageAttribute;
669
AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
671
var field = GetNamedValue ("AllowMultiple") as BoolConstant;
673
usage_attribute.AllowMultiple = field.Value;
675
field = GetNamedValue ("Inherited") as BoolConstant;
677
usage_attribute.Inherited = field.Value;
679
return usage_attribute;
683
/// Returns custom name of indexer
685
public string GetIndexerAttributeValue ()
688
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
689
// But because a lot of attribute class code must be rewritten will be better to wait...
692
if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
695
return ((Constant) pos_args[0].Expr).GetValue () as string;
699
/// Returns condition of ConditionalAttribute
701
public string GetConditionalAttributeValue ()
704
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
705
// But because a lot of attribute class code must be rewritten will be better to wait...
711
return ((Constant) pos_args[0].Expr).GetValue () as string;
715
/// Creates the instance of ObsoleteAttribute from this attribute instance
717
public ObsoleteAttribute GetObsoleteAttribute ()
720
// corlib only case when obsolete is used before is resolved
721
var c = Type.MemberDefinition as Class;
722
if (c != null && !c.HasMembersDefined)
725
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
726
// But because a lot of attribute class code must be rewritten will be better to wait...
733
if (pos_args == null)
734
return new ObsoleteAttribute ();
736
string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
737
if (pos_args.Count == 1)
738
return new ObsoleteAttribute (msg);
740
return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
744
/// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
745
/// before ApplyAttribute. We need to resolve the arguments.
746
/// This situation occurs when class deps is differs from Emit order.
748
public bool GetClsCompliantAttributeValue ()
751
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
752
// But because a lot of attribute class code must be rewritten will be better to wait...
758
return ((BoolConstant) pos_args[0].Expr).Value;
761
public TypeSpec GetCoClassAttributeValue ()
769
return GetArgumentType ();
772
public bool CheckTarget ()
774
string[] valid_targets = Owner.ValidAttributeTargets;
775
if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
776
Target = Owner.AttributeTargets;
780
// TODO: we can skip the first item
781
if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
782
switch (ExplicitTarget) {
783
case "return": Target = AttributeTargets.ReturnValue; return true;
784
case "param": Target = AttributeTargets.Parameter; return true;
785
case "field": Target = AttributeTargets.Field; return true;
786
case "method": Target = AttributeTargets.Method; return true;
787
case "property": Target = AttributeTargets.Property; return true;
788
case "module": Target = AttributeTargets.Module; return true;
790
throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
793
StringBuilder sb = new StringBuilder ();
794
foreach (string s in valid_targets) {
798
sb.Remove (sb.Length - 2, 2);
799
Report.Warning (657, 1, Location,
800
"`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'. All attributes in this section will be ignored",
801
ExplicitTarget, sb.ToString ());
806
/// Tests permitted SecurityAction for assembly or other types
808
bool IsSecurityActionValid ()
810
SecurityAction action = GetSecurityActionValue ();
811
bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
814
#pragma warning disable 618
815
case SecurityAction.Demand:
816
case SecurityAction.Assert:
817
case SecurityAction.Deny:
818
case SecurityAction.PermitOnly:
819
case SecurityAction.LinkDemand:
820
case SecurityAction.InheritanceDemand:
825
case SecurityAction.RequestMinimum:
826
case SecurityAction.RequestOptional:
827
case SecurityAction.RequestRefuse:
831
#pragma warning restore 618
834
Error_AttributeEmitError ("SecurityAction is out of range");
838
Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
842
System.Security.Permissions.SecurityAction GetSecurityActionValue ()
844
return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
848
/// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
850
/// <returns></returns>
851
public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
854
object[] values = new object[pos_args.Count];
855
for (int i = 0; i < values.Length; ++i)
856
values[i] = ((Constant) pos_args[i].Expr).GetValue ();
859
object[] prop_values;
860
if (named_values == null) {
864
prop = new PropertyInfo[named_values.Count];
865
prop_values = new object [named_values.Count];
866
for (int i = 0; i < prop.Length; ++i) {
867
prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
868
prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
872
if (permissions == null)
873
permissions = new SecurityType ();
875
var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
876
permissions.Add (cab);
878
throw new NotSupportedException ();
882
public Constant GetNamedValue (string name)
884
if (named_values == null)
887
for (int i = 0; i < named_values.Count; ++i) {
888
if (named_values [i].Value.Name == name)
889
return named_values [i].Value.Expr as Constant;
895
public CharSet GetCharSetValue ()
897
return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
900
public bool HasField (string fieldName)
902
if (named_values == null)
905
foreach (var na in named_values) {
906
if (na.Value.Name == fieldName)
914
// Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
916
public bool IsInternalCall ()
918
return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
921
public MethodImplOptions GetMethodImplOptions ()
923
MethodImplOptions options = 0;
924
if (pos_args.Count == 1) {
925
options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
926
} else if (HasField ("Value")) {
927
var named = GetNamedValue ("Value");
928
options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
935
// Returns true for StructLayoutAttribute with LayoutKind.Explicit value
937
public bool IsExplicitLayoutKind ()
939
if (pos_args == null || pos_args.Count != 1)
942
var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
943
return value == LayoutKind.Explicit;
946
public Expression GetParameterDefaultValue ()
948
if (pos_args == null)
951
return pos_args[0].Expr;
954
public override bool Equals (object obj)
956
Attribute a = obj as Attribute;
960
return Type == a.Type && Target == a.Target;
963
public override int GetHashCode ()
965
return Type.GetHashCode () ^ Target.GetHashCode ();
969
/// Emit attribute for Attributable symbol
971
public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
973
var ctor = Resolve ();
977
var predefined = context.Module.PredefinedAttributes;
979
AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
980
if ((usage_attr.ValidOn & Target) == 0) {
981
Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
982
"It is valid on `{1}' declarations only",
983
GetSignatureForError (), GetValidTargets ());
988
if (pos_args == null && named_values == null) {
989
cdata = AttributeEncoder.Empty;
991
AttributeEncoder encoder = new AttributeEncoder ();
993
if (pos_args != null) {
994
var param_types = ctor.Parameters.Types;
995
for (int j = 0; j < pos_args.Count; ++j) {
996
var pt = param_types[j];
997
var arg_expr = pos_args[j].Expr;
999
if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
1000
string v = ((Constant) arg_expr).GetValue () as string;
1001
if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
1002
context.Module.Compiler.Report.Error (633, arg_expr.Location,
1003
"The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1006
} else if (Type == predefined.Guid) {
1008
string v = ((StringConstant) arg_expr).Value;
1010
} catch (Exception e) {
1011
Error_AttributeEmitError (e.Message);
1014
} else if (Type == predefined.AttributeUsage) {
1015
int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
1017
context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
1018
"System.AttributeUsage");
1020
} else if (Type == predefined.MarshalAs) {
1021
if (pos_args.Count == 1) {
1022
var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
1023
if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
1024
Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
1027
} else if (Type == predefined.DllImport) {
1028
if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
1029
var value = ((Constant) pos_args[0].Expr).GetValue () as string;
1030
if (string.IsNullOrEmpty (value))
1031
Error_AttributeEmitError ("DllName cannot be empty or null");
1033
} else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
1034
!System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
1035
Error_AttributeEmitError ("Incorrect argument value.");
1040
arg_expr.EncodeAttributeValue (context, encoder, pt);
1044
if (named_values != null) {
1045
encoder.Encode ((ushort) named_values.Count);
1046
foreach (var na in named_values) {
1047
if (na.Key is FieldExpr)
1048
encoder.Encode ((byte) 0x53);
1050
encoder.Encode ((byte) 0x54);
1052
encoder.Encode (na.Key.Type);
1053
encoder.Encode (na.Value.Name);
1054
na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
1057
encoder.EncodeEmptyNamedArguments ();
1060
cdata = encoder.ToArray ();
1063
if (!ctor.DeclaringType.IsConditionallyExcluded (context, Location)) {
1065
foreach (Attributable target in targets)
1066
target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1067
} catch (Exception e) {
1068
if (e is BadImageFormat && Report.Errors > 0)
1071
Error_AttributeEmitError (e.Message);
1076
if (!usage_attr.AllowMultiple && allEmitted != null) {
1077
if (allEmitted.ContainsKey (this)) {
1078
var a = allEmitted [this];
1080
a = new List<Attribute> (2);
1081
allEmitted [this] = a;
1085
allEmitted.Add (this, null);
1089
if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1092
// Here we are testing attribute arguments for array usage (error 3016)
1093
if (Owner.IsClsComplianceRequired ()) {
1094
if (pos_args != null)
1095
pos_args.CheckArrayAsAttribute (context.Module.Compiler);
1097
if (NamedArguments == null)
1100
NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1104
private Expression GetValue ()
1106
if (pos_args == null || pos_args.Count < 1)
1109
return pos_args[0].Expr;
1112
public string GetString ()
1114
Expression e = GetValue ();
1115
if (e is StringConstant)
1116
return ((StringConstant)e).Value;
1120
public bool GetBoolean ()
1122
Expression e = GetValue ();
1123
if (e is BoolConstant)
1124
return ((BoolConstant)e).Value;
1128
public TypeSpec GetArgumentType ()
1130
TypeOf e = GetValue () as TypeOf;
1133
return e.TypeArgument;
1137
public class Attributes
1139
public readonly List<Attribute> Attrs;
1141
public readonly List<List<Attribute>> Sections = new List<List<Attribute>> ();
1144
public Attributes (Attribute a)
1146
Attrs = new List<Attribute> ();
1150
Sections.Add (Attrs);
1154
public Attributes (List<Attribute> attrs)
1158
Sections.Add (attrs);
1162
public void AddAttribute (Attribute attr)
1167
public void AddAttributes (List<Attribute> attrs)
1170
Sections.Add (attrs);
1172
Attrs.AddRange (attrs);
1176
public void AttachTo (Attributable attributable, IMemberContext context)
1178
foreach (Attribute a in Attrs)
1179
a.AttachTo (attributable, context);
1182
public Attributes Clone ()
1184
var al = new List<Attribute> (Attrs.Count);
1185
foreach (Attribute a in Attrs)
1186
al.Add (a.Clone ());
1188
return new Attributes (al);
1192
/// Checks whether attribute target is valid for the current element
1194
public bool CheckTargets ()
1196
for (int i = 0; i < Attrs.Count; ++i) {
1197
if (!Attrs [i].CheckTarget ())
1198
Attrs.RemoveAt (i--);
1204
public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
1206
var member_explicit_targets = member.ValidAttributeTargets;
1207
for (int i = 0; i < Attrs.Count; ++i) {
1208
var attr = Attrs[0];
1209
if (attr.ExplicitTarget == null)
1213
for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
1214
if (attr.ExplicitTarget == member_explicit_targets[ii]) {
1220
if (ii < 0 || !isGlobal)
1223
member.Module.AddAttribute (attr, currentNamespace);
1229
public bool HasResolveError()
1231
foreach (var a in Attrs) {
1239
public Attribute Search (PredefinedAttribute t)
1241
return Search (null, t);
1244
public Attribute Search (string explicitTarget, PredefinedAttribute t)
1246
foreach (Attribute a in Attrs) {
1247
if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1250
if (a.ResolveTypeForComparison () == t)
1257
/// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1259
public Attribute[] SearchMulti (PredefinedAttribute t)
1261
List<Attribute> ar = null;
1263
foreach (Attribute a in Attrs) {
1264
if (a.ResolveTypeForComparison () == t) {
1266
ar = new List<Attribute> (Attrs.Count);
1271
return ar == null ? null : ar.ToArray ();
1278
Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1280
foreach (Attribute a in Attrs)
1283
if (ld == null || ld.Count == 0)
1286
foreach (var d in ld) {
1287
if (d.Value == null)
1290
Attribute a = d.Key;
1292
foreach (Attribute collision in d.Value)
1293
a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1295
a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1296
a.GetSignatureForError ());
1300
public bool Contains (PredefinedAttribute t)
1302
return Search (t) != null;
1306
public sealed class AttributeEncoder
1309
public enum EncodedTypeProperties
1313
TypeParameter = 1 << 1
1316
public static readonly byte[] Empty;
1320
const ushort Version = 1;
1322
static AttributeEncoder ()
1324
Empty = new byte[4];
1325
Empty[0] = (byte) Version;
1328
public AttributeEncoder ()
1330
buffer = new byte[32];
1334
public void Encode (bool value)
1336
Encode (value ? (byte) 1 : (byte) 0);
1339
public void Encode (byte value)
1341
if (pos == buffer.Length)
1344
buffer [pos++] = value;
1347
public void Encode (sbyte value)
1349
Encode ((byte) value);
1352
public void Encode (short value)
1354
if (pos + 2 > buffer.Length)
1357
buffer[pos++] = (byte) value;
1358
buffer[pos++] = (byte) (value >> 8);
1361
public void Encode (ushort value)
1363
Encode ((short) value);
1366
public void Encode (int value)
1368
if (pos + 4 > buffer.Length)
1371
buffer[pos++] = (byte) value;
1372
buffer[pos++] = (byte) (value >> 8);
1373
buffer[pos++] = (byte) (value >> 16);
1374
buffer[pos++] = (byte) (value >> 24);
1377
public void Encode (uint value)
1379
Encode ((int) value);
1382
public void Encode (long value)
1384
if (pos + 8 > buffer.Length)
1387
buffer[pos++] = (byte) value;
1388
buffer[pos++] = (byte) (value >> 8);
1389
buffer[pos++] = (byte) (value >> 16);
1390
buffer[pos++] = (byte) (value >> 24);
1391
buffer[pos++] = (byte) (value >> 32);
1392
buffer[pos++] = (byte) (value >> 40);
1393
buffer[pos++] = (byte) (value >> 48);
1394
buffer[pos++] = (byte) (value >> 56);
1397
public void Encode (ulong value)
1399
Encode ((long) value);
1402
public void Encode (float value)
1404
Encode (SingleConverter.SingleToInt32Bits (value));
1407
public void Encode (double value)
1409
Encode (BitConverter.DoubleToInt64Bits (value));
1412
public void Encode (string value)
1414
if (value == null) {
1415
Encode ((byte) 0xFF);
1419
var buf = Encoding.UTF8.GetBytes(value);
1420
WriteCompressedValue (buf.Length);
1422
if (pos + buf.Length > buffer.Length)
1425
Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1429
public EncodedTypeProperties Encode (TypeSpec type)
1431
switch (type.BuiltinType) {
1432
case BuiltinTypeSpec.Type.Bool:
1433
Encode ((byte) 0x02);
1435
case BuiltinTypeSpec.Type.Char:
1436
Encode ((byte) 0x03);
1438
case BuiltinTypeSpec.Type.SByte:
1439
Encode ((byte) 0x04);
1441
case BuiltinTypeSpec.Type.Byte:
1442
Encode ((byte) 0x05);
1444
case BuiltinTypeSpec.Type.Short:
1445
Encode ((byte) 0x06);
1447
case BuiltinTypeSpec.Type.UShort:
1448
Encode ((byte) 0x07);
1450
case BuiltinTypeSpec.Type.Int:
1451
Encode ((byte) 0x08);
1453
case BuiltinTypeSpec.Type.UInt:
1454
Encode ((byte) 0x09);
1456
case BuiltinTypeSpec.Type.Long:
1457
Encode ((byte) 0x0A);
1459
case BuiltinTypeSpec.Type.ULong:
1460
Encode ((byte) 0x0B);
1462
case BuiltinTypeSpec.Type.Float:
1463
Encode ((byte) 0x0C);
1465
case BuiltinTypeSpec.Type.Double:
1466
Encode ((byte) 0x0D);
1468
case BuiltinTypeSpec.Type.String:
1469
Encode ((byte) 0x0E);
1471
case BuiltinTypeSpec.Type.Type:
1472
Encode ((byte) 0x50);
1474
case BuiltinTypeSpec.Type.Object:
1475
Encode ((byte) 0x51);
1477
case BuiltinTypeSpec.Type.Dynamic:
1478
Encode ((byte) 0x51);
1479
return EncodedTypeProperties.DynamicType;
1482
Encode ((byte) 0x1D);
1483
return Encode (TypeManager.GetElementType (type));
1486
if (type.Kind == MemberKind.Enum) {
1487
Encode ((byte) 0x55);
1488
EncodeTypeName (type);
1494
return EncodedTypeProperties.None;
1497
public void EncodeTypeName (TypeSpec type)
1499
var old_type = type.GetMetaInfo ();
1500
Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1503
public void EncodeTypeName (TypeContainer type)
1505
Encode (type.GetSignatureForMetadata ());
1510
// Encodes single property named argument per call
1512
public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1514
Encode ((ushort) 1); // length
1515
Encode ((byte) 0x54); // property
1516
Encode (property.MemberType);
1517
Encode (property.Name);
1518
value.EncodeAttributeValue (null, this, property.MemberType);
1522
// Encodes single field named argument per call
1524
public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1526
Encode ((ushort) 1); // length
1527
Encode ((byte) 0x53); // field
1528
Encode (field.MemberType);
1529
Encode (field.Name);
1530
value.EncodeAttributeValue (null, this, field.MemberType);
1533
public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1535
Encode ((ushort) members.Length);
1537
for (int i = 0; i < members.Length; ++i)
1539
var member = members[i];
1541
if (member.Kind == MemberKind.Field)
1542
Encode ((byte) 0x53);
1543
else if (member.Kind == MemberKind.Property)
1544
Encode ((byte) 0x54);
1546
throw new NotImplementedException (member.Kind.ToString ());
1548
Encode (member.MemberType);
1549
Encode (member.Name);
1550
values [i].EncodeAttributeValue (null, this, member.MemberType);
1554
public void EncodeEmptyNamedArguments ()
1556
Encode ((ushort) 0);
1561
int size = System.Math.Max (pos * 4, pos + inc + 2);
1562
Array.Resize (ref buffer, size);
1565
void WriteCompressedValue (int value)
1568
Encode ((byte) value);
1572
if (value < 0x4000) {
1573
Encode ((byte) (0x80 | (value >> 8)));
1574
Encode ((byte) value);
1581
public byte[] ToArray ()
1583
byte[] buf = new byte[pos];
1584
Array.Copy (buffer, buf, pos);
1591
/// Helper class for attribute verification routine.
1593
static class AttributeTester
1596
/// Common method for Obsolete error/warning reporting.
1598
public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1601
Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1605
if (oa.Message == null || oa.Message.Length == 0) {
1606
Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1609
Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1614
// Predefined attribute types
1616
public class PredefinedAttributes
1618
// Build-in attributes
1619
public readonly PredefinedAttribute ParamArray;
1620
public readonly PredefinedAttribute Out;
1622
// Optional attributes
1623
public readonly PredefinedAttribute Obsolete;
1624
public readonly PredefinedAttribute DllImport;
1625
public readonly PredefinedAttribute MethodImpl;
1626
public readonly PredefinedAttribute MarshalAs;
1627
public readonly PredefinedAttribute In;
1628
public readonly PredefinedAttribute IndexerName;
1629
public readonly PredefinedAttribute Conditional;
1630
public readonly PredefinedAttribute CLSCompliant;
1631
public readonly PredefinedAttribute Security;
1632
public readonly PredefinedAttribute Required;
1633
public readonly PredefinedAttribute Guid;
1634
public readonly PredefinedAttribute AssemblyCulture;
1635
public readonly PredefinedAttribute AssemblyVersion;
1636
public readonly PredefinedAttribute AssemblyAlgorithmId;
1637
public readonly PredefinedAttribute AssemblyFlags;
1638
public readonly PredefinedAttribute AssemblyFileVersion;
1639
public readonly PredefinedAttribute ComImport;
1640
public readonly PredefinedAttribute CoClass;
1641
public readonly PredefinedAttribute AttributeUsage;
1642
public readonly PredefinedAttribute DefaultParameterValue;
1643
public readonly PredefinedAttribute OptionalParameter;
1644
public readonly PredefinedAttribute UnverifiableCode;
1645
public readonly PredefinedAttribute DefaultCharset;
1646
public readonly PredefinedAttribute TypeForwarder;
1647
public readonly PredefinedAttribute FixedBuffer;
1648
public readonly PredefinedAttribute CompilerGenerated;
1649
public readonly PredefinedAttribute InternalsVisibleTo;
1650
public readonly PredefinedAttribute RuntimeCompatibility;
1651
public readonly PredefinedAttribute DebuggerHidden;
1652
public readonly PredefinedAttribute UnsafeValueType;
1653
public readonly PredefinedAttribute UnmanagedFunctionPointer;
1654
public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
1657
public readonly PredefinedAttribute Extension;
1660
public readonly PredefinedDynamicAttribute Dynamic;
1663
public readonly PredefinedStateMachineAttribute AsyncStateMachine;
1666
// Optional types which are used as types and for member lookup
1668
public readonly PredefinedAttribute DefaultMember;
1669
public readonly PredefinedDecimalAttribute DecimalConstant;
1670
public readonly PredefinedAttribute StructLayout;
1671
public readonly PredefinedAttribute FieldOffset;
1672
public readonly PredefinedAttribute CallerMemberNameAttribute;
1673
public readonly PredefinedAttribute CallerLineNumberAttribute;
1674
public readonly PredefinedAttribute CallerFilePathAttribute;
1676
public PredefinedAttributes (ModuleContainer module)
1678
ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1679
Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1680
ParamArray.Resolve ();
1683
Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1684
DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1685
MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1686
MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1687
In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1688
IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1689
Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1690
CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1691
Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1692
Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1693
Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1694
AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1695
AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1696
AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1697
AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1698
AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1699
ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1700
CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1701
AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1702
DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1703
OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1704
UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1706
DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1707
TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1708
FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1709
CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1710
InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1711
RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1712
DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1713
UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1714
UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
1715
DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
1717
Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1719
Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1721
DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1722
DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1723
StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1724
FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1726
AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
1728
CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
1729
CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
1730
CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
1732
// TODO: Should define only attributes which are used for comparison
1733
const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1734
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1736
foreach (var fi in GetType ().GetFields (all_fields)) {
1737
((PredefinedAttribute) fi.GetValue (this)).Define ();
1742
public class PredefinedAttribute : PredefinedType
1744
protected MethodSpec ctor;
1746
public PredefinedAttribute (ModuleContainer module, string ns, string name)
1747
: base (module, MemberKind.Class, ns, name)
1753
public MethodSpec Constructor {
1761
public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1763
return type == pa.type && pa.type != null;
1766
public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1768
return type != pa.type;
1771
public override int GetHashCode ()
1773
return base.GetHashCode ();
1776
public override bool Equals (object obj)
1778
throw new NotSupportedException ();
1781
public void EmitAttribute (ConstructorBuilder builder)
1783
if (ResolveBuilder ())
1784
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1787
public void EmitAttribute (MethodBuilder builder)
1789
if (ResolveBuilder ())
1790
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1793
public void EmitAttribute (PropertyBuilder builder)
1795
if (ResolveBuilder ())
1796
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1799
public void EmitAttribute (FieldBuilder builder)
1801
if (ResolveBuilder ())
1802
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1805
public void EmitAttribute (TypeBuilder builder)
1807
if (ResolveBuilder ())
1808
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1811
public void EmitAttribute (AssemblyBuilder builder)
1813
if (ResolveBuilder ())
1814
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1817
public void EmitAttribute (ModuleBuilder builder)
1819
if (ResolveBuilder ())
1820
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1823
public void EmitAttribute (ParameterBuilder builder)
1825
if (ResolveBuilder ())
1826
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1829
ConstructorInfo GetCtorMetaInfo ()
1831
return (ConstructorInfo) ctor.GetMetaInfo ();
1834
public bool ResolveBuilder ()
1840
// Handle all parameter-less attributes as optional
1845
ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1846
return ctor != null;
1850
public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
1852
public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
1853
: base (module, ns, name)
1857
public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
1859
var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
1863
AttributeEncoder encoder = new AttributeEncoder ();
1864
encoder.Encode ((int) state);
1865
encoder.EncodeEmptyNamedArguments ();
1867
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1871
public class PredefinedDecimalAttribute : PredefinedAttribute
1873
public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1874
: base (module, ns, name)
1878
public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1880
var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1884
int[] bits = decimal.GetBits (value);
1885
AttributeEncoder encoder = new AttributeEncoder ();
1886
encoder.Encode ((byte) (bits[3] >> 16));
1887
encoder.Encode ((byte) (bits[3] >> 31));
1888
encoder.Encode ((uint) bits[2]);
1889
encoder.Encode ((uint) bits[1]);
1890
encoder.Encode ((uint) bits[0]);
1891
encoder.EncodeEmptyNamedArguments ();
1893
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1896
public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1898
var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1902
int[] bits = decimal.GetBits (value);
1903
AttributeEncoder encoder = new AttributeEncoder ();
1904
encoder.Encode ((byte) (bits[3] >> 16));
1905
encoder.Encode ((byte) (bits[3] >> 31));
1906
encoder.Encode ((uint) bits[2]);
1907
encoder.Encode ((uint) bits[1]);
1908
encoder.Encode ((uint) bits[0]);
1909
encoder.EncodeEmptyNamedArguments ();
1911
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1915
public class PredefinedStateMachineAttribute : PredefinedAttribute
1917
public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
1918
: base (module, ns, name)
1922
public void EmitAttribute (MethodBuilder builder, StateMachine type)
1924
var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
1926
var ctor = predefined_ctor.Get ();
1931
AttributeEncoder encoder = new AttributeEncoder ();
1932
encoder.EncodeTypeName (type);
1933
encoder.EncodeEmptyNamedArguments ();
1935
builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1939
public class PredefinedDynamicAttribute : PredefinedAttribute
1943
public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
1944
: base (module, ns, name)
1948
public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
1950
if (ResolveTransformationCtor (loc)) {
1951
var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1952
builder.SetCustomAttribute (cab);
1956
public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
1958
if (ResolveTransformationCtor (loc)) {
1959
var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1960
builder.SetCustomAttribute (cab);
1964
public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
1966
if (ResolveTransformationCtor (loc)) {
1967
var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1968
builder.SetCustomAttribute (cab);
1972
public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
1974
if (ResolveTransformationCtor (loc)) {
1975
var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
1976
builder.SetCustomAttribute (cab);
1981
// When any element of the type is a dynamic type
1983
// This method builds a transformation array for dynamic types
1984
// used in places where DynamicAttribute cannot be applied to.
1985
// It uses bool flag when type is of dynamic type and each
1986
// section always starts with "false" for some reason.
1988
// LAMESPEC: This should be part of C# specification
1990
// Example: Func<dynamic, int, dynamic[]>
1991
// Transformation: { false, true, false, false, true }
1993
static bool[] GetTransformationFlags (TypeSpec t)
1996
var ac = t as ArrayContainer;
1998
element = GetTransformationFlags (ac.Element);
1999
if (element == null)
2002
bool[] res = new bool[element.Length + 1];
2004
Array.Copy (element, 0, res, 1, element.Length);
2012
List<bool> transform = null;
2013
var targs = t.TypeArguments;
2014
for (int i = 0; i < targs.Length; ++i) {
2015
element = GetTransformationFlags (targs[i]);
2016
if (element != null) {
2017
if (transform == null) {
2018
transform = new List<bool> ();
2019
for (int ii = 0; ii <= i; ++ii)
2020
transform.Add (false);
2023
transform.AddRange (element);
2024
} else if (transform != null) {
2025
transform.Add (false);
2029
if (transform != null)
2030
return transform.ToArray ();
2033
if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
2034
return new bool[] { true };
2039
bool ResolveTransformationCtor (Location loc)
2044
tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
2045
return tctor != null;