Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.ExtLibs/HeuristicLab.NRefactory/5.5.0/NRefactory.CSharp-5.5.0/Parser/mcs/attribute.cs @ 15888

Last change on this file since 15888 was 11700, checked in by jkarder, 10 years ago

#2077: created branch and added first version

File size: 60.8 KB
Line 
1//
2// attribute.cs: Attributes handling
3//
4// Author: Ravi Pratap (ravi@ximian.com)
5//         Marek Safar (marek.safar@gmail.com)
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-2013 Xamarin Inc
12//
13
14using System;
15using System.Collections.Generic;
16using System.Runtime.InteropServices;
17using System.Runtime.CompilerServices;
18using System.Security;
19using System.Security.Permissions;
20using System.Text;
21using System.IO;
22
23#if STATIC
24using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
25using BadImageFormat = IKVM.Reflection.BadImageFormatException;
26using IKVM.Reflection;
27using IKVM.Reflection.Emit;
28#else
29using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
30using BadImageFormat = System.BadImageFormatException;
31using System.Reflection;
32using System.Reflection.Emit;
33#endif
34
35namespace 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    void Error_AttributeEmitError (string inner)
261    {
262      Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'",
263              Type.GetSignatureForError (), inner);
264    }
265
266    public void Error_InvalidArgumentValue (TypeSpec attributeType)
267    {
268      Report.Error (591, Location, "Invalid value for argument to `{0}' attribute", attributeType.GetSignatureForError ());
269    }
270
271    public void Error_InvalidSecurityParent ()
272    {
273      Report.Error (7070, Location,
274        "Security attribute `{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations",
275        Type.GetSignatureForError ());
276    }
277
278    Attributable Owner {
279      get {
280        return targets [0];
281      }
282    }
283
284    /// <summary>
285    ///   Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
286    /// </summary>
287    void ResolveAttributeType (bool comparisonOnly)
288    {
289      var resolve_printer = new SessionReportPrinter ();
290      SessionReportPrinter secondary_printer = null;
291      ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
292
293      bool t1_is_attr = false;
294      bool t2_is_attr = false;
295      TypeSpec t1, t2;
296      ATypeNameExpression expanded = null;
297
298      // TODO: Additional warnings such as CS0436 are swallowed because we don't
299      // print on success
300
301      try {
302        t1 = expression.ResolveAsType (context);
303        resolve_printer.EndSession ();
304
305        if (t1 != null && resolve_printer.ErrorsCount == 0)
306          t1_is_attr = t1.IsAttribute;
307
308        if (nameEscaped) {
309          t2 = null;
310        } else {
311          expanded = (ATypeNameExpression) expression.Clone (null);
312          expanded.Name += "Attribute";
313
314          secondary_printer = new SessionReportPrinter ();
315          Report.SetPrinter (secondary_printer);
316          t2 = expanded.ResolveAsType (context);
317          secondary_printer.EndSession ();
318          if (t2 != null && secondary_printer.ErrorsCount == 0)
319            t2_is_attr = t2.IsAttribute;
320
321          secondary_printer.EndSession ();
322        }
323      } finally {
324        context.Module.Compiler.Report.SetPrinter (prev_recorder);
325      }
326
327      if (t1_is_attr && t2_is_attr && t1 != t2) {
328        if (!comparisonOnly) {
329          Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
330            GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
331          resolve_error = true;
332        }
333
334        return;
335      }
336
337      if (t1_is_attr) {
338        Type = t1;
339        return;
340      }
341
342      if (t2_is_attr) {
343        Type = t2;
344        return;
345      }
346
347      if (comparisonOnly)
348        return;
349
350      resolve_error = true;
351
352      if (t1 != null) {
353        if (resolve_printer.IsEmpty) {
354          Report.SymbolRelatedToPreviousError (t1);
355          Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
356        } else {
357          resolve_printer.Merge (prev_recorder);
358        }
359
360        return;
361      }
362
363      if (t2 != null) {
364        if (secondary_printer.IsEmpty) {
365          Report.SymbolRelatedToPreviousError (t2);
366          Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
367        } else {
368          secondary_printer.Merge (prev_recorder);
369        }
370
371        return;
372      }
373
374      resolve_printer.Merge (prev_recorder);
375    }
376
377    public TypeSpec ResolveTypeForComparison ()
378    {
379      if (Type == null && !resolve_error)
380        ResolveAttributeType (true);
381      return Type;
382    }
383
384    public string GetSignatureForError ()
385    {
386      if (Type != null)
387        return Type.GetSignatureForError ();
388
389      return expression.GetSignatureForError ();
390    }
391
392    public bool HasSecurityAttribute {
393      get {
394        PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
395        return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
396      }
397    }
398
399    public bool IsValidSecurityAttribute ()
400    {
401      return HasSecurityAttribute && IsSecurityActionValid ();
402    }
403
404    static bool IsValidMethodImplOption (int value)
405    {
406      //
407      // Allow to use AggressiveInlining on any runtime/corlib
408      //
409      MethodImplOptions all = (MethodImplOptions) 256;
410      foreach (MethodImplOptions v in System.Enum.GetValues (typeof (MethodImplOptions))) {
411        all |= v;
412      }
413
414      return ((MethodImplOptions) value | all) == all;
415    }
416
417    public static bool IsValidArgumentType (TypeSpec t)
418    {
419      if (t.IsArray) {
420        var ac = (ArrayContainer) t;
421        if (ac.Rank > 1)
422          return false;
423
424        t = ac.Element;
425      }
426
427      switch (t.BuiltinType) {
428      case BuiltinTypeSpec.Type.Int:
429      case BuiltinTypeSpec.Type.UInt:
430      case BuiltinTypeSpec.Type.Long:
431      case BuiltinTypeSpec.Type.ULong:
432      case BuiltinTypeSpec.Type.Float:
433      case BuiltinTypeSpec.Type.Double:
434      case BuiltinTypeSpec.Type.Char:
435      case BuiltinTypeSpec.Type.Short:
436      case BuiltinTypeSpec.Type.Bool:
437      case BuiltinTypeSpec.Type.SByte:
438      case BuiltinTypeSpec.Type.Byte:
439      case BuiltinTypeSpec.Type.UShort:
440
441      case BuiltinTypeSpec.Type.String:
442      case BuiltinTypeSpec.Type.Object:
443      case BuiltinTypeSpec.Type.Dynamic:
444      case BuiltinTypeSpec.Type.Type:
445        return true;
446      }
447
448      return t.IsEnum;
449    }
450
451    // TODO: Don't use this ambiguous value
452    public string Name {
453      get { return expression.Name; }
454    }
455
456    public ATypeNameExpression TypeNameExpression {
457      get {
458        return expression;
459      }
460    }
461
462    public Report Report {
463      get { return context.Module.Compiler.Report; }
464    }
465
466    public MethodSpec Resolve ()
467    {
468      if (resolve_error)
469        return null;
470
471      resolve_error = true;
472      arg_resolved = true;
473
474      if (Type == null) {
475        ResolveAttributeType (false);
476        if (Type == null)
477          return null;
478      }
479
480      if (Type.IsAbstract) {
481        Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
482        return null;
483      }
484
485      ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
486      if (obsolete_attr != null) {
487        AttributeTester.Report_ObsoleteMessage (obsolete_attr, Type.GetSignatureForError (), Location, Report);
488      }
489
490      ResolveContext rc = null;
491
492      MethodSpec ctor;
493      // Try if the attribute is simple and has been resolved before
494      if (pos_args != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
495        rc = CreateResolveContext ();
496        ctor = ResolveConstructor (rc);
497        if (ctor == null) {
498          return null;
499        }
500
501        if (pos_args == null && ctor.Parameters.IsEmpty)
502          context.Module.AttributeConstructorCache.Add (Type, ctor);
503      }
504
505      //
506      // Add [module: DefaultCharSet] to all DllImport import attributes
507      //
508      var module = context.Module;
509      if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
510        if (rc == null)
511          rc = CreateResolveContext ();
512
513        AddModuleCharSet (rc);
514      }
515
516      if (NamedArguments != null) {
517        if (rc == null)
518          rc = CreateResolveContext ();
519
520        if (!ResolveNamedArguments (rc))
521          return null;
522      }
523
524      resolve_error = false;
525      return ctor;
526    }
527
528    MethodSpec ResolveConstructor (ResolveContext ec)
529    {
530      if (pos_args != null) {
531        bool dynamic;
532        pos_args.Resolve (ec, out dynamic);
533        if (dynamic) {
534          Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
535          return null;
536        }
537      }
538
539      return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
540    }
541
542    bool ResolveNamedArguments (ResolveContext ec)
543    {
544      int named_arg_count = NamedArguments.Count;
545      var seen_names = new List<string> (named_arg_count);
546
547      named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
548     
549      foreach (NamedArgument a in NamedArguments) {
550        string name = a.Name;
551        if (seen_names.Contains (name)) {
552          ec.Report.Error (643, a.Location, "Duplicate named attribute `{0}' argument", name);
553          continue;
554        }     
555 
556        seen_names.Add (name);
557
558        a.Resolve (ec);
559
560        Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
561
562        if (member == null) {
563          member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
564
565          if (member != null) {
566            // TODO: ec.Report.SymbolRelatedToPreviousError (member);
567            Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
568            return false;
569          }
570        }
571
572        if (member == null){
573          Expression.Error_TypeDoesNotContainDefinition (ec, Location, Type, name);
574          return false;
575        }
576       
577        if (!(member is PropertyExpr || member is FieldExpr)) {
578          Error_InvalidNamedArgument (ec, a);
579          return false;
580        }
581
582        ObsoleteAttribute obsolete_attr;
583
584        if (member is PropertyExpr) {
585          var pi = ((PropertyExpr) member).PropertyInfo;
586
587          if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
588            ec.Report.SymbolRelatedToPreviousError (pi);
589            Error_InvalidNamedArgument (ec, a);
590            return false;
591          }
592
593          if (!IsValidArgumentType (member.Type)) {
594            ec.Report.SymbolRelatedToPreviousError (pi);
595            Error_InvalidNamedArgumentType (ec, a);
596            return false;
597          }
598
599          obsolete_attr = pi.GetAttributeObsolete ();
600          pi.MemberDefinition.SetIsAssigned ();
601        } else {
602          var fi = ((FieldExpr) member).Spec;
603
604          if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
605            Error_InvalidNamedArgument (ec, a);
606            return false;
607          }
608
609          if (!IsValidArgumentType (member.Type)) {
610            ec.Report.SymbolRelatedToPreviousError (fi);
611            Error_InvalidNamedArgumentType (ec, a);
612            return false;
613          }
614
615          obsolete_attr = fi.GetAttributeObsolete ();
616          fi.MemberDefinition.SetIsAssigned ();
617        }
618
619        if (obsolete_attr != null && !context.IsObsolete)
620          AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
621
622        if (a.Type != member.Type) {
623          a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
624        }
625
626        if (a.Expr != null)
627          named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
628      }
629
630      return true;
631    }
632
633    /// <summary>
634    ///   Get a string containing a list of valid targets for the attribute 'attr'
635    /// </summary>
636    public string GetValidTargets ()
637    {
638      StringBuilder sb = new StringBuilder ();
639      AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
640
641      if ((targets & AttributeTargets.Assembly) != 0)
642        sb.Append ("assembly, ");
643
644      if ((targets & AttributeTargets.Module) != 0)
645        sb.Append ("module, ");
646
647      if ((targets & AttributeTargets.Class) != 0)
648        sb.Append ("class, ");
649
650      if ((targets & AttributeTargets.Struct) != 0)
651        sb.Append ("struct, ");
652
653      if ((targets & AttributeTargets.Enum) != 0)
654        sb.Append ("enum, ");
655
656      if ((targets & AttributeTargets.Constructor) != 0)
657        sb.Append ("constructor, ");
658
659      if ((targets & AttributeTargets.Method) != 0)
660        sb.Append ("method, ");
661
662      if ((targets & AttributeTargets.Property) != 0)
663        sb.Append ("property, indexer, ");
664
665      if ((targets & AttributeTargets.Field) != 0)
666        sb.Append ("field, ");
667
668      if ((targets & AttributeTargets.Event) != 0)
669        sb.Append ("event, ");
670
671      if ((targets & AttributeTargets.Interface) != 0)
672        sb.Append ("interface, ");
673
674      if ((targets & AttributeTargets.Parameter) != 0)
675        sb.Append ("parameter, ");
676
677      if ((targets & AttributeTargets.Delegate) != 0)
678        sb.Append ("delegate, ");
679
680      if ((targets & AttributeTargets.ReturnValue) != 0)
681        sb.Append ("return, ");
682
683      if ((targets & AttributeTargets.GenericParameter) != 0)
684        sb.Append ("type parameter, ");
685
686      return sb.Remove (sb.Length - 2, 2).ToString ();
687    }
688
689    public AttributeUsageAttribute GetAttributeUsageAttribute ()
690    {
691      if (!arg_resolved)
692        // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
693        // But because a lot of attribute class code must be rewritten will be better to wait...
694        Resolve ();
695
696      if (resolve_error)
697        return DefaultUsageAttribute;
698
699      AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
700
701      var field = GetNamedValue ("AllowMultiple") as BoolConstant;
702      if (field != null)
703        usage_attribute.AllowMultiple = field.Value;
704
705      field = GetNamedValue ("Inherited") as BoolConstant;
706      if (field != null)
707        usage_attribute.Inherited = field.Value;
708
709      return usage_attribute;
710    }
711
712    /// <summary>
713    /// Returns custom name of indexer
714    /// </summary>
715    public string GetIndexerAttributeValue ()
716    {
717      if (!arg_resolved)
718        // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
719        // But because a lot of attribute class code must be rewritten will be better to wait...
720        Resolve ();
721
722      if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
723        return null;
724
725      return ((Constant) pos_args[0].Expr).GetValue () as string;
726    }
727
728    /// <summary>
729    /// Returns condition of ConditionalAttribute
730    /// </summary>
731    public string GetConditionalAttributeValue ()
732    {
733      if (!arg_resolved)
734        // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
735        // But because a lot of attribute class code must be rewritten will be better to wait...
736        Resolve ();
737
738      if (resolve_error)
739        return null;
740
741      return ((Constant) pos_args[0].Expr).GetValue () as string;
742    }
743
744    /// <summary>
745    /// Creates the instance of ObsoleteAttribute from this attribute instance
746    /// </summary>
747    public ObsoleteAttribute GetObsoleteAttribute ()
748    {
749      if (!arg_resolved) {
750        // corlib only case when obsolete is used before is resolved
751        var c = Type.MemberDefinition as Class;
752        if (c != null && !c.HasMembersDefined)
753          c.Define ();
754       
755        // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
756        // But because a lot of attribute class code must be rewritten will be better to wait...
757        Resolve ();
758      }
759
760      if (resolve_error)
761        return null;
762
763      if (pos_args == null)
764        return new ObsoleteAttribute ();
765
766      string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
767      if (pos_args.Count == 1)
768        return new ObsoleteAttribute (msg);
769
770      return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
771    }
772
773    /// <summary>
774    /// Returns value of CLSCompliantAttribute contructor parameter but because the method can be called
775    /// before ApplyAttribute. We need to resolve the arguments.
776    /// This situation occurs when class deps is differs from Emit order. 
777    /// </summary>
778    public bool GetClsCompliantAttributeValue ()
779    {
780      if (!arg_resolved)
781        // TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
782        // But because a lot of attribute class code must be rewritten will be better to wait...
783        Resolve ();
784
785      if (resolve_error)
786        return false;
787
788      return ((BoolConstant) pos_args[0].Expr).Value;
789    }
790
791    public TypeSpec GetCoClassAttributeValue ()
792    {
793      if (!arg_resolved)
794        Resolve ();
795
796      if (resolve_error)
797        return null;
798
799      return GetArgumentType ();
800    }
801
802    public bool CheckTarget ()
803    {
804      string[] valid_targets = Owner.ValidAttributeTargets;
805      if (ExplicitTarget == null || ExplicitTarget == valid_targets [0]) {
806        Target = Owner.AttributeTargets;
807        return true;
808      }
809
810      // TODO: we can skip the first item
811      if (Array.Exists (valid_targets, i => i == ExplicitTarget)) {
812        switch (ExplicitTarget) {
813        case "return": Target = AttributeTargets.ReturnValue; return true;
814        case "param": Target = AttributeTargets.Parameter; return true;
815        case "field": Target = AttributeTargets.Field; return true;
816        case "method": Target = AttributeTargets.Method; return true;
817        case "property": Target = AttributeTargets.Property; return true;
818        case "module": Target = AttributeTargets.Module; return true;
819        }
820        throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
821      }
822       
823      StringBuilder sb = new StringBuilder ();
824      foreach (string s in valid_targets) {
825        sb.Append (s);
826        sb.Append (", ");
827      }
828      sb.Remove (sb.Length - 2, 2);
829      Report.Warning (657, 1, Location,
830        "`{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",
831        ExplicitTarget, sb.ToString ());
832      return false;
833    }
834
835    /// <summary>
836    /// Tests permitted SecurityAction for assembly or other types
837    /// </summary>
838    bool IsSecurityActionValid ()
839    {
840      SecurityAction action = GetSecurityActionValue ();
841      bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
842      var c = (Constant)pos_args [0].Expr;
843
844      switch (action) {
845#pragma warning disable 618
846      case SecurityAction.Demand:
847      case SecurityAction.Assert:
848      case SecurityAction.Deny:
849      case SecurityAction.PermitOnly:
850      case SecurityAction.LinkDemand:
851      case SecurityAction.InheritanceDemand:
852        if (!for_assembly)
853          return true;
854        break;
855
856      case SecurityAction.RequestMinimum:
857      case SecurityAction.RequestOptional:
858      case SecurityAction.RequestRefuse:
859        if (for_assembly)
860          return true;
861        break;
862#pragma warning restore 618
863
864      default:
865        Report.Error (7049, c.Location, "Security attribute `{0}' has an invalid SecurityAction value `{1}'",
866          Type.GetSignatureForError (), c.GetValueAsLiteral());
867        return false;
868      }
869
870      switch (Target) {
871      case AttributeTargets.Assembly:
872        Report.Error (7050, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to an assembly",
873          c.GetSignatureForError ());
874        break;
875      default:
876        Report.Error (7051, c.Location, "SecurityAction value `{0}' is invalid for security attributes applied to a type or a method",
877          c.GetSignatureForError ());
878        break;
879      }
880
881      return false;
882    }
883
884    System.Security.Permissions.SecurityAction GetSecurityActionValue ()
885    {
886      return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
887    }
888
889    /// <summary>
890    /// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
891    /// </summary>
892    /// <returns></returns>
893    public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
894    {
895#if STATIC
896      object[] values = new object[pos_args.Count];
897      for (int i = 0; i < values.Length; ++i)
898        values[i] = ((Constant) pos_args[i].Expr).GetValue ();
899
900      PropertyInfo[] prop;
901      object[] prop_values;
902      if (named_values == null) {
903        prop = null;
904        prop_values = null;
905      } else {
906        prop = new PropertyInfo[named_values.Count];
907        prop_values = new object [named_values.Count];
908        for (int i = 0; i < prop.Length; ++i) {
909          prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
910          prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
911        }
912      }
913
914      if (permissions == null)
915        permissions = new SecurityType ();
916
917      var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
918      permissions.Add (cab);
919#else
920      throw new NotSupportedException ();
921#endif
922    }
923
924    public Constant GetNamedValue (string name)
925    {
926      if (named_values == null)
927        return null;
928
929      for (int i = 0; i < named_values.Count; ++i) {
930        if (named_values [i].Value.Name == name)
931          return named_values [i].Value.Expr as Constant;
932      }
933
934      return null;
935    }
936
937    public CharSet GetCharSetValue ()
938    {
939      return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
940    }
941
942    public bool HasField (string fieldName)
943    {
944      if (named_values == null)
945        return false;
946
947      foreach (var na in named_values) {
948        if (na.Value.Name == fieldName)
949          return true;
950      }
951
952      return false;
953    }
954
955    //
956    // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
957    //
958    public bool IsInternalCall ()
959    {
960      return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
961    }
962
963    public MethodImplOptions GetMethodImplOptions ()
964    {
965      MethodImplOptions options = 0;
966      if (pos_args.Count == 1) {
967        options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
968      } else if (HasField ("Value")) {
969        var named = GetNamedValue ("Value");
970        options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
971      }
972
973      return options;
974    }
975
976    //
977    // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
978    //
979    public bool IsExplicitLayoutKind ()
980    {
981      if (pos_args == null || pos_args.Count != 1)
982        return false;
983
984      var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
985      return value == LayoutKind.Explicit;
986    }
987
988    public Expression GetParameterDefaultValue ()
989    {
990      if (pos_args == null)
991        return null;
992
993      return pos_args[0].Expr;
994    }
995
996    public override bool Equals (object obj)
997    {
998      Attribute a = obj as Attribute;
999      if (a == null)
1000        return false;
1001
1002      return Type == a.Type && Target == a.Target;
1003    }
1004
1005    public override int GetHashCode ()
1006    {
1007      return Type.GetHashCode () ^ Target.GetHashCode ();
1008    }
1009
1010    /// <summary>
1011    /// Emit attribute for Attributable symbol
1012    /// </summary>
1013    public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
1014    {
1015      var ctor = Resolve ();
1016      if (ctor == null)
1017        return;
1018
1019      var predefined = context.Module.PredefinedAttributes;
1020
1021      AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
1022      if ((usage_attr.ValidOn & Target) == 0) {
1023        Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
1024                "It is valid on `{1}' declarations only",
1025          GetSignatureForError (), GetValidTargets ());
1026        return;
1027      }
1028
1029      byte[] cdata;
1030      if (pos_args == null && named_values == null) {
1031        cdata = AttributeEncoder.Empty;
1032      } else {
1033        AttributeEncoder encoder = new AttributeEncoder ();
1034
1035        if (pos_args != null) {
1036          var param_types = ctor.Parameters.Types;
1037          for (int j = 0; j < pos_args.Count; ++j) {
1038            var pt = param_types[j];
1039            var arg_expr = pos_args[j].Expr;
1040            if (j == 0) {
1041              if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
1042                string v = ((Constant) arg_expr).GetValue () as string;
1043                if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
1044                  context.Module.Compiler.Report.Error (633, arg_expr.Location,
1045                    "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
1046                  return;
1047                }
1048              } else if (Type == predefined.Guid) {
1049                string v = ((StringConstant) arg_expr).Value;
1050                try {
1051                  new Guid (v);
1052                } catch {
1053                  Error_InvalidArgumentValue (Type);
1054                  return;
1055                }
1056              } else if (Type == predefined.AttributeUsage) {
1057                int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
1058                if (v == 0)
1059                  Error_InvalidArgumentValue (Type);
1060              } else if (Type == predefined.MarshalAs) {
1061                if (pos_args.Count == 1) {
1062                  var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
1063                  if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
1064                    Report.Error (7055, pos_args [0].Expr.Location, "Unmanaged type `ByValArray' is only valid for fields");
1065                  }
1066                }
1067              } else if (Type == predefined.DllImport) {
1068                if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
1069                  var value = ((Constant) pos_args[0].Expr).GetValue () as string;
1070                  if (string.IsNullOrEmpty (value))
1071                    Error_InvalidArgumentValue (Type);
1072                }
1073              } else if (Type == predefined.MethodImpl) {
1074                if (pos_args.Count == 1) {
1075                  var value = (int) ((Constant) arg_expr).GetValueAsLong ();
1076
1077                  if (!IsValidMethodImplOption (value)) {
1078                    Error_InvalidArgumentValue (Type);
1079                  }
1080                }
1081              }
1082            }
1083
1084            arg_expr.EncodeAttributeValue (context, encoder, pt, pt);
1085          }
1086        }
1087
1088        if (named_values != null) {
1089          encoder.Encode ((ushort) named_values.Count);
1090          foreach (var na in named_values) {
1091            if (na.Key is FieldExpr)
1092              encoder.Encode ((byte) 0x53);
1093            else
1094              encoder.Encode ((byte) 0x54);
1095
1096            encoder.Encode (na.Key.Type);
1097            encoder.Encode (na.Value.Name);
1098            na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type, na.Key.Type);
1099          }
1100        } else {
1101          encoder.EncodeEmptyNamedArguments ();
1102        }
1103
1104        cdata = encoder.ToArray ();
1105      }
1106
1107      if (!ctor.DeclaringType.IsConditionallyExcluded (context)) {
1108        try {
1109          foreach (Attributable target in targets)
1110            target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
1111        } catch (Exception e) {
1112          if (e is BadImageFormat && Report.Errors > 0)
1113            return;
1114
1115          Error_AttributeEmitError (e.Message);
1116          return;
1117        }
1118      }
1119
1120      if (!usage_attr.AllowMultiple && allEmitted != null) {
1121        if (allEmitted.ContainsKey (this)) {
1122          var a = allEmitted [this];
1123          if (a == null) {
1124            a = new List<Attribute> (2);
1125            allEmitted [this] = a;
1126          }
1127          a.Add (this);
1128        } else {
1129          allEmitted.Add (this, null);
1130        }
1131      }
1132
1133      if (!context.Module.Compiler.Settings.VerifyClsCompliance)
1134        return;
1135
1136      // Here we are testing attribute arguments for array usage (error 3016)
1137      if (Owner.IsClsComplianceRequired ()) {
1138        if (pos_args != null)
1139          pos_args.CheckArrayAsAttribute (context.Module.Compiler);
1140     
1141        if (NamedArguments == null)
1142          return;
1143
1144        NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
1145      }
1146    }
1147
1148    private Expression GetValue ()
1149    {
1150      if (pos_args == null || pos_args.Count < 1)
1151        return null;
1152
1153      return pos_args[0].Expr;
1154    }
1155
1156    public string GetString ()
1157    {
1158      Expression e = GetValue ();
1159      if (e is StringConstant)
1160        return ((StringConstant)e).Value;
1161      return null;
1162    }
1163
1164    public bool GetBoolean ()
1165    {
1166      Expression e = GetValue ();
1167      if (e is BoolConstant)
1168        return ((BoolConstant)e).Value;
1169      return false;
1170    }
1171
1172    public TypeSpec GetArgumentType ()
1173    {
1174      TypeOf e = GetValue () as TypeOf;
1175      if (e == null)
1176        return null;
1177      return e.TypeArgument;
1178    }
1179  }
1180 
1181  public class Attributes
1182  {
1183    public readonly List<Attribute> Attrs;
1184#if FULL_AST
1185    public readonly List<List<Attribute>> Sections = new List<List<Attribute>> ();
1186#endif
1187
1188    public Attributes (Attribute a)
1189    {
1190      Attrs = new List<Attribute> ();
1191      Attrs.Add (a);
1192     
1193#if FULL_AST
1194      Sections.Add (Attrs);
1195#endif
1196    }
1197
1198    public Attributes (List<Attribute> attrs)
1199    {
1200      Attrs = attrs ?? new List<Attribute> ();
1201#if FULL_AST
1202      Sections.Add (attrs);
1203#endif
1204    }
1205
1206    public void AddAttribute (Attribute attr)
1207    {
1208      Attrs.Add (attr);
1209    }
1210
1211    public void AddAttributes (List<Attribute> attrs)
1212    {
1213#if FULL_AST
1214      Sections.Add (attrs);
1215#else
1216      Attrs.AddRange (attrs);
1217#endif
1218    }
1219
1220    public void AttachTo (Attributable attributable, IMemberContext context)
1221    {
1222      foreach (Attribute a in Attrs)
1223        a.AttachTo (attributable, context);
1224    }
1225
1226    public Attributes Clone ()
1227    {
1228      var al = new List<Attribute> (Attrs.Count);
1229      foreach (Attribute a in Attrs)
1230        al.Add (a.Clone ());
1231
1232      return new Attributes (al);
1233    }
1234
1235    /// <summary>
1236    /// Checks whether attribute target is valid for the current element
1237    /// </summary>
1238    public bool CheckTargets ()
1239    {
1240      for (int i = 0; i < Attrs.Count; ++i) {
1241        if (!Attrs [i].CheckTarget ())
1242          Attrs.RemoveAt (i--);
1243      }
1244
1245      return true;
1246    }
1247
1248    public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
1249    {
1250      var member_explicit_targets = member.ValidAttributeTargets;
1251      for (int i = 0; i < Attrs.Count; ++i) {
1252        var attr = Attrs[0];
1253        if (attr.ExplicitTarget == null)
1254          continue;
1255
1256        int ii;
1257        for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
1258          if (attr.ExplicitTarget == member_explicit_targets[ii]) {
1259            ii = -1;
1260            break;
1261          }
1262        }
1263
1264        if (ii < 0 || !isGlobal)
1265          continue;
1266
1267        member.Module.AddAttribute (attr, currentNamespace);
1268        Attrs.RemoveAt (i);
1269        --i;
1270      }
1271    }
1272
1273    public bool HasResolveError()
1274    {
1275      foreach (var a in Attrs) {
1276        if (a.ResolveError)
1277          return true;
1278      }
1279
1280      return false;
1281    }
1282
1283    public Attribute Search (PredefinedAttribute t)
1284    {
1285      return Search (null, t);
1286    }
1287
1288    public Attribute Search (string explicitTarget, PredefinedAttribute t)
1289    {
1290      foreach (Attribute a in Attrs) {
1291        if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
1292          continue;
1293
1294        if (a.ResolveTypeForComparison () == t)
1295          return a;
1296      }
1297      return null;
1298    }
1299
1300    /// <summary>
1301    /// Returns all attributes of type 't'. Use it when attribute is AllowMultiple = true
1302    /// </summary>
1303    public Attribute[] SearchMulti (PredefinedAttribute t)
1304    {
1305      List<Attribute> ar = null;
1306
1307      foreach (Attribute a in Attrs) {
1308        if (a.ResolveTypeForComparison () == t) {
1309          if (ar == null)
1310            ar = new List<Attribute> (Attrs.Count);
1311          ar.Add (a);
1312        }
1313      }
1314
1315      return ar == null ? null : ar.ToArray ();
1316    }
1317
1318    public void Emit ()
1319    {
1320      CheckTargets ();
1321
1322      Dictionary<Attribute, List<Attribute>> ld = Attrs.Count > 1 ? new Dictionary<Attribute, List<Attribute>> () : null;
1323
1324      foreach (Attribute a in Attrs)
1325        a.Emit (ld);
1326
1327      if (ld == null || ld.Count == 0)
1328        return;
1329
1330      foreach (var d in ld) {
1331        if (d.Value == null)
1332          continue;
1333
1334        Attribute a = d.Key;
1335
1336        foreach (Attribute collision in d.Value)
1337          a.Report.SymbolRelatedToPreviousError (collision.Location, "");
1338
1339        a.Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times",
1340          a.GetSignatureForError ());
1341      }
1342    }
1343
1344    public bool Contains (PredefinedAttribute t)
1345    {
1346      return Search (t) != null;
1347    }
1348  }
1349
1350  public sealed class AttributeEncoder
1351  {
1352    [Flags]
1353    public enum EncodedTypeProperties
1354    {
1355      None = 0,
1356      DynamicType = 1,
1357      TypeParameter = 1 << 1
1358    }
1359
1360    public static readonly byte[] Empty;
1361
1362    byte[] buffer;
1363    int pos;
1364    const ushort Version = 1;
1365
1366    static AttributeEncoder ()
1367    {
1368      Empty = new byte[4];
1369      Empty[0] = (byte) Version;
1370    }
1371
1372    public AttributeEncoder ()
1373    {
1374      buffer = new byte[32];
1375      Encode (Version);
1376    }
1377
1378    public void Encode (bool value)
1379    {
1380      Encode (value ? (byte) 1 : (byte) 0);
1381    }
1382
1383    public void Encode (byte value)
1384    {
1385      if (pos == buffer.Length)
1386        Grow (1);
1387
1388      buffer [pos++] = value;
1389    }
1390
1391    public void Encode (sbyte value)
1392    {
1393      Encode ((byte) value);
1394    }
1395
1396    public void Encode (short value)
1397    {
1398      if (pos + 2 > buffer.Length)
1399        Grow (2);
1400
1401      buffer[pos++] = (byte) value;
1402      buffer[pos++] = (byte) (value >> 8);
1403    }
1404
1405    public void Encode (ushort value)
1406    {
1407      Encode ((short) value);
1408    }
1409
1410    public void Encode (int value)
1411    {
1412      if (pos + 4 > buffer.Length)
1413        Grow (4);
1414
1415      buffer[pos++] = (byte) value;
1416      buffer[pos++] = (byte) (value >> 8);
1417      buffer[pos++] = (byte) (value >> 16);
1418      buffer[pos++] = (byte) (value >> 24);
1419    }
1420
1421    public void Encode (uint value)
1422    {
1423      Encode ((int) value);
1424    }
1425
1426    public void Encode (long value)
1427    {
1428      if (pos + 8 > buffer.Length)
1429        Grow (8);
1430
1431      buffer[pos++] = (byte) value;
1432      buffer[pos++] = (byte) (value >> 8);
1433      buffer[pos++] = (byte) (value >> 16);
1434      buffer[pos++] = (byte) (value >> 24);
1435      buffer[pos++] = (byte) (value >> 32);
1436      buffer[pos++] = (byte) (value >> 40);
1437      buffer[pos++] = (byte) (value >> 48);
1438      buffer[pos++] = (byte) (value >> 56);
1439    }
1440
1441    public void Encode (ulong value)
1442    {
1443      Encode ((long) value);
1444    }
1445
1446    public void Encode (float value)
1447    {
1448      Encode (SingleConverter.SingleToInt32Bits (value));
1449    }
1450
1451    public void Encode (double value)
1452    {
1453      Encode (BitConverter.DoubleToInt64Bits (value));
1454    }
1455
1456    public void Encode (string value)
1457    {
1458      if (value == null) {
1459        Encode ((byte) 0xFF);
1460        return;
1461      }
1462
1463      var buf = Encoding.UTF8.GetBytes(value);
1464      WriteCompressedValue (buf.Length);
1465
1466      if (pos + buf.Length > buffer.Length)
1467        Grow (buf.Length);
1468
1469      Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
1470      pos += buf.Length;
1471    }
1472
1473    public EncodedTypeProperties Encode (TypeSpec type)
1474    {
1475      switch (type.BuiltinType) {
1476      case BuiltinTypeSpec.Type.Bool:
1477        Encode ((byte) 0x02);
1478        break;
1479      case BuiltinTypeSpec.Type.Char:
1480        Encode ((byte) 0x03);
1481        break;
1482      case BuiltinTypeSpec.Type.SByte:
1483        Encode ((byte) 0x04);
1484        break;
1485      case BuiltinTypeSpec.Type.Byte:
1486        Encode ((byte) 0x05);
1487        break;
1488      case BuiltinTypeSpec.Type.Short:
1489        Encode ((byte) 0x06);
1490        break;
1491      case BuiltinTypeSpec.Type.UShort:
1492        Encode ((byte) 0x07);
1493        break;
1494      case BuiltinTypeSpec.Type.Int:
1495        Encode ((byte) 0x08);
1496        break;
1497      case BuiltinTypeSpec.Type.UInt:
1498        Encode ((byte) 0x09);
1499        break;
1500      case BuiltinTypeSpec.Type.Long:
1501        Encode ((byte) 0x0A);
1502        break;
1503      case BuiltinTypeSpec.Type.ULong:
1504        Encode ((byte) 0x0B);
1505        break;
1506      case BuiltinTypeSpec.Type.Float:
1507        Encode ((byte) 0x0C);
1508        break;
1509      case BuiltinTypeSpec.Type.Double:
1510        Encode ((byte) 0x0D);
1511        break;
1512      case BuiltinTypeSpec.Type.String:
1513        Encode ((byte) 0x0E);
1514        break;
1515      case BuiltinTypeSpec.Type.Type:
1516        Encode ((byte) 0x50);
1517        break;
1518      case BuiltinTypeSpec.Type.Object:
1519        Encode ((byte) 0x51);
1520        break;
1521      case BuiltinTypeSpec.Type.Dynamic:
1522        Encode ((byte) 0x51);
1523        return EncodedTypeProperties.DynamicType;
1524      default:
1525        if (type.IsArray) {
1526          Encode ((byte) 0x1D);
1527          return Encode (TypeManager.GetElementType (type));
1528        }
1529
1530        if (type.Kind == MemberKind.Enum) {
1531          Encode ((byte) 0x55);
1532          EncodeTypeName (type);
1533        }
1534
1535        break;
1536      }
1537
1538      return EncodedTypeProperties.None;
1539    }
1540
1541    public void EncodeTypeName (TypeSpec type)
1542    {
1543      var old_type = type.GetMetaInfo ();
1544      Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
1545    }
1546
1547    public void EncodeTypeName (TypeContainer type)
1548    {
1549      Encode (type.GetSignatureForMetadata ());
1550    }
1551
1552
1553    //
1554    // Encodes single property named argument per call
1555    //
1556    public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
1557    {
1558      Encode ((ushort) 1);  // length
1559      Encode ((byte) 0x54); // property
1560      Encode (property.MemberType);
1561      Encode (property.Name);
1562      value.EncodeAttributeValue (null, this, property.MemberType, property.MemberType);
1563    }
1564
1565    //
1566    // Encodes single field named argument per call
1567    //
1568    public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
1569    {
1570      Encode ((ushort) 1);  // length
1571      Encode ((byte) 0x53); // field
1572      Encode (field.MemberType);
1573      Encode (field.Name);
1574      value.EncodeAttributeValue (null, this, field.MemberType, field.MemberType);
1575    }
1576
1577    public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
1578    {
1579      Encode ((ushort) members.Length);
1580
1581      for (int i = 0; i < members.Length; ++i)
1582      {
1583        var member = members[i];
1584
1585        if (member.Kind == MemberKind.Field)
1586          Encode ((byte) 0x53);
1587        else if (member.Kind == MemberKind.Property)
1588          Encode ((byte) 0x54);
1589        else
1590          throw new NotImplementedException (member.Kind.ToString ());
1591
1592        Encode (member.MemberType);
1593        Encode (member.Name);
1594        values [i].EncodeAttributeValue (null, this, member.MemberType, member.MemberType);
1595      }
1596    }
1597
1598    public void EncodeEmptyNamedArguments ()
1599    {
1600      Encode ((ushort) 0);
1601    }
1602
1603    void Grow (int inc)
1604    {
1605      int size = System.Math.Max (pos * 4, pos + inc + 2);
1606      Array.Resize (ref buffer, size);
1607    }
1608
1609    void WriteCompressedValue (int value)
1610    {
1611      if (value < 0x80) {
1612        Encode ((byte) value);
1613        return;
1614      }
1615
1616      if (value < 0x4000) {
1617        Encode ((byte) (0x80 | (value >> 8)));
1618        Encode ((byte) value);
1619        return;
1620      }
1621
1622      Encode (value);
1623    }
1624
1625    public byte[] ToArray ()
1626    {
1627      byte[] buf = new byte[pos];
1628      Array.Copy (buffer, buf, pos);
1629      return buf;
1630    }
1631  }
1632
1633
1634  /// <summary>
1635  /// Helper class for attribute verification routine.
1636  /// </summary>
1637  static class AttributeTester
1638  {
1639    /// <summary>
1640    /// Common method for Obsolete error/warning reporting.
1641    /// </summary>
1642    public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
1643    {
1644      if (oa.IsError) {
1645        Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1646        return;
1647      }
1648
1649      if (oa.Message == null || oa.Message.Length == 0) {
1650        Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
1651        return;
1652      }
1653      Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
1654    }
1655  }
1656
1657  //
1658  // Predefined attribute types
1659  //
1660  public class PredefinedAttributes
1661  {
1662    // Build-in attributes
1663    public readonly PredefinedAttribute ParamArray;
1664    public readonly PredefinedAttribute Out;
1665
1666    // Optional attributes
1667    public readonly PredefinedAttribute Obsolete;
1668    public readonly PredefinedAttribute DllImport;
1669    public readonly PredefinedAttribute MethodImpl;
1670    public readonly PredefinedAttribute MarshalAs;
1671    public readonly PredefinedAttribute In;
1672    public readonly PredefinedAttribute IndexerName;
1673    public readonly PredefinedAttribute Conditional;
1674    public readonly PredefinedAttribute CLSCompliant;
1675    public readonly PredefinedAttribute Security;
1676    public readonly PredefinedAttribute Required;
1677    public readonly PredefinedAttribute Guid;
1678    public readonly PredefinedAttribute AssemblyCulture;
1679    public readonly PredefinedAttribute AssemblyVersion;
1680    public readonly PredefinedAttribute AssemblyAlgorithmId;
1681    public readonly PredefinedAttribute AssemblyFlags;
1682    public readonly PredefinedAttribute AssemblyFileVersion;
1683    public readonly PredefinedAttribute ComImport;
1684    public readonly PredefinedAttribute CoClass;
1685    public readonly PredefinedAttribute AttributeUsage;
1686    public readonly PredefinedAttribute DefaultParameterValue;
1687    public readonly PredefinedAttribute OptionalParameter;
1688    public readonly PredefinedAttribute UnverifiableCode;
1689    public readonly PredefinedAttribute DefaultCharset;
1690    public readonly PredefinedAttribute TypeForwarder;
1691    public readonly PredefinedAttribute FixedBuffer;
1692    public readonly PredefinedAttribute CompilerGenerated;
1693    public readonly PredefinedAttribute InternalsVisibleTo;
1694    public readonly PredefinedAttribute RuntimeCompatibility;
1695    public readonly PredefinedAttribute DebuggerHidden;
1696    public readonly PredefinedAttribute UnsafeValueType;
1697    public readonly PredefinedAttribute UnmanagedFunctionPointer;
1698    public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
1699    public readonly PredefinedAttribute DebuggerStepThrough;
1700    public readonly PredefinedDebuggableAttribute Debuggable;
1701
1702    // New in .NET 3.5
1703    public readonly PredefinedAttribute Extension;
1704
1705    // New in .NET 4.0
1706    public readonly PredefinedDynamicAttribute Dynamic;
1707
1708    // New in .NET 4.5
1709    public readonly PredefinedStateMachineAttribute AsyncStateMachine;
1710
1711    //
1712    // Optional types which are used as types and for member lookup
1713    //
1714    public readonly PredefinedAttribute DefaultMember;
1715    public readonly PredefinedDecimalAttribute DecimalConstant;
1716    public readonly PredefinedAttribute StructLayout;
1717    public readonly PredefinedAttribute FieldOffset;
1718    public readonly PredefinedAttribute AssemblyProduct;
1719    public readonly PredefinedAttribute AssemblyCompany;
1720    public readonly PredefinedAttribute AssemblyDescription;
1721    public readonly PredefinedAttribute AssemblyCopyright;
1722    public readonly PredefinedAttribute AssemblyTrademark;
1723    public readonly PredefinedAttribute CallerMemberNameAttribute;
1724    public readonly PredefinedAttribute CallerLineNumberAttribute;
1725    public readonly PredefinedAttribute CallerFilePathAttribute;
1726
1727    public PredefinedAttributes (ModuleContainer module)
1728    {
1729      ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
1730      Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
1731      ParamArray.Resolve ();
1732      Out.Resolve ();
1733
1734      Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
1735      DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
1736      MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
1737      MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
1738      In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
1739      IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
1740      Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
1741      CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
1742      Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
1743      Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
1744      Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
1745      AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
1746      AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
1747      AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
1748      AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
1749      AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
1750      ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
1751      CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
1752      AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
1753      DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
1754      OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
1755      UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
1756
1757      DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
1758      TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
1759      FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
1760      CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
1761      InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
1762      RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
1763      DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
1764      UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
1765      UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
1766      DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
1767      DebuggerStepThrough = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerStepThroughAttribute");
1768      Debuggable = new PredefinedDebuggableAttribute (module, "System.Diagnostics", "DebuggableAttribute");
1769
1770      Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
1771
1772      Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
1773
1774      DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
1775      DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
1776      StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
1777      FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
1778      AssemblyProduct = new PredefinedAttribute (module, "System.Reflection", "AssemblyProductAttribute");
1779      AssemblyCompany = new PredefinedAttribute (module, "System.Reflection", "AssemblyCompanyAttribute");
1780      AssemblyDescription = new PredefinedAttribute (module, "System.Reflection", "AssemblyDescriptionAttribute");
1781      AssemblyCopyright = new PredefinedAttribute (module, "System.Reflection", "AssemblyCopyrightAttribute");
1782      AssemblyTrademark = new PredefinedAttribute (module, "System.Reflection", "AssemblyTrademarkAttribute");
1783
1784      AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
1785
1786      CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
1787      CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
1788      CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
1789
1790      // TODO: Should define only attributes which are used for comparison
1791      const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
1792        System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
1793
1794      foreach (var fi in GetType ().GetFields (all_fields)) {
1795        ((PredefinedAttribute) fi.GetValue (this)).Define ();
1796      }
1797    }
1798  }
1799
1800  public class PredefinedAttribute : PredefinedType
1801  {
1802    protected MethodSpec ctor;
1803
1804    public PredefinedAttribute (ModuleContainer module, string ns, string name)
1805      : base (module, MemberKind.Class, ns, name)
1806    {
1807    }
1808
1809    #region Properties
1810
1811    public MethodSpec Constructor {
1812      get {
1813        return ctor;
1814      }
1815    }
1816
1817    #endregion
1818
1819    public static bool operator == (TypeSpec type, PredefinedAttribute pa)
1820    {
1821      return type == pa.type && pa.type != null;
1822    }
1823
1824    public static bool operator != (TypeSpec type, PredefinedAttribute pa)
1825    {
1826      return type != pa.type;
1827    }
1828
1829    public override int GetHashCode ()
1830    {
1831      return base.GetHashCode ();
1832    }
1833
1834    public override bool Equals (object obj)
1835    {
1836      throw new NotSupportedException ();
1837    }
1838
1839    public void EmitAttribute (ConstructorBuilder builder)
1840    {
1841      if (ResolveBuilder ())
1842        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1843    }
1844
1845    public void EmitAttribute (MethodBuilder builder)
1846    {
1847      if (ResolveBuilder ())
1848        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1849    }
1850
1851    public void EmitAttribute (PropertyBuilder builder)
1852    {
1853      if (ResolveBuilder ())
1854        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1855    }
1856
1857    public void EmitAttribute (FieldBuilder builder)
1858    {
1859      if (ResolveBuilder ())
1860        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1861    }
1862
1863    public void EmitAttribute (TypeBuilder builder)
1864    {
1865      if (ResolveBuilder ())
1866        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1867    }
1868
1869    public void EmitAttribute (AssemblyBuilder builder)
1870    {
1871      if (ResolveBuilder ())
1872        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1873    }
1874
1875    public void EmitAttribute (ModuleBuilder builder)
1876    {
1877      if (ResolveBuilder ())
1878        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1879    }
1880
1881    public void EmitAttribute (ParameterBuilder builder)
1882    {
1883      if (ResolveBuilder ())
1884        builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
1885    }
1886
1887    ConstructorInfo GetCtorMetaInfo ()
1888    {
1889      return (ConstructorInfo) ctor.GetMetaInfo ();
1890    }
1891
1892    public bool ResolveBuilder ()
1893    {
1894      if (ctor != null)
1895        return true;
1896
1897      //
1898      // Handle all parameter-less attributes as optional
1899      //
1900      if (!Define ())
1901        return false;
1902
1903      ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
1904      return ctor != null;
1905    }
1906  }
1907
1908  public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
1909  {
1910    public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
1911      : base (module, ns, name)
1912    {
1913    }
1914
1915    public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
1916    {
1917      var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
1918      if (ctor == null)
1919        return;
1920
1921      AttributeEncoder encoder = new AttributeEncoder ();
1922      encoder.Encode ((int) state);
1923      encoder.EncodeEmptyNamedArguments ();
1924
1925      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1926    }
1927  }
1928
1929  public class PredefinedDebuggableAttribute : PredefinedAttribute
1930  {
1931    public PredefinedDebuggableAttribute (ModuleContainer module, string ns, string name)
1932      : base (module, ns, name)
1933    {
1934    }
1935
1936    public void EmitAttribute (AssemblyBuilder builder, System.Diagnostics.DebuggableAttribute.DebuggingModes modes)
1937    {
1938      var atype = module.PredefinedAttributes.Debuggable;
1939      if (!atype.Define ())
1940        return;
1941
1942      MethodSpec ctor = null;
1943      foreach (MethodSpec m in MemberCache.FindMembers (atype.TypeSpec, CSharp.Constructor.ConstructorName, true)) {
1944        if (m.Parameters.Count != 1)
1945          continue;
1946
1947        if (m.Parameters.Types[0].Kind == MemberKind.Enum) {
1948          ctor = m;
1949        }
1950      }
1951
1952      if (ctor == null)
1953        return;
1954
1955      AttributeEncoder encoder = new AttributeEncoder ();
1956      encoder.Encode ((int) modes);
1957      encoder.EncodeEmptyNamedArguments ();
1958
1959      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1960    }
1961  }
1962
1963  public class PredefinedDecimalAttribute : PredefinedAttribute
1964  {
1965    public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
1966      : base (module, ns, name)
1967    {
1968    }
1969
1970    public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
1971    {
1972      var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1973      if (ctor == null)
1974        return;
1975
1976      int[] bits = decimal.GetBits (value);
1977      AttributeEncoder encoder = new AttributeEncoder ();
1978      encoder.Encode ((byte) (bits[3] >> 16));
1979      encoder.Encode ((byte) (bits[3] >> 31));
1980      encoder.Encode ((uint) bits[2]);
1981      encoder.Encode ((uint) bits[1]);
1982      encoder.Encode ((uint) bits[0]);
1983      encoder.EncodeEmptyNamedArguments ();
1984
1985      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
1986    }
1987
1988    public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
1989    {
1990      var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
1991      if (ctor == null)
1992        return;
1993
1994      int[] bits = decimal.GetBits (value);
1995      AttributeEncoder encoder = new AttributeEncoder ();
1996      encoder.Encode ((byte) (bits[3] >> 16));
1997      encoder.Encode ((byte) (bits[3] >> 31));
1998      encoder.Encode ((uint) bits[2]);
1999      encoder.Encode ((uint) bits[1]);
2000      encoder.Encode ((uint) bits[0]);
2001      encoder.EncodeEmptyNamedArguments ();
2002
2003      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2004    }
2005  }
2006
2007  public class PredefinedStateMachineAttribute : PredefinedAttribute
2008  {
2009    public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
2010      : base (module, ns, name)
2011    {
2012    }
2013
2014    public void EmitAttribute (MethodBuilder builder, StateMachine type)
2015    {
2016      var predefined_ctor = module.PredefinedMembers.AsyncStateMachineAttributeCtor;
2017
2018      var ctor = predefined_ctor.Get ();
2019
2020      if (ctor == null)
2021        return;
2022
2023      AttributeEncoder encoder = new AttributeEncoder ();
2024      encoder.EncodeTypeName (type);
2025      encoder.EncodeEmptyNamedArguments ();
2026
2027      builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
2028    }
2029  }
2030
2031  public class PredefinedDynamicAttribute : PredefinedAttribute
2032  {
2033    MethodSpec tctor;
2034
2035    public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
2036      : base (module, ns, name)
2037    {
2038    }
2039
2040    public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
2041    {
2042      if (ResolveTransformationCtor (loc)) {
2043        var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2044        builder.SetCustomAttribute (cab);
2045      }
2046    }
2047
2048    public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
2049    {
2050      if (ResolveTransformationCtor (loc)) {
2051        var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2052        builder.SetCustomAttribute (cab);
2053      }
2054    }
2055
2056    public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
2057    {
2058      if (ResolveTransformationCtor (loc)) {
2059        var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2060        builder.SetCustomAttribute (cab);
2061      }
2062    }
2063
2064    public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
2065    {
2066      if (ResolveTransformationCtor (loc)) {
2067        var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
2068        builder.SetCustomAttribute (cab);
2069      }
2070    }
2071
2072    //
2073    // When any element of the type is a dynamic type
2074    //
2075    // This method builds a transformation array for dynamic types
2076    // used in places where DynamicAttribute cannot be applied to.
2077    // It uses bool flag when type is of dynamic type and each
2078    // section always starts with "false" for some reason.
2079    //
2080    // LAMESPEC: This should be part of C# specification
2081    //
2082    // Example: Func<dynamic, int, dynamic[]>
2083    // Transformation: { false, true, false, false, true }
2084    //
2085    static bool[] GetTransformationFlags (TypeSpec t)
2086    {
2087      bool[] element;
2088      var ac = t as ArrayContainer;
2089      if (ac != null) {
2090        element = GetTransformationFlags (ac.Element);
2091        if (element == null)
2092          return new bool[] { false, false };
2093
2094        bool[] res = new bool[element.Length + 1];
2095        res[0] = false;
2096        Array.Copy (element, 0, res, 1, element.Length);
2097        return res;
2098      }
2099
2100      if (t == null)
2101        return null;
2102
2103      if (t.IsGeneric) {
2104        List<bool> transform = null;
2105        var targs = t.TypeArguments;
2106        for (int i = 0; i < targs.Length; ++i) {
2107          element = GetTransformationFlags (targs[i]);
2108          if (element != null) {
2109            if (transform == null) {
2110              transform = new List<bool> ();
2111              for (int ii = 0; ii <= i; ++ii)
2112                transform.Add (false);
2113            }
2114
2115            transform.AddRange (element);
2116          } else if (transform != null) {
2117            transform.Add (false);
2118          }
2119        }
2120
2121        if (transform != null)
2122          return transform.ToArray ();
2123      }
2124
2125      if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
2126        return new bool[] { true };
2127
2128      return null;
2129    }
2130
2131    bool ResolveTransformationCtor (Location loc)
2132    {
2133      if (tctor != null)
2134        return true;
2135
2136      tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
2137      return tctor != null;
2138    }
2139  }
2140}
Note: See TracBrowser for help on using the repository browser.