~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to external/nrefactory/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//
 
2
// attribute.cs: Attribute Handler
 
3
//
 
4
// Author: Ravi Pratap (ravi@ximian.com)
 
5
//         Marek Safar (marek.safar@seznam.cz)
 
6
//
 
7
// Dual licensed under the terms of the MIT X11 or GNU GPL
 
8
//
 
9
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
 
10
// Copyright 2003-2008 Novell, Inc.
 
11
// Copyright 2011 Xamarin Inc
 
12
//
 
13
 
 
14
using System;
 
15
using System.Collections.Generic;
 
16
using System.Runtime.InteropServices;
 
17
using System.Runtime.CompilerServices;
 
18
using System.Security; 
 
19
using System.Security.Permissions;
 
20
using System.Text;
 
21
using System.IO;
 
22
 
 
23
#if STATIC
 
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;
 
28
#else
 
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;
 
33
#endif
 
34
 
 
35
namespace Mono.CSharp {
 
36
 
 
37
        /// <summary>
 
38
        ///   Base class for objects that can have Attributes applied to them.
 
39
        /// </summary>
 
40
        public abstract class Attributable {
 
41
                //
 
42
                // Holds all attributes attached to this element
 
43
                //
 
44
                protected Attributes attributes;
 
45
 
 
46
                public void AddAttributes (Attributes attrs, IMemberContext context)
 
47
                {
 
48
                        if (attrs == null)
 
49
                                return;
 
50
                
 
51
                        if (attributes == null)
 
52
                                attributes = attrs;
 
53
                        else
 
54
                                attributes.AddAttributes (attrs.Attrs);
 
55
                        attrs.AttachTo (this, context);
 
56
                }
 
57
 
 
58
                public Attributes OptAttributes {
 
59
                        get {
 
60
                                return attributes;
 
61
                        }
 
62
                        set {
 
63
                                attributes = value;
 
64
                        }
 
65
                }
 
66
 
 
67
                /// <summary>
 
68
                /// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
 
69
                /// </summary>
 
70
                public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
 
71
 
 
72
                /// <summary>
 
73
                /// Returns one AttributeTarget for this element.
 
74
                /// </summary>
 
75
                public abstract AttributeTargets AttributeTargets { get; }
 
76
 
 
77
                public abstract bool IsClsComplianceRequired ();
 
78
 
 
79
                /// <summary>
 
80
                /// Gets list of valid attribute targets for explicit target declaration.
 
81
                /// The first array item is default target. Don't break this rule.
 
82
                /// </summary>
 
83
                public abstract string[] ValidAttributeTargets { get; }
 
84
        };
 
85
 
 
86
        public class Attribute
 
87
        {
 
88
                public readonly string ExplicitTarget;
 
89
                public AttributeTargets Target;
 
90
                readonly ATypeNameExpression expression;
 
91
 
 
92
                Arguments pos_args, named_args;
 
93
 
 
94
                bool resolve_error;
 
95
                bool arg_resolved;
 
96
                readonly bool nameEscaped;
 
97
                readonly Location loc;
 
98
                public TypeSpec Type;   
 
99
 
 
100
                //
 
101
                // An attribute can be attached to multiple targets (e.g. multiple fields)
 
102
                //
 
103
                Attributable[] targets;
 
104
 
 
105
                //
 
106
                // A member context for the attribute, it's much easier to hold it here
 
107
                // than trying to pull it during resolve
 
108
                //
 
109
                IMemberContext context;
 
110
 
 
111
                public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
 
112
                public static readonly object[] EmptyObject = new object [0];
 
113
 
 
114
                List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
 
115
 
 
116
                public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
 
117
                {
 
118
                        this.expression = expr;
 
119
                        if (args != null) {
 
120
                                pos_args = args[0];
 
121
                                named_args = args[1];
 
122
                        }
 
123
                        this.loc = loc;
 
124
                        ExplicitTarget = target;
 
125
                        this.nameEscaped = nameEscaped;
 
126
                }
 
127
 
 
128
                public Location Location {
 
129
                        get {
 
130
                                return loc;
 
131
                        }
 
132
                }
 
133
 
 
134
                public Arguments NamedArguments {
 
135
                        get {
 
136
                                return named_args;
 
137
                        }
 
138
                }
 
139
 
 
140
                public Arguments PositionalArguments {
 
141
                        get {
 
142
                                return pos_args;
 
143
                        }
 
144
                }
 
145
 
 
146
                public bool ResolveError {
 
147
                        get {
 
148
                                return resolve_error;
 
149
                        }
 
150
                }
 
151
 
 
152
                public ATypeNameExpression TypeExpression {
 
153
                        get {
 
154
                                return expression;
 
155
                        }
 
156
                }
 
157
 
 
158
                void AddModuleCharSet (ResolveContext rc)
 
159
                {
 
160
                        const string dll_import_char_set = "CharSet";
 
161
 
 
162
                        //
 
163
                        // Only when not customized by user
 
164
                        //
 
165
                        if (HasField (dll_import_char_set))
 
166
                                return;
 
167
 
 
168
                        if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
 
169
                                return;
 
170
                        }
 
171
 
 
172
                        if (NamedArguments == null)
 
173
                                named_args = new Arguments (1);
 
174
 
 
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));
 
177
                }
 
178
 
 
179
                public Attribute Clone ()
 
180
                {
 
181
                        Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
 
182
                        a.pos_args = pos_args;
 
183
                        a.named_args = NamedArguments;
 
184
                        return a;
 
185
                }
 
186
 
 
187
                //
 
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.
 
191
                //
 
192
                public void AttachTo (Attributable target, IMemberContext context)
 
193
                {
 
194
                        if (this.targets == null) {
 
195
                                this.targets = new Attributable[] { target };
 
196
                                this.context = context;
 
197
                                return;
 
198
                        }
 
199
 
 
200
                        // When re-attaching global attributes
 
201
                        if (context is NamespaceContainer) {
 
202
                                this.targets[0] = target;
 
203
                                this.context = context;
 
204
                                return;
 
205
                        }
 
206
 
 
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;
 
212
 
 
213
                        // No need to update context, different targets cannot have
 
214
                        // different contexts, it's enough to remove same attributes
 
215
                        // from secondary members.
 
216
 
 
217
                        target.OptAttributes = null;
 
218
                }
 
219
 
 
220
                public ResolveContext CreateResolveContext ()
 
221
                {
 
222
                        return new ResolveContext (context, ResolveContext.Options.ConstantScope);
 
223
                }
 
224
 
 
225
                static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
 
226
                {
 
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",
 
230
                              name.Name);
 
231
                }
 
232
 
 
233
                static void Error_InvalidNamedArgumentType (ResolveContext rc, NamedArgument name)
 
234
                {
 
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",
 
237
                                name.Name);
 
238
                }
 
239
 
 
240
                public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
 
241
                {
 
242
                        context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
 
243
                }
 
244
                
 
245
                public void Error_MissingGuidAttribute ()
 
246
                {
 
247
                        Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute");
 
248
                }
 
249
 
 
250
                public void Error_MisusedExtensionAttribute ()
 
251
                {
 
252
                        Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ());
 
253
                }
 
254
 
 
255
                public void Error_MisusedDynamicAttribute ()
 
256
                {
 
257
                        Report.Error (1970, loc, "Do not use `{0}' directly. Use `dynamic' keyword instead", GetSignatureForError ());
 
258
                }
 
259
 
 
260
                /// <summary>
 
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.
 
263
                /// </summary>
 
264
                public void Error_AttributeEmitError (string inner)
 
265
                {
 
266
                        Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
 
267
                                      TypeManager.CSharpName (Type), inner);
 
268
                }
 
269
 
 
270
                public void Error_InvalidSecurityParent ()
 
271
                {
 
272
                        Error_AttributeEmitError ("it is attached to invalid parent");
 
273
                }
 
274
 
 
275
                Attributable Owner {
 
276
                        get {
 
277
                                return targets [0];
 
278
                        }
 
279
                }
 
280
 
 
281
                /// <summary>
 
282
                ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
 
283
                /// </summary>
 
284
                void ResolveAttributeType (bool comparisonOnly)
 
285
                {
 
286
                        SessionReportPrinter resolve_printer = new SessionReportPrinter ();
 
287
                        ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
 
288
 
 
289
                        bool t1_is_attr = false;
 
290
                        bool t2_is_attr = false;
 
291
                        TypeSpec t1, t2;
 
292
                        ATypeNameExpression expanded = null;
 
293
 
 
294
                        // TODO: Additional warnings such as CS0436 are swallowed because we don't
 
295
                        // print on success
 
296
 
 
297
                        try {
 
298
                                t1 = expression.ResolveAsType (context);
 
299
                                if (t1 != null)
 
300
                                        t1_is_attr = t1.IsAttribute;
 
301
 
 
302
                                resolve_printer.EndSession ();
 
303
 
 
304
                                if (nameEscaped) {
 
305
                                        t2 = null;
 
306
                                } else {
 
307
                                        expanded = (ATypeNameExpression) expression.Clone (null);
 
308
                                        expanded.Name += "Attribute";
 
309
 
 
310
                                        t2 = expanded.ResolveAsType (context);
 
311
                                        if (t2 != null)
 
312
                                                t2_is_attr = t2.IsAttribute;
 
313
                                }
 
314
                        } finally {
 
315
                                context.Module.Compiler.Report.SetPrinter (prev_recorder);
 
316
                        }
 
317
 
 
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;
 
323
                                }
 
324
 
 
325
                                return;
 
326
                        }
 
327
 
 
328
                        if (t1_is_attr) {
 
329
                                Type = t1;
 
330
                                return;
 
331
                        }
 
332
 
 
333
                        if (t2_is_attr) {
 
334
                                Type = t2;
 
335
                                return;
 
336
                        }
 
337
 
 
338
                        if (comparisonOnly)
 
339
                                return;
 
340
 
 
341
                        resolve_error = true;
 
342
 
 
343
                        if (t1 != null) {
 
344
                                resolve_printer.Merge (prev_recorder);
 
345
 
 
346
                                Report.SymbolRelatedToPreviousError (t1);
 
347
                                Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
 
348
                                return;
 
349
                        }
 
350
 
 
351
                        if (t2 != null) {
 
352
                                Report.SymbolRelatedToPreviousError (t2);
 
353
                                Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
 
354
                                return;
 
355
                        }
 
356
 
 
357
                        resolve_printer.Merge (prev_recorder);
 
358
                }
 
359
 
 
360
                public TypeSpec ResolveTypeForComparison ()
 
361
                {
 
362
                        if (Type == null && !resolve_error)
 
363
                                ResolveAttributeType (true);
 
364
                        return Type;
 
365
                }
 
366
 
 
367
                public string GetSignatureForError ()
 
368
                {
 
369
                        if (Type != null)
 
370
                                return TypeManager.CSharpName (Type);
 
371
 
 
372
                        return expression.GetSignatureForError ();
 
373
                }
 
374
 
 
375
                public bool HasSecurityAttribute {
 
376
                        get {
 
377
                                PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
 
378
                                return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
 
379
                        }
 
380
                }
 
381
 
 
382
                public bool IsValidSecurityAttribute ()
 
383
                {
 
384
                        return HasSecurityAttribute && IsSecurityActionValid ();
 
385
                }
 
386
 
 
387
                static bool IsValidArgumentType (TypeSpec t)
 
388
                {
 
389
                        if (t.IsArray) {
 
390
                                var ac = (ArrayContainer) t;
 
391
                                if (ac.Rank > 1)
 
392
                                        return false;
 
393
 
 
394
                                t = ac.Element;
 
395
                        }
 
396
 
 
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:
 
410
 
 
411
                        case BuiltinTypeSpec.Type.String:
 
412
                        case BuiltinTypeSpec.Type.Object:
 
413
                        case BuiltinTypeSpec.Type.Dynamic:
 
414
                        case BuiltinTypeSpec.Type.Type:
 
415
                                return true;
 
416
                        }
 
417
 
 
418
                        return t.IsEnum;
 
419
                }
 
420
 
 
421
                // TODO: Don't use this ambiguous value
 
422
                public string Name {
 
423
                        get { return expression.Name; }
 
424
                }
 
425
 
 
426
                public ATypeNameExpression TypeNameExpression {
 
427
                        get {
 
428
                                return expression;
 
429
                        }
 
430
                }
 
431
 
 
432
                public Report Report {
 
433
                        get { return context.Module.Compiler.Report; }
 
434
                }
 
435
 
 
436
                public MethodSpec Resolve ()
 
437
                {
 
438
                        if (resolve_error)
 
439
                                return null;
 
440
 
 
441
                        resolve_error = true;
 
442
                        arg_resolved = true;
 
443
 
 
444
                        if (Type == null) {
 
445
                                ResolveAttributeType (false);
 
446
                                if (Type == null)
 
447
                                        return null;
 
448
                        }
 
449
 
 
450
                        if (Type.IsAbstract) {
 
451
                                Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
 
452
                                return null;
 
453
                        }
 
454
 
 
455
                        ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
 
456
                        if (obsolete_attr != null) {
 
457
                                AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
 
458
                        }
 
459
 
 
460
                        ResolveContext rc = null;
 
461
 
 
462
                        MethodSpec ctor;
 
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);
 
467
                                if (ctor == null) {
 
468
                                        return null;
 
469
                                }
 
470
 
 
471
                                if (pos_args == null && ctor.Parameters.IsEmpty)
 
472
                                        context.Module.AttributeConstructorCache.Add (Type, ctor);
 
473
                        }
 
474
 
 
475
                        //
 
476
                        // Add [module: DefaultCharSet] to all DllImport import attributes
 
477
                        //
 
478
                        var module = context.Module;
 
479
                        if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
 
480
                                if (rc == null)
 
481
                                        rc = CreateResolveContext ();
 
482
 
 
483
                                AddModuleCharSet (rc);
 
484
                        }
 
485
 
 
486
                        if (NamedArguments != null) {
 
487
                                if (rc == null)
 
488
                                        rc = CreateResolveContext ();
 
489
 
 
490
                                if (!ResolveNamedArguments (rc))
 
491
                                        return null;
 
492
                        }
 
493
 
 
494
                        resolve_error = false;
 
495
                        return ctor;
 
496
                }
 
497
 
 
498
                MethodSpec ResolveConstructor (ResolveContext ec)
 
499
                {
 
500
                        if (pos_args != null) {
 
501
                                bool dynamic;
 
502
                                pos_args.Resolve (ec, out dynamic);
 
503
                                if (dynamic) {
 
504
                                        Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
 
505
                                        return null;
 
506
                                }
 
507
                        }
 
508
 
 
509
                        return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
 
510
                }
 
511
 
 
512
                bool ResolveNamedArguments (ResolveContext ec)
 
513
                {
 
514
                        int named_arg_count = NamedArguments.Count;
 
515
                        var seen_names = new List<string> (named_arg_count);
 
516
 
 
517
                        named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
 
518
                        
 
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);
 
523
                                        continue;
 
524
                                }                       
 
525
        
 
526
                                seen_names.Add (name);
 
527
 
 
528
                                a.Resolve (ec);
 
529
 
 
530
                                Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
 
531
 
 
532
                                if (member == null) {
 
533
                                        member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
 
534
 
 
535
                                        if (member != null) {
 
536
                                                // TODO: ec.Report.SymbolRelatedToPreviousError (member);
 
537
                                                Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
 
538
                                                return false;
 
539
                                        }
 
540
                                }
 
541
 
 
542
                                if (member == null){
 
543
                                        Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
 
544
                                        return false;
 
545
                                }
 
546
                                
 
547
                                if (!(member is PropertyExpr || member is FieldExpr)) {
 
548
                                        Error_InvalidNamedArgument (ec, a);
 
549
                                        return false;
 
550
                                }
 
551
 
 
552
                                ObsoleteAttribute obsolete_attr;
 
553
 
 
554
                                if (member is PropertyExpr) {
 
555
                                        var pi = ((PropertyExpr) member).PropertyInfo;
 
556
 
 
557
                                        if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
 
558
                                                ec.Report.SymbolRelatedToPreviousError (pi);
 
559
                                                Error_InvalidNamedArgument (ec, a);
 
560
                                                return false;
 
561
                                        }
 
562
 
 
563
                                        if (!IsValidArgumentType (member.Type)) {
 
564
                                                ec.Report.SymbolRelatedToPreviousError (pi);
 
565
                                                Error_InvalidNamedArgumentType (ec, a);
 
566
                                                return false;
 
567
                                        }
 
568
 
 
569
                                        obsolete_attr = pi.GetAttributeObsolete ();
 
570
                                        pi.MemberDefinition.SetIsAssigned ();
 
571
                                } else {
 
572
                                        var fi = ((FieldExpr) member).Spec;
 
573
 
 
574
                                        if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
 
575
                                                Error_InvalidNamedArgument (ec, a);
 
576
                                                return false;
 
577
                                        }
 
578
 
 
579
                                        if (!IsValidArgumentType (member.Type)) {
 
580
                                                ec.Report.SymbolRelatedToPreviousError (fi);
 
581
                                                Error_InvalidNamedArgumentType (ec, a);
 
582
                                                return false;
 
583
                                        }
 
584
 
 
585
                                        obsolete_attr = fi.GetAttributeObsolete ();
 
586
                                        fi.MemberDefinition.SetIsAssigned ();
 
587
                                }
 
588
 
 
589
                                if (obsolete_attr != null && !context.IsObsolete)
 
590
                                        AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
 
591
 
 
592
                                if (a.Type != member.Type) {
 
593
                                        a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
 
594
                                }
 
595
 
 
596
                                if (a.Expr != null)
 
597
                                        named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
 
598
                        }
 
599
 
 
600
                        return true;
 
601
                }
 
602
 
 
603
                /// <summary>
 
604
                ///   Get a string containing a list of valid targets for the attribute 'attr'
 
605
                /// </summary>
 
606
                public string GetValidTargets ()
 
607
                {
 
608
                        StringBuilder sb = new StringBuilder ();
 
609
                        AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
 
610
 
 
611
                        if ((targets & AttributeTargets.Assembly) != 0)
 
612
                                sb.Append ("assembly, ");
 
613
 
 
614
                        if ((targets & AttributeTargets.Module) != 0)
 
615
                                sb.Append ("module, ");
 
616
 
 
617
                        if ((targets & AttributeTargets.Class) != 0)
 
618
                                sb.Append ("class, ");
 
619
 
 
620
                        if ((targets & AttributeTargets.Struct) != 0)
 
621
                                sb.Append ("struct, ");
 
622
 
 
623
                        if ((targets & AttributeTargets.Enum) != 0)
 
624
                                sb.Append ("enum, ");
 
625
 
 
626
                        if ((targets & AttributeTargets.Constructor) != 0)
 
627
                                sb.Append ("constructor, ");
 
628
 
 
629
                        if ((targets & AttributeTargets.Method) != 0)
 
630
                                sb.Append ("method, ");
 
631
 
 
632
                        if ((targets & AttributeTargets.Property) != 0)
 
633
                                sb.Append ("property, indexer, ");
 
634
 
 
635
                        if ((targets & AttributeTargets.Field) != 0)
 
636
                                sb.Append ("field, ");
 
637
 
 
638
                        if ((targets & AttributeTargets.Event) != 0)
 
639
                                sb.Append ("event, ");
 
640
 
 
641
                        if ((targets & AttributeTargets.Interface) != 0)
 
642
                                sb.Append ("interface, ");
 
643
 
 
644
                        if ((targets & AttributeTargets.Parameter) != 0)
 
645
                                sb.Append ("parameter, ");
 
646
 
 
647
                        if ((targets & AttributeTargets.Delegate) != 0)
 
648
                                sb.Append ("delegate, ");
 
649
 
 
650
                        if ((targets & AttributeTargets.ReturnValue) != 0)
 
651
                                sb.Append ("return, ");
 
652
 
 
653
                        if ((targets & AttributeTargets.GenericParameter) != 0)
 
654
                                sb.Append ("type parameter, ");
 
655
 
 
656
                        return sb.Remove (sb.Length - 2, 2).ToString ();
 
657
                }
 
658
 
 
659
                public AttributeUsageAttribute GetAttributeUsageAttribute ()
 
660
                {
 
661
                        if (!arg_resolved)
 
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...
 
664
                                Resolve ();
 
665
 
 
666
                        if (resolve_error)
 
667
                                return DefaultUsageAttribute;
 
668
 
 
669
                        AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
 
670
 
 
671
                        var field = GetNamedValue ("AllowMultiple") as BoolConstant;
 
672
                        if (field != null)
 
673
                                usage_attribute.AllowMultiple = field.Value;
 
674
 
 
675
                        field = GetNamedValue ("Inherited") as BoolConstant;
 
676
                        if (field != null)
 
677
                                usage_attribute.Inherited = field.Value;
 
678
 
 
679
                        return usage_attribute;
 
680
                }
 
681
 
 
682
                /// <summary>
 
683
                /// Returns custom name of indexer
 
684
                /// </summary>
 
685
                public string GetIndexerAttributeValue ()
 
686
                {
 
687
                        if (!arg_resolved)
 
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...
 
690
                                Resolve ();
 
691
 
 
692
                        if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
 
693
                                return null;
 
694
 
 
695
                        return ((Constant) pos_args[0].Expr).GetValue () as string;
 
696
                }
 
697
 
 
698
                /// <summary>
 
699
                /// Returns condition of ConditionalAttribute
 
700
                /// </summary>
 
701
                public string GetConditionalAttributeValue ()
 
702
                {
 
703
                        if (!arg_resolved)
 
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...
 
706
                                Resolve ();
 
707
 
 
708
                        if (resolve_error)
 
709
                                return null;
 
710
 
 
711
                        return ((Constant) pos_args[0].Expr).GetValue () as string;
 
712
                }
 
713
 
 
714
                /// <summary>
 
715
                /// Creates the instance of ObsoleteAttribute from this attribute instance
 
716
                /// </summary>
 
717
                public ObsoleteAttribute GetObsoleteAttribute ()
 
718
                {
 
719
                        if (!arg_resolved) {
 
720
                                // corlib only case when obsolete is used before is resolved
 
721
                                var c = Type.MemberDefinition as Class;
 
722
                                if (c != null && !c.HasMembersDefined)
 
723
                                        c.Define ();
 
724
                                
 
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...
 
727
                                Resolve ();
 
728
                        }
 
729
 
 
730
                        if (resolve_error)
 
731
                                return null;
 
732
 
 
733
                        if (pos_args == null)
 
734
                                return new ObsoleteAttribute ();
 
735
 
 
736
                        string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
 
737
                        if (pos_args.Count == 1)
 
738
                                return new ObsoleteAttribute (msg);
 
739
 
 
740
                        return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
 
741
                }
 
742
 
 
743
                /// <summary>
 
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.  
 
747
                /// </summary>
 
748
                public bool GetClsCompliantAttributeValue ()
 
749
                {
 
750
                        if (!arg_resolved)
 
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...
 
753
                                Resolve ();
 
754
 
 
755
                        if (resolve_error)
 
756
                                return false;
 
757
 
 
758
                        return ((BoolConstant) pos_args[0].Expr).Value;
 
759
                }
 
760
 
 
761
                public TypeSpec GetCoClassAttributeValue ()
 
762
                {
 
763
                        if (!arg_resolved)
 
764
                                Resolve ();
 
765
 
 
766
                        if (resolve_error)
 
767
                                return null;
 
768
 
 
769
                        return GetArgumentType ();
 
770
                }
 
771
 
 
772
                public bool CheckTarget ()
 
773
                {
 
774
                        string[] valid_targets = Owner.ValidAttributeTargets;
 
775
                        if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
 
776
                                Target = Owner.AttributeTargets;
 
777
                                return true;
 
778
                        }
 
779
 
 
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;
 
789
                                }
 
790
                                throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
 
791
                        }
 
792
                                
 
793
                        StringBuilder sb = new StringBuilder ();
 
794
                        foreach (string s in valid_targets) {
 
795
                                sb.Append (s);
 
796
                                sb.Append (", ");
 
797
                        }
 
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 ());
 
802
                        return false;
 
803
                }
 
804
 
 
805
                /// <summary>
 
806
                /// Tests permitted SecurityAction for assembly or other types
 
807
                /// </summary>
 
808
                bool IsSecurityActionValid ()
 
809
                {
 
810
                        SecurityAction action = GetSecurityActionValue ();
 
811
                        bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
 
812
 
 
813
                        switch (action) {
 
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:
 
821
                                if (!for_assembly)
 
822
                                        return true;
 
823
                                break;
 
824
 
 
825
                        case SecurityAction.RequestMinimum:
 
826
                        case SecurityAction.RequestOptional:
 
827
                        case SecurityAction.RequestRefuse:
 
828
                                if (for_assembly)
 
829
                                        return true;
 
830
                                break;
 
831
#pragma warning restore 618
 
832
 
 
833
                        default:
 
834
                                Error_AttributeEmitError ("SecurityAction is out of range");
 
835
                                return false;
 
836
                        }
 
837
 
 
838
                        Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration"));
 
839
                        return false;
 
840
                }
 
841
 
 
842
                System.Security.Permissions.SecurityAction GetSecurityActionValue ()
 
843
                {
 
844
                        return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
 
845
                }
 
846
 
 
847
                /// <summary>
 
848
                /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
 
849
                /// </summary>
 
850
                /// <returns></returns>
 
851
                public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
 
852
                {
 
853
#if STATIC
 
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 ();
 
857
 
 
858
                        PropertyInfo[] prop;
 
859
                        object[] prop_values;
 
860
                        if (named_values == null) {
 
861
                                prop = null;
 
862
                                prop_values = null;
 
863
                        } else {
 
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 ();
 
869
                                }
 
870
                        }
 
871
 
 
872
                        if (permissions == null)
 
873
                                permissions = new SecurityType ();
 
874
 
 
875
                        var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
 
876
                        permissions.Add (cab);
 
877
#else
 
878
                        throw new NotSupportedException ();
 
879
#endif
 
880
                }
 
881
 
 
882
                public Constant GetNamedValue (string name)
 
883
                {
 
884
                        if (named_values == null)
 
885
                                return null;
 
886
 
 
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;
 
890
                        }
 
891
 
 
892
                        return null;
 
893
                }
 
894
 
 
895
                public CharSet GetCharSetValue ()
 
896
                {
 
897
                        return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
 
898
                }
 
899
 
 
900
                public bool HasField (string fieldName)
 
901
                {
 
902
                        if (named_values == null)
 
903
                                return false;
 
904
 
 
905
                        foreach (var na in named_values) {
 
906
                                if (na.Value.Name == fieldName)
 
907
                                        return true;
 
908
                        }
 
909
 
 
910
                        return false;
 
911
                }
 
912
 
 
913
                //
 
914
                // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
 
915
                // 
 
916
                public bool IsInternalCall ()
 
917
                {
 
918
                        return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
 
919
                }
 
920
 
 
921
                public MethodImplOptions GetMethodImplOptions ()
 
922
                {
 
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 ());
 
929
                        }
 
930
 
 
931
                        return options;
 
932
                }
 
933
 
 
934
                //
 
935
                // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
 
936
                // 
 
937
                public bool IsExplicitLayoutKind ()
 
938
                {
 
939
                        if (pos_args == null || pos_args.Count != 1)
 
940
                                return false;
 
941
 
 
942
                        var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
 
943
                        return value == LayoutKind.Explicit;
 
944
                }
 
945
 
 
946
                public Expression GetParameterDefaultValue ()
 
947
                {
 
948
                        if (pos_args == null)
 
949
                                return null;
 
950
 
 
951
                        return pos_args[0].Expr;
 
952
                }
 
953
 
 
954
                public override bool Equals (object obj)
 
955
                {
 
956
                        Attribute a = obj as Attribute;
 
957
                        if (a == null)
 
958
                                return false;
 
959
 
 
960
                        return Type == a.Type && Target == a.Target;
 
961
                }
 
962
 
 
963
                public override int GetHashCode ()
 
964
                {
 
965
                        return Type.GetHashCode () ^ Target.GetHashCode ();
 
966
                }
 
967
 
 
968
                /// <summary>
 
969
                /// Emit attribute for Attributable symbol
 
970
                /// </summary>
 
971
                public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
 
972
                {
 
973
                        var ctor = Resolve ();
 
974
                        if (ctor == null)
 
975
                                return;
 
976
 
 
977
                        var predefined = context.Module.PredefinedAttributes;
 
978
 
 
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 ());
 
984
                                return;
 
985
                        }
 
986
 
 
987
                        byte[] cdata;
 
988
                        if (pos_args == null && named_values == null) {
 
989
                                cdata = AttributeEncoder.Empty;
 
990
                        } else {
 
991
                                AttributeEncoder encoder = new AttributeEncoder ();
 
992
 
 
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;
 
998
                                                if (j == 0) {
 
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 ());
 
1004
                                                                        return;
 
1005
                                                                }
 
1006
                                                        } else if (Type == predefined.Guid) {
 
1007
                                                                try {
 
1008
                                                                        string v = ((StringConstant) arg_expr).Value;
 
1009
                                                                        new Guid (v);
 
1010
                                                                } catch (Exception e) {
 
1011
                                                                        Error_AttributeEmitError (e.Message);
 
1012
                                                                        return;
 
1013
                                                                }
 
1014
                                                        } else if (Type == predefined.AttributeUsage) {
 
1015
                                                                int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
 
1016
                                                                if (v == 0) {
 
1017
                                                                        context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
 
1018
                                                                                "System.AttributeUsage");
 
1019
                                                                }
 
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");
 
1025
                                                                        }
 
1026
                                                                }
 
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");
 
1032
                                                                }
 
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.");
 
1036
                                                                return;
 
1037
                                                        }
 
1038
                                                }
 
1039
 
 
1040
                                                arg_expr.EncodeAttributeValue (context, encoder, pt);
 
1041
                                        }
 
1042
                                }
 
1043
 
 
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);
 
1049
                                                else
 
1050
                                                        encoder.Encode ((byte) 0x54);
 
1051
 
 
1052
                                                encoder.Encode (na.Key.Type);
 
1053
                                                encoder.Encode (na.Value.Name);
 
1054
                                                na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
 
1055
                                        }
 
1056
                                } else {
 
1057
                                        encoder.EncodeEmptyNamedArguments ();
 
1058
                                }
 
1059
 
 
1060
                                cdata = encoder.ToArray ();
 
1061
                        }
 
1062
 
 
1063
                        if (!ctor.DeclaringType.IsConditionallyExcluded (context, Location)) {
 
1064
                                try {
 
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)
 
1069
                                                return;
 
1070
 
 
1071
                                        Error_AttributeEmitError (e.Message);
 
1072
                                        return;
 
1073
                                }
 
1074
                        }
 
1075
 
 
1076
                        if (!usage_attr.AllowMultiple && allEmitted != null) {
 
1077
                                if (allEmitted.ContainsKey (this)) {
 
1078
                                        var a = allEmitted [this];
 
1079
                                        if (a == null) {
 
1080
                                                a = new List<Attribute> (2);
 
1081
                                                allEmitted [this] = a;
 
1082
                                        }
 
1083
                                        a.Add (this);
 
1084
                                } else {
 
1085
                                        allEmitted.Add (this, null);
 
1086
                                }
 
1087
                        }
 
1088
 
 
1089
                        if (!context.Module.Compiler.Settings.VerifyClsCompliance)
 
1090
                                return;
 
1091
 
 
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);
 
1096
                        
 
1097
                                if (NamedArguments == null)
 
1098
                                        return;
 
1099
 
 
1100
                                NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
 
1101
                        }
 
1102
                }
 
1103
 
 
1104
                private Expression GetValue () 
 
1105
                {
 
1106
                        if (pos_args == null || pos_args.Count < 1)
 
1107
                                return null;
 
1108
 
 
1109
                        return pos_args[0].Expr;
 
1110
                }
 
1111
 
 
1112
                public string GetString () 
 
1113
                {
 
1114
                        Expression e = GetValue ();
 
1115
                        if (e is StringConstant)
 
1116
                                return ((StringConstant)e).Value;
 
1117
                        return null;
 
1118
                }
 
1119
 
 
1120
                public bool GetBoolean () 
 
1121
                {
 
1122
                        Expression e = GetValue ();
 
1123
                        if (e is BoolConstant)
 
1124
                                return ((BoolConstant)e).Value;
 
1125
                        return false;
 
1126
                }
 
1127
 
 
1128
                public TypeSpec GetArgumentType ()
 
1129
                {
 
1130
                        TypeOf e = GetValue () as TypeOf;
 
1131
                        if (e == null)
 
1132
                                return null;
 
1133
                        return e.TypeArgument;
 
1134
                }
 
1135
        }
 
1136
        
 
1137
        public class Attributes
 
1138
        {
 
1139
                public readonly List<Attribute> Attrs;
 
1140
#if FULL_AST
 
1141
                public readonly List<List<Attribute>> Sections = new List<List<Attribute>> ();
 
1142
#endif
 
1143
 
 
1144
                public Attributes (Attribute a)
 
1145
                {
 
1146
                        Attrs = new List<Attribute> ();
 
1147
                        Attrs.Add (a);
 
1148
                        
 
1149
#if FULL_AST
 
1150
                        Sections.Add (Attrs);
 
1151
#endif
 
1152
                }
 
1153
 
 
1154
                public Attributes (List<Attribute> attrs)
 
1155
                {
 
1156
                        Attrs = attrs;
 
1157
#if FULL_AST
 
1158
                        Sections.Add (attrs);
 
1159
#endif
 
1160
                }
 
1161
 
 
1162
                public void AddAttribute (Attribute attr)
 
1163
                {
 
1164
                        Attrs.Add (attr);
 
1165
                }
 
1166
 
 
1167
                public void AddAttributes (List<Attribute> attrs)
 
1168
                {
 
1169
#if FULL_AST
 
1170
                        Sections.Add (attrs);
 
1171
#else
 
1172
                        Attrs.AddRange (attrs);
 
1173
#endif
 
1174
                }
 
1175
 
 
1176
                public void AttachTo (Attributable attributable, IMemberContext context)
 
1177
                {
 
1178
                        foreach (Attribute a in Attrs)
 
1179
                                a.AttachTo (attributable, context);
 
1180
                }
 
1181
 
 
1182
                public Attributes Clone ()
 
1183
                {
 
1184
                        var al = new List<Attribute> (Attrs.Count);
 
1185
                        foreach (Attribute a in Attrs)
 
1186
                                al.Add (a.Clone ());
 
1187
 
 
1188
                        return new Attributes (al);
 
1189
                }
 
1190
 
 
1191
                /// <summary>
 
1192
                /// Checks whether attribute target is valid for the current element
 
1193
                /// </summary>
 
1194
                public bool CheckTargets ()
 
1195
                {
 
1196
                        for (int i = 0; i < Attrs.Count; ++i) {
 
1197
                                if (!Attrs [i].CheckTarget ())
 
1198
                                        Attrs.RemoveAt (i--);
 
1199
                        }
 
1200
 
 
1201
                        return true;
 
1202
                }
 
1203
 
 
1204
                public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
 
1205
                {
 
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)
 
1210
                                        continue;
 
1211
 
 
1212
                                int ii;
 
1213
                                for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
 
1214
                                        if (attr.ExplicitTarget == member_explicit_targets[ii]) {
 
1215
                                                ii = -1;
 
1216
                                                break;
 
1217
                                        }
 
1218
                                }
 
1219
 
 
1220
                                if (ii < 0 || !isGlobal)
 
1221
                                        continue;
 
1222
 
 
1223
                                member.Module.AddAttribute (attr, currentNamespace);
 
1224
                                Attrs.RemoveAt (i);
 
1225
                                --i;
 
1226
                        }
 
1227
                }
 
1228
 
 
1229
                public bool HasResolveError()
 
1230
                {
 
1231
                        foreach (var a in Attrs) {
 
1232
                                if (a.ResolveError)
 
1233
                                        return true;
 
1234
                        }
 
1235
 
 
1236
                        return false;
 
1237
                }
 
1238
 
 
1239
                public Attribute Search (PredefinedAttribute t)
 
1240
                {
 
1241
                        return Search (null, t);
 
1242
                }
 
1243
 
 
1244
                public Attribute Search (string explicitTarget, PredefinedAttribute t)
 
1245
                {
 
1246
                        foreach (Attribute a in Attrs) {
 
1247
                                if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
 
1248
                                        continue;
 
1249
 
 
1250
                                if (a.ResolveTypeForComparison () == t)
 
1251
                                        return a;
 
1252
                        }
 
1253
                        return null;
 
1254
                }
 
1255
 
 
1256
                /// <summary>
 
1257
                /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
 
1258
                /// </summary>
 
1259
                public Attribute[] SearchMulti (PredefinedAttribute t)
 
1260
                {
 
1261
                        List<Attribute> ar = null;
 
1262
 
 
1263
                        foreach (Attribute a in Attrs) {
 
1264
                                if (a.ResolveTypeForComparison () == t) {
 
1265
                                        if (ar == null)
 
1266
                                                ar = new List<Attribute> (Attrs.Count);
 
1267
                                        ar.Add (a);
 
1268
                                }
 
1269
                        }
 
1270
 
 
1271
                        return ar == null ? null : ar.ToArray ();
 
1272
                }
 
1273
 
 
1274
                public void Emit ()
 
1275
                {
 
1276
                        CheckTargets ();
 
1277
 
 
1278
                        Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
 
1279
 
 
1280
                        foreach (Attribute a in Attrs)
 
1281
                                a.Emit (ld);
 
1282
 
 
1283
                        if (ld == null || ld.Count == 0)
 
1284
                                return;
 
1285
 
 
1286
                        foreach (var d in ld) {
 
1287
                                if (d.Value == null)
 
1288
                                        continue;
 
1289
 
 
1290
                                Attribute a = d.Key;
 
1291
 
 
1292
                                foreach (Attribute collision in d.Value)
 
1293
                                        a.Report.SymbolRelatedToPreviousError (collision.Location, "");
 
1294
 
 
1295
                                a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
 
1296
                                        a.GetSignatureForError ());
 
1297
                        }
 
1298
                }
 
1299
 
 
1300
                public bool Contains (PredefinedAttribute t)
 
1301
                {
 
1302
                        return Search (t) != null;
 
1303
                }
 
1304
        }
 
1305
 
 
1306
        public sealed class AttributeEncoder
 
1307
        {
 
1308
                [Flags]
 
1309
                public enum EncodedTypeProperties
 
1310
                {
 
1311
                        None = 0,
 
1312
                        DynamicType = 1,
 
1313
                        TypeParameter = 1 << 1
 
1314
                }
 
1315
 
 
1316
                public static readonly byte[] Empty;
 
1317
 
 
1318
                byte[] buffer;
 
1319
                int pos;
 
1320
                const ushort Version = 1;
 
1321
 
 
1322
                static AttributeEncoder ()
 
1323
                {
 
1324
                        Empty = new byte[4];
 
1325
                        Empty[0] = (byte) Version;
 
1326
                }
 
1327
 
 
1328
                public AttributeEncoder ()
 
1329
                {
 
1330
                        buffer = new byte[32];
 
1331
                        Encode (Version);
 
1332
                }
 
1333
 
 
1334
                public void Encode (bool value)
 
1335
                {
 
1336
                        Encode (value ? (byte) 1 : (byte) 0);
 
1337
                }
 
1338
 
 
1339
                public void Encode (byte value)
 
1340
                {
 
1341
                        if (pos == buffer.Length)
 
1342
                                Grow (1);
 
1343
 
 
1344
                        buffer [pos++] = value;
 
1345
                }
 
1346
 
 
1347
                public void Encode (sbyte value)
 
1348
                {
 
1349
                        Encode ((byte) value);
 
1350
                }
 
1351
 
 
1352
                public void Encode (short value)
 
1353
                {
 
1354
                        if (pos + 2 > buffer.Length)
 
1355
                                Grow (2);
 
1356
 
 
1357
                        buffer[pos++] = (byte) value;
 
1358
                        buffer[pos++] = (byte) (value >> 8);
 
1359
                }
 
1360
 
 
1361
                public void Encode (ushort value)
 
1362
                {
 
1363
                        Encode ((short) value);
 
1364
                }
 
1365
 
 
1366
                public void Encode (int value)
 
1367
                {
 
1368
                        if (pos + 4 > buffer.Length)
 
1369
                                Grow (4);
 
1370
 
 
1371
                        buffer[pos++] = (byte) value;
 
1372
                        buffer[pos++] = (byte) (value >> 8);
 
1373
                        buffer[pos++] = (byte) (value >> 16);
 
1374
                        buffer[pos++] = (byte) (value >> 24);
 
1375
                }
 
1376
 
 
1377
                public void Encode (uint value)
 
1378
                {
 
1379
                        Encode ((int) value);
 
1380
                }
 
1381
 
 
1382
                public void Encode (long value)
 
1383
                {
 
1384
                        if (pos + 8 > buffer.Length)
 
1385
                                Grow (8);
 
1386
 
 
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);
 
1395
                }
 
1396
 
 
1397
                public void Encode (ulong value)
 
1398
                {
 
1399
                        Encode ((long) value);
 
1400
                }
 
1401
 
 
1402
                public void Encode (float value)
 
1403
                {
 
1404
                        Encode (SingleConverter.SingleToInt32Bits (value));
 
1405
                }
 
1406
 
 
1407
                public void Encode (double value)
 
1408
                {
 
1409
                        Encode (BitConverter.DoubleToInt64Bits (value));
 
1410
                }
 
1411
 
 
1412
                public void Encode (string value)
 
1413
                {
 
1414
                        if (value == null) {
 
1415
                                Encode ((byte) 0xFF);
 
1416
                                return;
 
1417
                        }
 
1418
 
 
1419
                        var buf = Encoding.UTF8.GetBytes(value);
 
1420
                        WriteCompressedValue (buf.Length);
 
1421
 
 
1422
                        if (pos + buf.Length > buffer.Length)
 
1423
                                Grow (buf.Length);
 
1424
 
 
1425
                        Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
 
1426
                        pos += buf.Length;
 
1427
                }
 
1428
 
 
1429
                public EncodedTypeProperties Encode (TypeSpec type)
 
1430
                {
 
1431
                        switch (type.BuiltinType) {
 
1432
                        case BuiltinTypeSpec.Type.Bool:
 
1433
                                Encode ((byte) 0x02);
 
1434
                                break;
 
1435
                        case BuiltinTypeSpec.Type.Char:
 
1436
                                Encode ((byte) 0x03);
 
1437
                                break;
 
1438
                        case BuiltinTypeSpec.Type.SByte:
 
1439
                                Encode ((byte) 0x04);
 
1440
                                break;
 
1441
                        case BuiltinTypeSpec.Type.Byte:
 
1442
                                Encode ((byte) 0x05);
 
1443
                                break;
 
1444
                        case BuiltinTypeSpec.Type.Short:
 
1445
                                Encode ((byte) 0x06);
 
1446
                                break;
 
1447
                        case BuiltinTypeSpec.Type.UShort:
 
1448
                                Encode ((byte) 0x07);
 
1449
                                break;
 
1450
                        case BuiltinTypeSpec.Type.Int:
 
1451
                                Encode ((byte) 0x08);
 
1452
                                break;
 
1453
                        case BuiltinTypeSpec.Type.UInt:
 
1454
                                Encode ((byte) 0x09);
 
1455
                                break;
 
1456
                        case BuiltinTypeSpec.Type.Long:
 
1457
                                Encode ((byte) 0x0A);
 
1458
                                break;
 
1459
                        case BuiltinTypeSpec.Type.ULong:
 
1460
                                Encode ((byte) 0x0B);
 
1461
                                break;
 
1462
                        case BuiltinTypeSpec.Type.Float:
 
1463
                                Encode ((byte) 0x0C);
 
1464
                                break;
 
1465
                        case BuiltinTypeSpec.Type.Double:
 
1466
                                Encode ((byte) 0x0D);
 
1467
                                break;
 
1468
                        case BuiltinTypeSpec.Type.String:
 
1469
                                Encode ((byte) 0x0E);
 
1470
                                break;
 
1471
                        case BuiltinTypeSpec.Type.Type:
 
1472
                                Encode ((byte) 0x50);
 
1473
                                break;
 
1474
                        case BuiltinTypeSpec.Type.Object:
 
1475
                                Encode ((byte) 0x51);
 
1476
                                break;
 
1477
                        case BuiltinTypeSpec.Type.Dynamic:
 
1478
                                Encode ((byte) 0x51);
 
1479
                                return EncodedTypeProperties.DynamicType;
 
1480
                        default:
 
1481
                                if (type.IsArray) {
 
1482
                                        Encode ((byte) 0x1D);
 
1483
                                        return Encode (TypeManager.GetElementType (type));
 
1484
                                }
 
1485
 
 
1486
                                if (type.Kind == MemberKind.Enum) {
 
1487
                                        Encode ((byte) 0x55);
 
1488
                                        EncodeTypeName (type);
 
1489
                                }
 
1490
 
 
1491
                                break;
 
1492
                        }
 
1493
 
 
1494
                        return EncodedTypeProperties.None;
 
1495
                }
 
1496
 
 
1497
                public void EncodeTypeName (TypeSpec type)
 
1498
                {
 
1499
                        var old_type = type.GetMetaInfo ();
 
1500
                        Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
 
1501
                }
 
1502
 
 
1503
                public void EncodeTypeName (TypeContainer type)
 
1504
                {
 
1505
                        Encode (type.GetSignatureForMetadata ());
 
1506
                }
 
1507
 
 
1508
 
 
1509
                //
 
1510
                // Encodes single property named argument per call
 
1511
                //
 
1512
                public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
 
1513
                {
 
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);
 
1519
                }
 
1520
 
 
1521
                //
 
1522
                // Encodes single field named argument per call
 
1523
                //
 
1524
                public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
 
1525
                {
 
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);
 
1531
                }
 
1532
 
 
1533
                public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
 
1534
                {
 
1535
                        Encode ((ushort) members.Length);
 
1536
 
 
1537
                        for (int i = 0; i < members.Length; ++i)
 
1538
                        {
 
1539
                                var member = members[i];
 
1540
 
 
1541
                                if (member.Kind == MemberKind.Field)
 
1542
                                        Encode ((byte) 0x53);
 
1543
                                else if (member.Kind == MemberKind.Property)
 
1544
                                        Encode ((byte) 0x54);
 
1545
                                else
 
1546
                                        throw new NotImplementedException (member.Kind.ToString ());
 
1547
 
 
1548
                                Encode (member.MemberType);
 
1549
                                Encode (member.Name);
 
1550
                                values [i].EncodeAttributeValue (null, this, member.MemberType);
 
1551
                        }
 
1552
                }
 
1553
 
 
1554
                public void EncodeEmptyNamedArguments ()
 
1555
                {
 
1556
                        Encode ((ushort) 0);
 
1557
                }
 
1558
 
 
1559
                void Grow (int inc)
 
1560
                {
 
1561
                        int size = System.Math.Max (pos * 4, pos + inc + 2);
 
1562
                        Array.Resize (ref buffer, size);
 
1563
                }
 
1564
 
 
1565
                void WriteCompressedValue (int value)
 
1566
                {
 
1567
                        if (value < 0x80) {
 
1568
                                Encode ((byte) value);
 
1569
                                return;
 
1570
                        }
 
1571
 
 
1572
                        if (value < 0x4000) {
 
1573
                                Encode ((byte) (0x80 | (value >> 8)));
 
1574
                                Encode ((byte) value);
 
1575
                                return;
 
1576
                        }
 
1577
 
 
1578
                        Encode (value);
 
1579
                }
 
1580
 
 
1581
                public byte[] ToArray ()
 
1582
                {
 
1583
                        byte[] buf = new byte[pos];
 
1584
                        Array.Copy (buffer, buf, pos);
 
1585
                        return buf;
 
1586
                }
 
1587
        }
 
1588
 
 
1589
 
 
1590
        /// <summary>
 
1591
        /// Helper class for attribute verification routine.
 
1592
        /// </summary>
 
1593
        static class AttributeTester
 
1594
        {
 
1595
                /// <summary>
 
1596
                /// Common method for Obsolete error/warning reporting.
 
1597
                /// </summary>
 
1598
                public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
 
1599
                {
 
1600
                        if (oa.IsError) {
 
1601
                                Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
 
1602
                                return;
 
1603
                        }
 
1604
 
 
1605
                        if (oa.Message == null || oa.Message.Length == 0) {
 
1606
                                Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
 
1607
                                return;
 
1608
                        }
 
1609
                        Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
 
1610
                }
 
1611
        }
 
1612
 
 
1613
        //
 
1614
        // Predefined attribute types
 
1615
        //
 
1616
        public class PredefinedAttributes
 
1617
        {
 
1618
                // Build-in attributes
 
1619
                public readonly PredefinedAttribute ParamArray;
 
1620
                public readonly PredefinedAttribute Out;
 
1621
 
 
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;
 
1655
 
 
1656
                // New in .NET 3.5
 
1657
                public readonly PredefinedAttribute Extension;
 
1658
 
 
1659
                // New in .NET 4.0
 
1660
                public readonly PredefinedDynamicAttribute Dynamic;
 
1661
 
 
1662
                // New in .NET 4.5
 
1663
                public readonly PredefinedStateMachineAttribute AsyncStateMachine;
 
1664
 
 
1665
                //
 
1666
                // Optional types which are used as types and for member lookup
 
1667
                //
 
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;
 
1675
 
 
1676
                public PredefinedAttributes (ModuleContainer module)
 
1677
                {
 
1678
                        ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
 
1679
                        Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
 
1680
                        ParamArray.Resolve ();
 
1681
                        Out.Resolve ();
 
1682
 
 
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");
 
1705
 
 
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");
 
1716
 
 
1717
                        Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
 
1718
 
 
1719
                        Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
 
1720
 
 
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");
 
1725
 
 
1726
                        AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
 
1727
 
 
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");
 
1731
 
 
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;
 
1735
 
 
1736
                        foreach (var fi in GetType ().GetFields (all_fields)) {
 
1737
                                ((PredefinedAttribute) fi.GetValue (this)).Define ();
 
1738
                        }
 
1739
                }
 
1740
        }
 
1741
 
 
1742
        public class PredefinedAttribute : PredefinedType
 
1743
        {
 
1744
                protected MethodSpec ctor;
 
1745
 
 
1746
                public PredefinedAttribute (ModuleContainer module, string ns, string name)
 
1747
                        : base (module, MemberKind.Class, ns, name)
 
1748
                {
 
1749
                }
 
1750
 
 
1751
                #region Properties
 
1752
 
 
1753
                public MethodSpec Constructor {
 
1754
                        get {
 
1755
                                return ctor;
 
1756
                        }
 
1757
                }
 
1758
 
 
1759
                #endregion
 
1760
 
 
1761
                public static bool operator == (TypeSpec type, PredefinedAttribute pa)
 
1762
                {
 
1763
                        return type == pa.type && pa.type != null;
 
1764
                }
 
1765
 
 
1766
                public static bool operator != (TypeSpec type, PredefinedAttribute pa)
 
1767
                {
 
1768
                        return type != pa.type;
 
1769
                }
 
1770
 
 
1771
                public override int GetHashCode ()
 
1772
                {
 
1773
                        return base.GetHashCode ();
 
1774
                }
 
1775
 
 
1776
                public override bool Equals (object obj)
 
1777
                {
 
1778
                        throw new NotSupportedException ();
 
1779
                }
 
1780
 
 
1781
                public void EmitAttribute (ConstructorBuilder builder)
 
1782
                {
 
1783
                        if (ResolveBuilder ())
 
1784
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1785
                }
 
1786
 
 
1787
                public void EmitAttribute (MethodBuilder builder)
 
1788
                {
 
1789
                        if (ResolveBuilder ())
 
1790
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1791
                }
 
1792
 
 
1793
                public void EmitAttribute (PropertyBuilder builder)
 
1794
                {
 
1795
                        if (ResolveBuilder ())
 
1796
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1797
                }
 
1798
 
 
1799
                public void EmitAttribute (FieldBuilder builder)
 
1800
                {
 
1801
                        if (ResolveBuilder ())
 
1802
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1803
                }
 
1804
 
 
1805
                public void EmitAttribute (TypeBuilder builder)
 
1806
                {
 
1807
                        if (ResolveBuilder ())
 
1808
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1809
                }
 
1810
 
 
1811
                public void EmitAttribute (AssemblyBuilder builder)
 
1812
                {
 
1813
                        if (ResolveBuilder ())
 
1814
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1815
                }
 
1816
 
 
1817
                public void EmitAttribute (ModuleBuilder builder)
 
1818
                {
 
1819
                        if (ResolveBuilder ())
 
1820
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1821
                }
 
1822
 
 
1823
                public void EmitAttribute (ParameterBuilder builder)
 
1824
                {
 
1825
                        if (ResolveBuilder ())
 
1826
                                builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
 
1827
                }
 
1828
 
 
1829
                ConstructorInfo GetCtorMetaInfo ()
 
1830
                {
 
1831
                        return (ConstructorInfo) ctor.GetMetaInfo ();
 
1832
                }
 
1833
 
 
1834
                public bool ResolveBuilder ()
 
1835
                {
 
1836
                        if (ctor != null)
 
1837
                                return true;
 
1838
 
 
1839
                        //
 
1840
                        // Handle all parameter-less attributes as optional
 
1841
                        //
 
1842
                        if (!IsDefined)
 
1843
                                return false;
 
1844
 
 
1845
                        ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
 
1846
                        return ctor != null;
 
1847
                }
 
1848
        }
 
1849
 
 
1850
        public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
 
1851
        {
 
1852
                public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
 
1853
                        : base (module, ns, name)
 
1854
                {
 
1855
                }
 
1856
 
 
1857
                public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
 
1858
                {
 
1859
                        var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
 
1860
                        if (ctor == null)
 
1861
                                return;
 
1862
 
 
1863
                        AttributeEncoder encoder = new AttributeEncoder ();
 
1864
                        encoder.Encode ((int) state);
 
1865
                        encoder.EncodeEmptyNamedArguments ();
 
1866
 
 
1867
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
1868
                }
 
1869
        }
 
1870
 
 
1871
        public class PredefinedDecimalAttribute : PredefinedAttribute
 
1872
        {
 
1873
                public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
 
1874
                        : base (module, ns, name)
 
1875
                {
 
1876
                }
 
1877
 
 
1878
                public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
 
1879
                {
 
1880
                        var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
 
1881
                        if (ctor == null)
 
1882
                                return;
 
1883
 
 
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 ();
 
1892
 
 
1893
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
1894
                }
 
1895
 
 
1896
                public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
 
1897
                {
 
1898
                        var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
 
1899
                        if (ctor == null)
 
1900
                                return;
 
1901
 
 
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 ();
 
1910
 
 
1911
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
1912
                }
 
1913
        }
 
1914
 
 
1915
        public class PredefinedStateMachineAttribute : PredefinedAttribute
 
1916
        {
 
1917
                public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
 
1918
                        : base (module, ns, name)
 
1919
                {
 
1920
                }
 
1921
 
 
1922
                public void EmitAttribute (MethodBuilder builder, StateMachine type)
 
1923
                {
 
1924
                        var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
 
1925
 
 
1926
                        var ctor = predefined_ctor.Get ();
 
1927
 
 
1928
                        if (ctor == null)
 
1929
                                return;
 
1930
 
 
1931
                        AttributeEncoder encoder = new AttributeEncoder ();
 
1932
                        encoder.EncodeTypeName (type);
 
1933
                        encoder.EncodeEmptyNamedArguments ();
 
1934
 
 
1935
                        builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
 
1936
                }
 
1937
        }
 
1938
 
 
1939
        public class PredefinedDynamicAttribute : PredefinedAttribute
 
1940
        {
 
1941
                MethodSpec tctor;
 
1942
 
 
1943
                public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
 
1944
                        : base (module, ns, name)
 
1945
                {
 
1946
                }
 
1947
 
 
1948
                public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
 
1949
                {
 
1950
                        if (ResolveTransformationCtor (loc)) {
 
1951
                                var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
 
1952
                                builder.SetCustomAttribute (cab);
 
1953
                        }
 
1954
                }
 
1955
 
 
1956
                public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
 
1957
                {
 
1958
                        if (ResolveTransformationCtor (loc)) {
 
1959
                                var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
 
1960
                                builder.SetCustomAttribute (cab);
 
1961
                        }
 
1962
                }
 
1963
 
 
1964
                public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
 
1965
                {
 
1966
                        if (ResolveTransformationCtor (loc)) {
 
1967
                                var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
 
1968
                                builder.SetCustomAttribute (cab);
 
1969
                        }
 
1970
                }
 
1971
 
 
1972
                public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
 
1973
                {
 
1974
                        if (ResolveTransformationCtor (loc)) {
 
1975
                                var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
 
1976
                                builder.SetCustomAttribute (cab);
 
1977
                        }
 
1978
                }
 
1979
 
 
1980
                //
 
1981
                // When any element of the type is a dynamic type
 
1982
                //
 
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.
 
1987
                //
 
1988
                // LAMESPEC: This should be part of C# specification
 
1989
                // 
 
1990
                // Example: Func<dynamic, int, dynamic[]>
 
1991
                // Transformation: { false, true, false, false, true }
 
1992
                //
 
1993
                static bool[] GetTransformationFlags (TypeSpec t)
 
1994
                {
 
1995
                        bool[] element;
 
1996
                        var ac = t as ArrayContainer;
 
1997
                        if (ac != null) {
 
1998
                                element = GetTransformationFlags (ac.Element);
 
1999
                                if (element == null)
 
2000
                                        return null;
 
2001
 
 
2002
                                bool[] res = new bool[element.Length + 1];
 
2003
                                res[0] = false;
 
2004
                                Array.Copy (element, 0, res, 1, element.Length);
 
2005
                                return res;
 
2006
                        }
 
2007
 
 
2008
                        if (t == null)
 
2009
                                return null;
 
2010
 
 
2011
                        if (t.IsGeneric) {
 
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);
 
2021
                                                }
 
2022
 
 
2023
                                                transform.AddRange (element);
 
2024
                                        } else if (transform != null) {
 
2025
                                                transform.Add (false);
 
2026
                                        }
 
2027
                                }
 
2028
 
 
2029
                                if (transform != null)
 
2030
                                        return transform.ToArray ();
 
2031
                        }
 
2032
 
 
2033
                        if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
 
2034
                                return new bool[] { true };
 
2035
 
 
2036
                        return null;
 
2037
                }
 
2038
 
 
2039
                bool ResolveTransformationCtor (Location loc)
 
2040
                {
 
2041
                        if (tctor != null)
 
2042
                                return true;
 
2043
 
 
2044
                        tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
 
2045
                        return tctor != null;
 
2046
                }
 
2047
        }
 
2048
}