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 | |
---|
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 | 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 | } |
---|