//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
//
using System;
-using System.Diagnostics;
using System.Collections.Generic;
-using System.Reflection;
-using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Security;
using System.Text;
using System.IO;
+#if STATIC
+using SecurityType = System.Collections.Generic.List<IKVM.Reflection.Emit.CustomAttributeBuilder>;
+using BadImageFormat = IKVM.Reflection.BadImageFormatException;
+using IKVM.Reflection;
+using IKVM.Reflection.Emit;
+#else
+using SecurityType = System.Collections.Generic.Dictionary<System.Security.Permissions.SecurityAction, System.Security.PermissionSet>;
+using BadImageFormat = System.BadImageFormatException;
+using System.Reflection;
+using System.Reflection.Emit;
+#endif
+
namespace Mono.CSharp {
/// <summary>
if (attributes == null)
attributes = attrs;
else
- throw new NotImplementedException ();
+ attributes.AddAttributes (attrs.Attrs);
- attributes.AttachTo (this, context);
+ attrs.AttachTo (this, context);
}
public Attributes OptAttributes {
/// <summary>
/// Use member-specific procedure to apply attribute @a in @cb to the entity being built in @builder
/// </summary>
- public abstract void ApplyAttributeBuilder (Attribute a, CustomAttributeBuilder cb, PredefinedAttributes pa);
+ public abstract void ApplyAttributeBuilder (Attribute a, MethodSpec ctor, byte[] cdata, PredefinedAttributes pa);
/// <summary>
/// Returns one AttributeTarget for this element.
public abstract string[] ValidAttributeTargets { get; }
};
- public class Attribute : Expression
+ public class Attribute
{
public readonly string ExplicitTarget;
public AttributeTargets Target;
readonly ATypeNameExpression expression;
- Arguments PosArguments;
- Arguments NamedArguments;
+ Arguments pos_args, named_args;
bool resolve_error;
+ bool arg_resolved;
readonly bool nameEscaped;
+ readonly Location loc;
+ public TypeSpec Type;
//
// An attribute can be attached to multiple targets (e.g. multiple fields)
//
- protected Attributable[] targets;
+ Attributable[] targets;
//
// A member context for the attribute, it's much easier to hold it here
//
IMemberContext context;
- static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
- static Assembly orig_sec_assembly;
+ public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
public static readonly object[] EmptyObject = new object [0];
- // non-null if named args present after Resolve () is called
- PropertyInfo [] prop_info_arr;
- FieldInfo [] field_info_arr;
- object [] field_values_arr;
- object [] prop_values_arr;
- object [] pos_values;
-
- static Dictionary<Type, AttributeUsageAttribute> usage_attr_cache;
- // Cache for parameter-less attributes
- static Dictionary<Type, CustomAttributeBuilder> att_cache;
+ List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
public Attribute (string target, ATypeNameExpression expr, Arguments[] args, Location loc, bool nameEscaped)
{
this.expression = expr;
if (args != null) {
- PosArguments = args [0];
- NamedArguments = args [1];
+ pos_args = args[0];
+ named_args = args[1];
}
this.loc = loc;
ExplicitTarget = target;
this.nameEscaped = nameEscaped;
}
- public Attribute Clone ()
- {
- Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
- a.PosArguments = PosArguments;
- a.NamedArguments = NamedArguments;
- return a;
+ public Location Location {
+ get {
+ return loc;
+ }
+ }
+
+ public Arguments NamedArguments {
+ get {
+ return named_args;
+ }
+ }
+
+ public Arguments PositionalArguments {
+ get {
+ return pos_args;
+ }
+ }
+
+ public ATypeNameExpression TypeExpression {
+ get {
+ return expression;
+ }
}
- static Attribute ()
+ void AddModuleCharSet (ResolveContext rc)
{
- Reset ();
+ const string dll_import_char_set = "CharSet";
+
+ //
+ // Only when not customized by user
+ //
+ if (HasField (dll_import_char_set))
+ return;
+
+ if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
+ return;
+ }
+
+ if (NamedArguments == null)
+ named_args = new Arguments (1);
+
+ var value = Constant.CreateConstant (rc.Module.PredefinedTypes.CharSet.TypeSpec, rc.Module.DefaultCharSet, Location);
+ NamedArguments.Add (new NamedArgument (dll_import_char_set, loc, value));
}
- public static void Reset ()
+ public Attribute Clone ()
{
- usage_attr_cache = new Dictionary<Type, AttributeUsageAttribute> (ReferenceEquality<Type>.Default);
- att_cache = new Dictionary<Type, CustomAttributeBuilder> (ReferenceEquality<Type>.Default);
+ Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
+ a.pos_args = pos_args;
+ a.named_args = NamedArguments;
+ return a;
}
//
// we use @target field as a list of targets. The attribute
// has to be resolved only once but emitted for each target.
//
- public virtual void AttachTo (Attributable target, IMemberContext context)
+ public void AttachTo (Attributable target, IMemberContext context)
{
if (this.targets == null) {
this.targets = new Attributable[] { target };
return;
}
+ // When re-attaching global attributes
+ if (context is NamespaceContainer) {
+ this.targets[0] = target;
+ this.context = context;
+ return;
+ }
+
// Resize target array
Attributable[] new_array = new Attributable [this.targets.Length + 1];
targets.CopyTo (new_array, 0);
target.OptAttributes = null;
}
+ public ResolveContext CreateResolveContext ()
+ {
+ return new ResolveContext (context, ResolveContext.Options.ConstantScope);
+ }
+
static void Error_InvalidNamedArgument (ResolveContext rc, NamedArgument name)
{
rc.Report.Error (617, name.Location, "`{0}' is not a valid named attribute argument. Named attribute arguments " +
name.Name);
}
- public static void Error_AttributeArgumentNotValid (ResolveContext rc, Location loc)
+ public static void Error_AttributeArgumentIsDynamic (IMemberContext context, Location loc)
{
- rc.Report.Error (182, loc,
- "An attribute argument must be a constant expression, typeof " +
- "expression or array creation expression");
+ context.Module.Compiler.Report.Error (1982, loc, "An attribute argument cannot be dynamic expression");
}
public void Error_MissingGuidAttribute ()
}
}
- protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
- {
- return expr.ResolveAsTypeTerminal (ec, false);
- }
-
- Type ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
- {
- TypeExpr te = ResolveAsTypeTerminal (expr, context);
- if (te == null)
- return null;
-
- Type t = te.Type;
- if (TypeManager.IsSubclassOf (t, TypeManager.attribute_type)) {
- is_attr = true;
- } else {
- Report.SymbolRelatedToPreviousError (t);
- Report.Error (616, Location, "`{0}': is not an attribute class", TypeManager.CSharpName (t));
- }
- return t;
- }
-
/// <summary>
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
/// </summary>
void ResolveAttributeType ()
{
SessionReportPrinter resolve_printer = new SessionReportPrinter ();
- ReportPrinter prev_recorder = context.Compiler.Report.SetPrinter (resolve_printer);
+ ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
bool t1_is_attr = false;
bool t2_is_attr = false;
- Type t1, t2;
+ TypeSpec t1, t2;
ATypeNameExpression expanded = null;
+ // TODO: Additional warnings such as CS0436 are swallowed because we don't
+ // print on success
+
try {
- t1 = ResolvePossibleAttributeType (expression, ref t1_is_attr);
+ t1 = expression.ResolveAsType (context);
+ if (t1 != null)
+ t1_is_attr = t1.IsAttribute;
+
+ resolve_printer.EndSession ();
if (nameEscaped) {
t2 = null;
expanded = (ATypeNameExpression) expression.Clone (null);
expanded.Name += "Attribute";
- t2 = ResolvePossibleAttributeType (expanded, ref t2_is_attr);
+ t2 = expanded.ResolveAsType (context);
+ if (t2 != null)
+ t2_is_attr = t2.IsAttribute;
}
-
- resolve_printer.EndSession ();
} finally {
- context.Compiler.Report.SetPrinter (prev_recorder);
+ context.Module.Compiler.Report.SetPrinter (prev_recorder);
}
- if (t1_is_attr && t2_is_attr) {
+ if (t1_is_attr && t2_is_attr && t1 != t2) {
Report.Error (1614, Location, "`{0}' is ambiguous between `{1}' and `{2}'. Use either `@{0}' or `{0}Attribute'",
GetSignatureForError (), expression.GetSignatureForError (), expanded.GetSignatureForError ());
resolve_error = true;
return;
}
- resolve_printer.Merge (prev_recorder);
resolve_error = true;
+
+ if (t1 != null) {
+ resolve_printer.Merge (prev_recorder);
+
+ Report.SymbolRelatedToPreviousError (t1);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t1.GetSignatureForError ());
+ return;
+ }
+
+ if (t2 != null) {
+ Report.SymbolRelatedToPreviousError (t2);
+ Report.Error (616, Location, "`{0}': is not an attribute class", t2.GetSignatureForError ());
+ return;
+ }
+
+ resolve_printer.Merge (prev_recorder);
}
- public virtual Type ResolveType ()
+ public TypeSpec ResolveType ()
{
if (Type == null && !resolve_error)
ResolveAttributeType ();
return Type;
}
- public override string GetSignatureForError ()
+ public string GetSignatureForError ()
{
if (Type != null)
return TypeManager.CSharpName (Type);
public bool HasSecurityAttribute {
get {
- PredefinedAttribute pa = PredefinedAttributes.Get.Security;
- return pa.IsDefined && TypeManager.IsSubclassOf (type, pa.Type);
+ PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
+ return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
}
}
public bool IsValidSecurityAttribute ()
{
- return HasSecurityAttribute && IsSecurityActionValid (false);
+ return HasSecurityAttribute && IsSecurityActionValid ();
}
- static bool IsValidArgumentType (Type t)
+ static bool IsValidArgumentType (TypeSpec t)
{
- if (t.IsArray)
- t = TypeManager.GetElementType (t);
+ if (t.IsArray) {
+ var ac = (ArrayContainer) t;
+ if (ac.Rank > 1)
+ return false;
+
+ t = ac.Element;
+ }
+
+ switch (t.BuiltinType) {
+ case BuiltinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.Float:
+ case BuiltinTypeSpec.Type.Double:
+ case BuiltinTypeSpec.Type.Char:
+ case BuiltinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.Bool:
+ case BuiltinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.UShort:
+
+ case BuiltinTypeSpec.Type.String:
+ case BuiltinTypeSpec.Type.Object:
+ case BuiltinTypeSpec.Type.Dynamic:
+ case BuiltinTypeSpec.Type.Type:
+ return true;
+ }
- return t == TypeManager.string_type ||
- TypeManager.IsPrimitiveType (t) ||
- TypeManager.IsEnumType (t) ||
- t == TypeManager.object_type ||
- t == TypeManager.type_type;
+ return t.IsEnum;
}
// TODO: Don't use this ambiguous value
get { return expression.Name; }
}
- void ApplyModuleCharSet (ResolveContext rc)
- {
- if (Type != PredefinedAttributes.Get.DllImport)
- return;
-
- if (!RootContext.ToplevelTypes.HasDefaultCharSet)
- return;
-
- const string CharSetEnumMember = "CharSet";
- if (NamedArguments == null) {
- NamedArguments = new Arguments (1);
- } else {
- foreach (NamedArgument a in NamedArguments) {
- if (a.Name == CharSetEnumMember)
- return;
- }
- }
-
- NamedArguments.Add (new NamedArgument (CharSetEnumMember, loc,
- Constant.CreateConstant (rc, typeof (CharSet), RootContext.ToplevelTypes.DefaultCharSet, Location)));
- }
-
public Report Report {
- get { return context.Compiler.Report; }
+ get { return context.Module.Compiler.Report; }
}
- public CustomAttributeBuilder Resolve ()
+ public MethodSpec Resolve ()
{
if (resolve_error)
return null;
resolve_error = true;
+ arg_resolved = true;
if (Type == null) {
ResolveAttributeType ();
return null;
}
- ObsoleteAttribute obsolete_attr = AttributeTester.GetObsoleteAttribute (Type);
+ ObsoleteAttribute obsolete_attr = Type.GetAttributeObsolete ();
if (obsolete_attr != null) {
AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
}
- CustomAttributeBuilder cb;
- if (PosArguments == null && NamedArguments == null) {
- if (att_cache.TryGetValue (Type, out cb)) {
- resolve_error = false;
- return cb;
- }
- }
-
- ResolveContext rc = new ResolveContext (context, ResolveContext.Options.ConstantScope);
- var ctor = ResolveConstructor (rc);
- if (ctor == null) {
- if (Type is TypeBuilder &&
- TypeManager.LookupDeclSpace (Type).MemberCache == null)
- // The attribute type has been DefineType'd, but not Defined. Let's not treat it as an error.
- // It'll be resolved again when the attached-to entity is emitted.
- resolve_error = false;
- return null;
- }
-
- ApplyModuleCharSet (rc);
-
- try {
- var ctor_meta = (ConstructorInfo) ctor.MetaInfo;
- // SRE does not allow private ctor but we want to report all source code errors
- if (ctor.MetaInfo.IsPrivate)
- return null;
-
- if (NamedArguments == null) {
- cb = new CustomAttributeBuilder (ctor_meta, pos_values);
-
- if (pos_values.Length == 0)
- att_cache.Add (Type, cb);
-
- resolve_error = false;
- return cb;
- }
+ ResolveContext rc = null;
- if (!ResolveNamedArguments (rc)) {
+ MethodSpec ctor;
+ // Try if the attribute is simple and has been resolved before
+ if (pos_args != null || !context.Module.AttributeConstructorCache.TryGetValue (Type, out ctor)) {
+ rc = CreateResolveContext ();
+ ctor = ResolveConstructor (rc);
+ if (ctor == null) {
return null;
}
- cb = new CustomAttributeBuilder (ctor_meta, pos_values,
- prop_info_arr, prop_values_arr,
- field_info_arr, field_values_arr);
-
- resolve_error = false;
- return cb;
- }
- catch (Exception) {
- Error_AttributeArgumentNotValid (rc, Location);
- return null;
- }
- }
-
- protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
- {
- if (PosArguments != null) {
- bool dynamic;
- PosArguments.Resolve (ec, out dynamic);
- if (dynamic) {
- Error_AttributeArgumentNotValid (ec, loc);
- return null;
- }
+ if (pos_args == null && ctor.Parameters.IsEmpty)
+ context.Module.AttributeConstructorCache.Add (Type, ctor);
}
- MethodGroupExpr mg = MemberLookupFinal (ec, ec.CurrentType,
- Type, ConstructorInfo.ConstructorName, MemberTypes.Constructor,
- BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
- Location) as MethodGroupExpr;
-
- if (mg == null)
- throw new NotImplementedException ();
+ //
+ // Add [module: DefaultCharSet] to all DllImport import attributes
+ //
+ var module = context.Module;
+ if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
+ if (rc == null)
+ rc = CreateResolveContext ();
- mg = mg.OverloadResolve (ec, ref PosArguments, false, Location);
- if (mg == null)
- return null;
-
- var constructor = (MethodSpec) mg;
- if (PosArguments == null) {
- pos_values = EmptyObject;
- return constructor;
+ AddModuleCharSet (rc);
}
- if (!PosArguments.GetAttributableValue (ec, out pos_values))
- return null;
+ if (NamedArguments != null) {
+ if (rc == null)
+ rc = CreateResolveContext ();
- // Here we do the checks which should be done by corlib or by runtime.
- // However Zoltan doesn't like it and every Mono compiler has to do it again.
- PredefinedAttributes pa = PredefinedAttributes.Get;
- if (Type == pa.Guid) {
- try {
- new Guid ((string)pos_values [0]);
- }
- catch (Exception e) {
- Error_AttributeEmitError (e.Message);
+ if (!ResolveNamedArguments (rc))
return null;
- }
}
- if (Type == pa.AttributeUsage && (int)pos_values [0] == 0) {
- ec.Report.Error (591, Location, "Invalid value for argument to `System.AttributeUsage' attribute");
- return null;
- }
+ resolve_error = false;
+ return ctor;
+ }
- if (Type == pa.IndexerName || Type == pa.Conditional) {
- string v = pos_values [0] as string;
- if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
- ec.Report.Error (633, PosArguments [0].Expr.Location,
- "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
+ MethodSpec ResolveConstructor (ResolveContext ec)
+ {
+ if (pos_args != null) {
+ bool dynamic;
+ pos_args.Resolve (ec, out dynamic);
+ if (dynamic) {
+ Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
return null;
}
}
- if (Type == pa.MethodImpl && pos_values.Length == 1 &&
- constructor.Parameters.Types [0] == TypeManager.short_type &&
- !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) {
- Error_AttributeEmitError ("Incorrect argument value.");
- return null;
- }
-
- return constructor;
+ return Expression.ConstructorLookup (ec, Type, ref pos_args, loc);
}
- protected virtual bool ResolveNamedArguments (ResolveContext ec)
+ bool ResolveNamedArguments (ResolveContext ec)
{
int named_arg_count = NamedArguments.Count;
-
- var field_infos = new List<FieldInfo> (named_arg_count);
- var prop_infos = new List<PropertyInfo> (named_arg_count);
- var field_values = new List<object> (named_arg_count);
- var prop_values = new List<object> (named_arg_count);
-
var seen_names = new List<string> (named_arg_count);
+
+ named_values = new List<KeyValuePair<MemberExpr, NamedArgument>> (named_arg_count);
foreach (NamedArgument a in NamedArguments) {
string name = a.Name;
a.Resolve (ec);
- Expression member = Expression.MemberLookup (ec.Compiler,
- ec.CurrentType, Type, name,
- MemberTypes.All,
- BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static,
- Location);
+ Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
if (member == null) {
- member = Expression.MemberLookup (ec.Compiler, ec.CurrentType, Type, name,
- MemberTypes.All, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
- Location);
+ member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
if (member != null) {
- ec.Report.SymbolRelatedToPreviousError (member.Type);
- Expression.ErrorIsInaccesible (Location, member.GetSignatureForError (), ec.Report);
+ // TODO: ec.Report.SymbolRelatedToPreviousError (member);
+ Expression.ErrorIsInaccesible (ec, member.GetSignatureForError (), loc);
return false;
}
}
ObsoleteAttribute obsolete_attr;
if (member is PropertyExpr) {
- PropertyInfo pi = ((PropertyExpr) member).PropertyInfo;
+ var pi = ((PropertyExpr) member).PropertyInfo;
- if (!pi.CanWrite || !pi.CanRead || pi.GetGetMethod ().IsStatic) {
+ if (!pi.HasSet || !pi.HasGet || pi.IsStatic || !pi.Get.IsPublic || !pi.Set.IsPublic) {
ec.Report.SymbolRelatedToPreviousError (pi);
Error_InvalidNamedArgument (ec, a);
return false;
return false;
}
- object value;
- if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
- return false;
-
- PropertyBase pb = TypeManager.GetProperty (pi);
- if (pb != null)
- obsolete_attr = pb.GetObsoleteAttribute ();
- else
- obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (pi);
-
- prop_values.Add (value);
- prop_infos.Add (pi);
-
+ obsolete_attr = pi.GetAttributeObsolete ();
+ pi.MemberDefinition.SetIsAssigned ();
} else {
var fi = ((FieldExpr) member).Spec;
- if (fi.IsReadOnly || fi.IsStatic) {
+ if (fi.IsReadOnly || fi.IsStatic || !fi.IsPublic) {
Error_InvalidNamedArgument (ec, a);
return false;
}
if (!IsValidArgumentType (member.Type)) {
- ec.Report.SymbolRelatedToPreviousError (fi.MetaInfo);
+ ec.Report.SymbolRelatedToPreviousError (fi);
Error_InvalidNamedArgumentType (ec, a);
return false;
}
- object value;
- if (!a.Expr.GetAttributableValue (ec, member.Type, out value))
- return false;
-
- FieldBase fb = TypeManager.GetField (fi.MetaInfo);
- if (fb != null)
- obsolete_attr = fb.GetObsoleteAttribute ();
- else
- obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi.MetaInfo);
-
- field_values.Add (value);
- field_infos.Add (fi.MetaInfo);
+ obsolete_attr = fi.GetAttributeObsolete ();
+ fi.MemberDefinition.SetIsAssigned ();
}
if (obsolete_attr != null && !context.IsObsolete)
AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location, Report);
- }
-
- prop_info_arr = new PropertyInfo [prop_infos.Count];
- field_info_arr = new FieldInfo [field_infos.Count];
- field_values_arr = new object [field_values.Count];
- prop_values_arr = new object [prop_values.Count];
- field_infos.CopyTo (field_info_arr, 0);
- field_values.CopyTo (field_values_arr, 0);
+ if (a.Type != member.Type) {
+ a.Expr = Convert.ImplicitConversionRequired (ec, a.Expr, member.Type, a.Expr.Location);
+ }
- prop_values.CopyTo (prop_values_arr, 0);
- prop_infos.CopyTo (prop_info_arr, 0);
+ if (a.Expr != null)
+ named_values.Add (new KeyValuePair<MemberExpr, NamedArgument> ((MemberExpr) member, a));
+ }
return true;
}
public string GetValidTargets ()
{
StringBuilder sb = new StringBuilder ();
- AttributeTargets targets = GetAttributeUsage (Type).ValidOn;
+ AttributeTargets targets = Type.GetAttributeUsage (context.Module.PredefinedAttributes.AttributeUsage).ValidOn;
if ((targets & AttributeTargets.Assembly) != 0)
sb.Append ("assembly, ");
return sb.Remove (sb.Length - 2, 2).ToString ();
}
- /// <summary>
- /// Returns AttributeUsage attribute based on types hierarchy
- /// </summary>
- static AttributeUsageAttribute GetAttributeUsage (Type type)
- {
- AttributeUsageAttribute ua;
- if (usage_attr_cache.TryGetValue (type, out ua))
- return ua;
-
- Class attr_class = TypeManager.LookupClass (type);
- PredefinedAttribute pa = PredefinedAttributes.Get.AttributeUsage;
-
- if (attr_class == null) {
- if (!pa.IsDefined)
- return new AttributeUsageAttribute (0);
-
- object[] usage_attr = type.GetCustomAttributes (pa.Type, true);
- ua = (AttributeUsageAttribute)usage_attr [0];
- usage_attr_cache.Add (type, ua);
- return ua;
- }
-
- Attribute a = null;
- if (attr_class.OptAttributes != null)
- a = attr_class.OptAttributes.Search (pa);
-
- if (a == null) {
- if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type)
- ua = GetAttributeUsage (attr_class.TypeBuilder.BaseType);
- else
- ua = DefaultUsageAttribute;
- } else {
- ua = a.GetAttributeUsageAttribute ();
- }
-
- usage_attr_cache.Add (type, ua);
- return ua;
- }
-
- AttributeUsageAttribute GetAttributeUsageAttribute ()
+ public AttributeUsageAttribute GetAttributeUsageAttribute ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve ();
if (resolve_error)
return DefaultUsageAttribute;
- AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)pos_values [0]);
+ AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
- object field = GetPropertyValue ("AllowMultiple");
+ var field = GetNamedValue ("AllowMultiple") as BoolConstant;
if (field != null)
- usage_attribute.AllowMultiple = (bool)field;
+ usage_attribute.AllowMultiple = field.Value;
- field = GetPropertyValue ("Inherited");
+ field = GetNamedValue ("Inherited") as BoolConstant;
if (field != null)
- usage_attribute.Inherited = (bool)field;
+ usage_attribute.Inherited = field.Value;
return usage_attribute;
}
/// </summary>
public string GetIndexerAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve ();
- if (resolve_error)
+ if (resolve_error || pos_args.Count != 1 || !(pos_args[0].Expr is Constant))
return null;
- return pos_values [0] as string;
+ return ((Constant) pos_args[0].Expr).GetValue () as string;
}
/// <summary>
/// </summary>
public string GetConditionalAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve ();
if (resolve_error)
return null;
- return (string)pos_values [0];
+ return ((Constant) pos_args[0].Expr).GetValue () as string;
}
/// <summary>
/// </summary>
public ObsoleteAttribute GetObsoleteAttribute ()
{
- if (pos_values == null)
+ if (!arg_resolved) {
+ // corlib only case when obsolete is used before is resolved
+ var c = Type.MemberDefinition as Class;
+ if (c != null && !c.HasMembersDefined)
+ c.Define ();
+
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve ();
+ }
if (resolve_error)
return null;
- if (pos_values == null || pos_values.Length == 0)
+ if (pos_args == null)
return new ObsoleteAttribute ();
- if (pos_values.Length == 1)
- return new ObsoleteAttribute ((string)pos_values [0]);
+ string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
+ if (pos_args.Count == 1)
+ return new ObsoleteAttribute (msg);
- return new ObsoleteAttribute ((string)pos_values [0], (bool)pos_values [1]);
+ return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
}
/// <summary>
/// </summary>
public bool GetClsCompliantAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
// TODO: It is not neccessary to call whole Resolve (ApplyAttribute does it now) we need only ctor args.
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve ();
if (resolve_error)
return false;
- return (bool)pos_values [0];
+ return ((BoolConstant) pos_args[0].Expr).Value;
}
- public Type GetCoClassAttributeValue ()
+ public TypeSpec GetCoClassAttributeValue ()
{
- if (pos_values == null)
+ if (!arg_resolved)
Resolve ();
if (resolve_error)
return null;
- return (Type)pos_values [0];
+ return GetArgumentType ();
}
public bool CheckTarget ()
case "field": Target = AttributeTargets.Field; return true;
case "method": Target = AttributeTargets.Method; return true;
case "property": Target = AttributeTargets.Property; return true;
+ case "module": Target = AttributeTargets.Module; return true;
}
throw new InternalErrorException ("Unknown explicit target: " + ExplicitTarget);
}
sb.Append (", ");
}
sb.Remove (sb.Length - 2, 2);
- Report.Error (657, Location, "`{0}' is not a valid attribute location for this declaration. " +
- "Valid attribute locations for this declaration are `{1}'", ExplicitTarget, sb.ToString ());
+ Report.Warning (657, 1, Location,
+ "`{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",
+ ExplicitTarget, sb.ToString ());
return false;
}
/// <summary>
/// Tests permitted SecurityAction for assembly or other types
/// </summary>
- protected virtual bool IsSecurityActionValid (bool for_assembly)
+ bool IsSecurityActionValid ()
{
SecurityAction action = GetSecurityActionValue ();
+ bool for_assembly = Target == AttributeTargets.Assembly || Target == AttributeTargets.Module;
switch (action) {
+#pragma warning disable 618
case SecurityAction.Demand:
case SecurityAction.Assert:
case SecurityAction.Deny:
if (for_assembly)
return true;
break;
+#pragma warning restore 618
default:
Error_AttributeEmitError ("SecurityAction is out of range");
System.Security.Permissions.SecurityAction GetSecurityActionValue ()
{
- return (SecurityAction)pos_values [0];
+ return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
}
/// <summary>
/// Creates instance of SecurityAttribute class and add result of CreatePermission method to permission table.
/// </summary>
/// <returns></returns>
- public void ExtractSecurityPermissionSet (Dictionary<SecurityAction, PermissionSet> permissions)
- {
- Type orig_assembly_type = null;
-
- if (TypeManager.LookupDeclSpace (Type) != null) {
- if (!RootContext.StdLib) {
- orig_assembly_type = Type.GetType (Type.FullName);
- } else {
- string orig_version_path = Environment.GetEnvironmentVariable ("__SECURITY_BOOTSTRAP_DB");
- if (orig_version_path == null) {
- Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
- return;
- }
-
- if (orig_sec_assembly == null) {
- string file = Path.Combine (orig_version_path, Driver.OutputFile);
- orig_sec_assembly = Assembly.LoadFile (file);
- }
-
- orig_assembly_type = orig_sec_assembly.GetType (Type.FullName, true);
- if (orig_assembly_type == null) {
- Report.Warning (-112, 1, Location, "Self-referenced security attribute `{0}' " +
- "was not found in previous version of assembly");
- return;
- }
- }
- }
-
- SecurityAttribute sa;
- // For all non-selfreferencing security attributes we can avoid all hacks
- if (orig_assembly_type == null) {
- sa = (SecurityAttribute) Activator.CreateInstance (Type, pos_values);
-
- if (prop_info_arr != null) {
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- PropertyInfo pi = prop_info_arr [i];
- pi.SetValue (sa, prop_values_arr [i], null);
- }
- }
+ public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
+ {
+#if STATIC
+ object[] values = new object[pos_args.Count];
+ for (int i = 0; i < values.Length; ++i)
+ values[i] = ((Constant) pos_args[i].Expr).GetValue ();
+
+ PropertyInfo[] prop;
+ object[] prop_values;
+ if (named_values == null) {
+ prop = null;
+ prop_values = null;
} else {
- // HACK: All security attributes have same ctor syntax
- sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, new object[] { GetSecurityActionValue () } );
-
- // All types are from newly created assembly but for invocation with old one we need to convert them
- if (prop_info_arr != null) {
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- PropertyInfo emited_pi = prop_info_arr [i];
- // FIXME: We are missing return type filter
- // TODO: pi can be null
- PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name);
-
- object old_instance = TypeManager.IsEnumType (pi.PropertyType) ?
- System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
- prop_values_arr [i];
-
- pi.SetValue (sa, old_instance, null);
- }
- }
- }
-
- IPermission perm;
- perm = sa.CreatePermission ();
- SecurityAction action = GetSecurityActionValue ();
-
- // IS is correct because for corlib we are using an instance from old corlib
- if (!(perm is System.Security.CodeAccessPermission)) {
- switch (action) {
- case SecurityAction.Demand:
- action = (SecurityAction)13;
- break;
- case SecurityAction.LinkDemand:
- action = (SecurityAction)14;
- break;
- case SecurityAction.InheritanceDemand:
- action = (SecurityAction)15;
- break;
+ prop = new PropertyInfo[named_values.Count];
+ prop_values = new object [named_values.Count];
+ for (int i = 0; i < prop.Length; ++i) {
+ prop [i] = ((PropertyExpr) named_values [i].Key).PropertyInfo.MetaInfo;
+ prop_values [i] = ((Constant) named_values [i].Value.Expr).GetValue ();
}
}
- PermissionSet ps;
- if (!permissions.TryGetValue (action, out ps)) {
- if (sa is PermissionSetAttribute)
- ps = new PermissionSet (sa.Unrestricted ? PermissionState.Unrestricted : PermissionState.None);
- else
- ps = new PermissionSet (PermissionState.None);
-
- permissions.Add (action, ps);
- } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
- ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
- permissions [action] = ps;
- }
- ps.AddPermission (perm);
- }
-
- public object GetPropertyValue (string name)
- {
- if (prop_info_arr == null)
- return null;
-
- for (int i = 0; i < prop_info_arr.Length; ++i) {
- if (prop_info_arr [i].Name == name)
- return prop_values_arr [i];
- }
+ if (permissions == null)
+ permissions = new SecurityType ();
- return null;
+ var cab = new CustomAttributeBuilder ((ConstructorInfo) ctor.GetMetaInfo (), values, prop, prop_values);
+ permissions.Add (cab);
+#else
+ throw new NotSupportedException ();
+#endif
}
- //
- // Theoretically, we can get rid of this, since FieldBuilder.SetCustomAttribute()
- // and ParameterBuilder.SetCustomAttribute() are supposed to handle this attribute.
- // However, we can't, since it appears that the .NET 1.1 SRE hangs when given a MarshalAsAttribute.
- //
-#if false
- public UnmanagedMarshal GetMarshal (Attributable attr)
+ public Constant GetNamedValue (string name)
{
- UnmanagedType UnmanagedType;
- if (!RootContext.StdLib || pos_values [0].GetType () != typeof (UnmanagedType))
- UnmanagedType = (UnmanagedType) System.Enum.ToObject (typeof (UnmanagedType), pos_values [0]);
- else
- UnmanagedType = (UnmanagedType) pos_values [0];
-
- object value = GetFieldValue ("SizeParamIndex");
- if (value != null && UnmanagedType != UnmanagedType.LPArray) {
- Error_AttributeEmitError ("SizeParamIndex field is not valid for the specified unmanaged type");
+ if (named_values == null)
return null;
- }
-
- object o = GetFieldValue ("ArraySubType");
- UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
-
- switch (UnmanagedType) {
- case UnmanagedType.CustomMarshaler: {
- MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
- BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
- if (define_custom == null) {
- Report.RuntimeMissingSupport (Location, "set marshal info");
- return null;
- }
-
- object [] args = new object [4];
- args [0] = GetFieldValue ("MarshalTypeRef");
- args [1] = GetFieldValue ("MarshalCookie");
- args [2] = GetFieldValue ("MarshalType");
- args [3] = Guid.Empty;
- return (UnmanagedMarshal) define_custom.Invoke (null, args);
- }
- case UnmanagedType.LPArray: {
- object size_const = GetFieldValue ("SizeConst");
- object size_param_index = GetFieldValue ("SizeParamIndex");
-
- if ((size_const != null) || (size_param_index != null)) {
- MethodInfo define_array = typeof (UnmanagedMarshal).GetMethod ("DefineLPArrayInternal",
- BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
- if (define_array == null) {
- Report.RuntimeMissingSupport (Location, "set marshal info");
- return null;
- }
-
- object [] args = new object [3];
- args [0] = array_sub_type;
- args [1] = size_const == null ? -1 : size_const;
- args [2] = size_param_index == null ? -1 : size_param_index;
- return (UnmanagedMarshal) define_array.Invoke (null, args);
- }
- else
- return UnmanagedMarshal.DefineLPArray (array_sub_type);
- }
- case UnmanagedType.SafeArray:
- return UnmanagedMarshal.DefineSafeArray (array_sub_type);
-
- case UnmanagedType.ByValArray:
- FieldBase fm = attr as FieldBase;
- if (fm == null) {
- Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
- return null;
- }
- return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
-
- case UnmanagedType.ByValTStr:
- return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
- default:
- return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
+ for (int i = 0; i < named_values.Count; ++i) {
+ if (named_values [i].Value.Name == name)
+ return named_values [i].Value.Expr as Constant;
}
- }
- object GetFieldValue (string name)
- {
- int i;
- if (field_info_arr == null)
- return null;
- i = 0;
- foreach (FieldInfo fi in field_info_arr) {
- if (fi.Name == name)
- return GetValue (field_values_arr [i]);
- i++;
- }
return null;
}
- static object GetValue (object value)
- {
- if (value is EnumConstant)
- return ((EnumConstant) value).GetValue ();
- else
- return value;
- }
-
-#endif
-
public CharSet GetCharSetValue ()
{
- return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ());
+ return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
}
public bool HasField (string fieldName)
{
- if (field_info_arr == null)
+ if (named_values == null)
return false;
- foreach (FieldInfo fi in field_info_arr) {
- if (fi.Name == fieldName)
+ foreach (var na in named_values) {
+ if (na.Value.Name == fieldName)
return true;
}
return false;
}
- public bool IsInternalMethodImplAttribute {
- get {
- if (Type != PredefinedAttributes.Get.MethodImpl)
- return false;
-
- MethodImplOptions options;
- if (pos_values[0].GetType () != typeof (MethodImplOptions))
- options = (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values[0]);
- else
- options = (MethodImplOptions)pos_values[0];
+ //
+ // Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
+ //
+ public bool IsInternalCall ()
+ {
+ return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
+ }
- return (options & MethodImplOptions.InternalCall) != 0;
+ public MethodImplOptions GetMethodImplOptions ()
+ {
+ MethodImplOptions options = 0;
+ if (pos_args.Count == 1) {
+ options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
+ } else if (HasField ("Value")) {
+ var named = GetNamedValue ("Value");
+ options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), named.GetValue ().ToString ());
}
+
+ return options;
}
- public LayoutKind GetLayoutKindValue ()
+ //
+ // Returns true for StructLayoutAttribute with LayoutKind.Explicit value
+ //
+ public bool IsExplicitLayoutKind ()
{
- if (!RootContext.StdLib || pos_values [0].GetType () != typeof (LayoutKind))
- return (LayoutKind)System.Enum.ToObject (typeof (LayoutKind), pos_values [0]);
+ if (pos_args == null || pos_args.Count != 1)
+ return false;
- return (LayoutKind)pos_values [0];
+ var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
+ return value == LayoutKind.Explicit;
}
- public object GetParameterDefaultValue ()
+ public Expression GetParameterDefaultValue ()
{
- return pos_values [0];
+ if (pos_args == null)
+ return null;
+
+ return pos_args[0].Expr;
}
public override bool Equals (object obj)
public override int GetHashCode ()
{
- return type.GetHashCode () ^ Target.GetHashCode ();
+ return Type.GetHashCode () ^ Target.GetHashCode ();
}
/// <summary>
/// </summary>
public void Emit (Dictionary<Attribute, List<Attribute>> allEmitted)
{
- CustomAttributeBuilder cb = Resolve ();
- if (cb == null)
+ var ctor = Resolve ();
+ if (ctor == null)
return;
- AttributeUsageAttribute usage_attr = GetAttributeUsage (Type);
+ var predefined = context.Module.PredefinedAttributes;
+
+ AttributeUsageAttribute usage_attr = Type.GetAttributeUsage (predefined.AttributeUsage);
if ((usage_attr.ValidOn & Target) == 0) {
Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " +
"It is valid on `{1}' declarations only",
return;
}
- var predefined = PredefinedAttributes.Get;
+ byte[] cdata;
+ if (pos_args == null && named_values == null) {
+ cdata = AttributeEncoder.Empty;
+ } else {
+ AttributeEncoder encoder = new AttributeEncoder ();
+
+ if (pos_args != null) {
+ var param_types = ctor.Parameters.Types;
+ for (int j = 0; j < pos_args.Count; ++j) {
+ var pt = param_types[j];
+ var arg_expr = pos_args[j].Expr;
+ if (j == 0) {
+ if ((Type == predefined.IndexerName || Type == predefined.Conditional) && arg_expr is Constant) {
+ string v = ((Constant) arg_expr).GetValue () as string;
+ if (!Tokenizer.IsValidIdentifier (v) || (Type == predefined.IndexerName && Tokenizer.IsKeyword (v))) {
+ context.Module.Compiler.Report.Error (633, arg_expr.Location,
+ "The argument to the `{0}' attribute must be a valid identifier", GetSignatureForError ());
+ return;
+ }
+ } else if (Type == predefined.Guid) {
+ try {
+ string v = ((StringConstant) arg_expr).Value;
+ new Guid (v);
+ } catch (Exception e) {
+ Error_AttributeEmitError (e.Message);
+ return;
+ }
+ } else if (Type == predefined.AttributeUsage) {
+ int v = ((IntConstant) ((EnumConstant) arg_expr).Child).Value;
+ if (v == 0) {
+ context.Module.Compiler.Report.Error (591, Location, "Invalid value for argument to `{0}' attribute",
+ "System.AttributeUsage");
+ }
+ } else if (Type == predefined.MarshalAs) {
+ if (pos_args.Count == 1) {
+ var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
+ if (u_type == UnmanagedType.ByValArray && !(Owner is FieldBase)) {
+ Error_AttributeEmitError ("Specified unmanaged type is only valid on fields");
+ }
+ }
+ } else if (Type == predefined.DllImport) {
+ if (pos_args.Count == 1 && pos_args[0].Expr is Constant) {
+ var value = ((Constant) pos_args[0].Expr).GetValue () as string;
+ if (string.IsNullOrEmpty (value))
+ Error_AttributeEmitError ("DllName cannot be empty");
+ }
+ } else if (Type == predefined.MethodImpl && pt.BuiltinType == BuiltinTypeSpec.Type.Short &&
+ !System.Enum.IsDefined (typeof (MethodImplOptions), ((Constant) arg_expr).GetValue ().ToString ())) {
+ Error_AttributeEmitError ("Incorrect argument value.");
+ return;
+ }
+ }
+
+ arg_expr.EncodeAttributeValue (context, encoder, pt);
+ }
+ }
+
+ if (named_values != null) {
+ encoder.Encode ((ushort) named_values.Count);
+ foreach (var na in named_values) {
+ if (na.Key is FieldExpr)
+ encoder.Encode ((byte) 0x53);
+ else
+ encoder.Encode ((byte) 0x54);
+
+ encoder.Encode (na.Key.Type);
+ encoder.Encode (na.Value.Name);
+ na.Value.Expr.EncodeAttributeValue (context, encoder, na.Key.Type);
+ }
+ } else {
+ encoder.EncodeEmptyNamedArguments ();
+ }
+
+ cdata = encoder.ToArray ();
+ }
try {
foreach (Attributable target in targets)
- target.ApplyAttributeBuilder (this, cb, predefined);
+ target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
} catch (Exception e) {
+ if (e is BadImageFormat && Report.Errors > 0)
+ return;
+
Error_AttributeEmitError (e.Message);
return;
}
}
}
- if (!RootContext.VerifyClsCompliance)
+ if (!context.Module.Compiler.Settings.VerifyClsCompliance)
return;
// Here we are testing attribute arguments for array usage (error 3016)
if (Owner.IsClsComplianceRequired ()) {
- if (PosArguments != null)
- PosArguments.CheckArrayAsAttribute (context.Compiler);
+ if (pos_args != null)
+ pos_args.CheckArrayAsAttribute (context.Module.Compiler);
if (NamedArguments == null)
return;
- NamedArguments.CheckArrayAsAttribute (context.Compiler);
+ NamedArguments.CheckArrayAsAttribute (context.Module.Compiler);
}
}
private Expression GetValue ()
{
- if (PosArguments == null || PosArguments.Count < 1)
+ if (pos_args == null || pos_args.Count < 1)
return null;
- return PosArguments [0].Expr;
+ return pos_args[0].Expr;
}
public string GetString ()
return false;
}
- public Type GetArgumentType ()
+ public TypeSpec GetArgumentType ()
{
TypeOf e = GetValue () as TypeOf;
if (e == null)
return null;
return e.TypeArgument;
}
+ }
+
+ public class Attributes
+ {
+ public readonly List<Attribute> Attrs;
- public override Expression CreateExpressionTree (ResolveContext ec)
+ public Attributes (Attribute a)
{
- throw new NotSupportedException ("ET");
+ Attrs = new List<Attribute> ();
+ Attrs.Add (a);
}
- protected override Expression DoResolve (ResolveContext ec)
+ public Attributes (List<Attribute> attrs)
{
- throw new NotImplementedException ();
+ Attrs = attrs;
}
- public override void Emit (EmitContext ec)
+ public void AddAttribute (Attribute attr)
{
- throw new NotImplementedException ();
- }
- }
-
-
- /// <summary>
- /// For global attributes (assembly, module) we need special handling.
- /// Attributes can be located in the several files
- /// </summary>
- public class GlobalAttribute : Attribute
- {
- public readonly NamespaceEntry ns;
-
- public GlobalAttribute (NamespaceEntry ns, string target, ATypeNameExpression expression,
- Arguments[] args, Location loc, bool nameEscaped):
- base (target, expression, args, loc, nameEscaped)
- {
- this.ns = ns;
- }
-
- public override void AttachTo (Attributable target, IMemberContext context)
- {
- if (ExplicitTarget == "assembly") {
- base.AttachTo (CodeGen.Assembly, context);
- return;
- }
-
- if (ExplicitTarget == "module") {
- base.AttachTo (RootContext.ToplevelTypes, context);
- return;
- }
-
- throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget);
- }
-
- void Enter ()
- {
- // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten
- // each time a new file is parsed. However, we need to use the NamespaceEntry
- // in effect where the attribute was used. Since code elsewhere cannot assume
- // that the NamespaceEntry is right, just overwrite it.
- //
- // Precondition: RootContext.ToplevelTypes == null
-
- if (RootContext.ToplevelTypes.NamespaceEntry != null)
- throw new InternalErrorException (Location + " non-null NamespaceEntry");
-
- RootContext.ToplevelTypes.NamespaceEntry = ns;
- }
-
- protected override bool IsSecurityActionValid (bool for_assembly)
- {
- return base.IsSecurityActionValid (true);
- }
-
- void Leave ()
- {
- RootContext.ToplevelTypes.NamespaceEntry = null;
- }
-
- protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
- {
- try {
- Enter ();
- return base.ResolveAsTypeTerminal (expr, ec);
- }
- finally {
- Leave ();
- }
- }
-
- protected override MethodSpec ResolveConstructor (ResolveContext ec)
- {
- try {
- Enter ();
- return base.ResolveConstructor (ec);
- }
- finally {
- Leave ();
- }
- }
-
- protected override bool ResolveNamedArguments (ResolveContext ec)
- {
- try {
- Enter ();
- return base.ResolveNamedArguments (ec);
- }
- finally {
- Leave ();
- }
- }
- }
-
- public class Attributes {
- public readonly List<Attribute> Attrs;
-
- public Attributes (Attribute a)
- {
- Attrs = new List<Attribute> ();
- Attrs.Add (a);
- }
-
- public Attributes (List<Attribute> attrs)
- {
- Attrs = attrs;
+ Attrs.Add (attr);
}
public void AddAttributes (List<Attribute> attrs)
/// </summary>
public bool CheckTargets ()
{
- foreach (Attribute a in Attrs) {
- if (!a.CheckTarget ())
- return false;
+ for (int i = 0; i < Attrs.Count; ++i) {
+ if (!Attrs [i].CheckTarget ())
+ Attrs.RemoveAt (i--);
}
+
return true;
}
+ public void ConvertGlobalAttributes (TypeContainer member, NamespaceContainer currentNamespace, bool isGlobal)
+ {
+ var member_explicit_targets = member.ValidAttributeTargets;
+ for (int i = 0; i < Attrs.Count; ++i) {
+ var attr = Attrs[0];
+ if (attr.ExplicitTarget == null)
+ continue;
+
+ int ii;
+ for (ii = 0; ii < member_explicit_targets.Length; ++ii) {
+ if (attr.ExplicitTarget == member_explicit_targets[ii]) {
+ ii = -1;
+ break;
+ }
+ }
+
+ if (ii < 0 || !isGlobal)
+ continue;
+
+ member.Module.AddAttribute (attr, currentNamespace);
+ Attrs.RemoveAt (i);
+ --i;
+ }
+ }
+
public Attribute Search (PredefinedAttribute t)
+ {
+ return Search (null, t);
+ }
+
+ public Attribute Search (string explicitTarget, PredefinedAttribute t)
{
foreach (Attribute a in Attrs) {
+ if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
+ continue;
+
if (a.ResolveType () == t)
return a;
}
}
}
- /// <summary>
- /// Helper class for attribute verification routine.
- /// </summary>
- sealed class AttributeTester
+ public sealed class AttributeEncoder
{
- static Dictionary<Type, bool> analyzed_types;
- static Dictionary<Type, ObsoleteAttribute> analyzed_types_obsolete;
- static Dictionary<MemberInfo, ObsoleteAttribute> analyzed_member_obsolete;
- static Dictionary<MethodBase, bool> analyzed_method_excluded;
-// static Dictionary<FieldInfo, IFixedBuffer> fixed_buffer_cache;
-
- static AttributeTester ()
+ [Flags]
+ public enum EncodedTypeProperties
{
- Reset ();
+ None = 0,
+ DynamicType = 1,
+ TypeParameter = 1 << 1
}
- private AttributeTester ()
+ public static readonly byte[] Empty;
+
+ byte[] buffer;
+ int pos;
+ const ushort Version = 1;
+
+ static AttributeEncoder ()
{
+ Empty = new byte[4];
+ Empty[0] = (byte) Version;
}
- public static void Reset ()
+ public AttributeEncoder ()
{
- analyzed_types = new Dictionary<Type, bool> (ReferenceEquality<Type>.Default);
- analyzed_types_obsolete = new Dictionary<Type, ObsoleteAttribute> (ReferenceEquality<Type>.Default);
- analyzed_member_obsolete = new Dictionary<MemberInfo, ObsoleteAttribute> (ReferenceEquality<MemberInfo>.Default);
- analyzed_method_excluded = new Dictionary<MethodBase, bool> (ReferenceEquality<MethodBase>.Default);
-// fixed_buffer_cache = new Dictionary<FieldInfo, IFixedBuffer> (ReferenceEquality<FieldInfo>.Default);
+ buffer = new byte[32];
+ Encode (Version);
}
- public enum Result {
- Ok,
- RefOutArrayError,
- ArrayArrayError
+ public void Encode (bool value)
+ {
+ Encode (value ? (byte) 1 : (byte) 0);
}
- /// <summary>
- /// Returns true if parameters of two compared methods are CLS-Compliant.
- /// It tests differing only in ref or out, or in array rank.
- /// </summary>
- public static Result AreOverloadedMethodParamsClsCompliant (AParametersCollection pa, AParametersCollection pb)
- {
- Type [] types_a = pa.Types;
- Type [] types_b = pb.Types;
- if (types_a == null || types_b == null)
- return Result.Ok;
-
- if (types_a.Length != types_b.Length)
- return Result.Ok;
-
- Result result = Result.Ok;
- for (int i = 0; i < types_b.Length; ++i) {
- Type aType = types_a [i];
- Type bType = types_b [i];
-
- if (aType.IsArray && bType.IsArray) {
- Type a_el_type = TypeManager.GetElementType (aType);
- Type b_el_type = TypeManager.GetElementType (bType);
- if (aType.GetArrayRank () != bType.GetArrayRank () && a_el_type == b_el_type) {
- result = Result.RefOutArrayError;
- continue;
- }
-
- if (a_el_type.IsArray || b_el_type.IsArray) {
- result = Result.ArrayArrayError;
- continue;
- }
- }
-
- if (aType != bType)
- return Result.Ok;
+ public void Encode (byte value)
+ {
+ if (pos == buffer.Length)
+ Grow (1);
- const Parameter.Modifier out_ref_mod = (Parameter.Modifier.OUTMASK | Parameter.Modifier.REFMASK);
- if ((pa.FixedParameters[i].ModFlags & out_ref_mod) != (pb.FixedParameters[i].ModFlags & out_ref_mod))
- result = Result.RefOutArrayError;
- }
- return result;
+ buffer [pos++] = value;
}
- /// <summary>
- /// This method tests the CLS compliance of external types. It doesn't test type visibility.
- /// </summary>
- public static bool IsClsCompliant (Type type)
+ public void Encode (sbyte value)
{
- if (type == null)
- return true;
-
- bool result;
- if (analyzed_types.TryGetValue (type, out result))
- return result;
-
- if (type.IsPointer) {
- analyzed_types.Add (type, false);
- return false;
- }
-
- if (type.IsArray) {
- result = IsClsCompliant (TypeManager.GetElementType (type));
- } else if (TypeManager.IsNullableType (type)) {
- result = IsClsCompliant (TypeManager.TypeToCoreType (TypeManager.GetTypeArguments (type) [0]));
- } else {
- result = AnalyzeTypeCompliance (type);
- }
- analyzed_types.Add (type, result);
- return result;
- }
+ Encode ((byte) value);
+ }
- public static void VerifyModulesClsCompliance (CompilerContext ctx)
+ public void Encode (short value)
{
- Module[] modules = GlobalRootNamespace.Instance.Modules;
- if (modules == null)
- return;
+ if (pos + 2 > buffer.Length)
+ Grow (2);
- // The first module is generated assembly
- for (int i = 1; i < modules.Length; ++i) {
- Module module = modules [i];
- if (!GetClsCompliantAttributeValue (module, null)) {
- ctx.Report.Error (3013, "Added modules must be marked with the CLSCompliant attribute " +
- "to match the assembly", module.Name);
- return;
- }
- }
+ buffer[pos++] = (byte) value;
+ buffer[pos++] = (byte) (value >> 8);
}
- public static Type GetImportedIgnoreCaseClsType (string name)
+ public void Encode (ushort value)
{
- foreach (Assembly a in GlobalRootNamespace.Instance.Assemblies) {
- Type t = a.GetType (name, false, true);
- if (t == null)
- continue;
-
- if (IsClsCompliant (t))
- return t;
- }
- return null;
+ Encode ((short) value);
}
- static bool GetClsCompliantAttributeValue (ICustomAttributeProvider attribute_provider, Assembly a)
+ public void Encode (int value)
{
- PredefinedAttribute pa = PredefinedAttributes.Get.CLSCompliant;
- if (!pa.IsDefined)
- return false;
+ if (pos + 4 > buffer.Length)
+ Grow (4);
- object[] cls_attr = attribute_provider.GetCustomAttributes (pa.Type, false);
- if (cls_attr.Length == 0) {
- if (a == null)
- return false;
-
- return GetClsCompliantAttributeValue (a, null);
- }
-
- return ((CLSCompliantAttribute)cls_attr [0]).IsCompliant;
+ buffer[pos++] = (byte) value;
+ buffer[pos++] = (byte) (value >> 8);
+ buffer[pos++] = (byte) (value >> 16);
+ buffer[pos++] = (byte) (value >> 24);
}
- static bool AnalyzeTypeCompliance (Type type)
+ public void Encode (uint value)
{
- type = TypeManager.DropGenericTypeArguments (type);
- DeclSpace ds = TypeManager.LookupDeclSpace (type);
- if (ds != null) {
- return ds.IsClsComplianceRequired ();
- }
+ Encode ((int) value);
+ }
- if (TypeManager.IsGenericParameter (type))
- return true;
+ public void Encode (long value)
+ {
+ if (pos + 8 > buffer.Length)
+ Grow (8);
- return GetClsCompliantAttributeValue (type, type.Assembly);
+ buffer[pos++] = (byte) value;
+ buffer[pos++] = (byte) (value >> 8);
+ buffer[pos++] = (byte) (value >> 16);
+ buffer[pos++] = (byte) (value >> 24);
+ buffer[pos++] = (byte) (value >> 32);
+ buffer[pos++] = (byte) (value >> 40);
+ buffer[pos++] = (byte) (value >> 48);
+ buffer[pos++] = (byte) (value >> 56);
}
- /// <summary>
- /// Returns instance of ObsoleteAttribute when type is obsolete
- /// </summary>
- public static ObsoleteAttribute GetObsoleteAttribute (Type type)
- {
- ObsoleteAttribute result;
- if (analyzed_types_obsolete.TryGetValue (type, out result))
- return result;
-
- if (TypeManager.HasElementType (type)) {
- result = GetObsoleteAttribute (TypeManager.GetElementType (type));
- } else if (TypeManager.IsGenericParameter (type))
- result = null; // TODO: throw new NotSupportedException ()
- else if (TypeManager.IsGenericType (type) && !TypeManager.IsGenericTypeDefinition (type)) {
- return GetObsoleteAttribute (TypeManager.DropGenericTypeArguments (type));
- } else {
- DeclSpace type_ds = TypeManager.LookupDeclSpace (type);
-
- // Type is external, we can get attribute directly
- if (type_ds == null) {
- PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
- if (pa.IsDefined) {
- object[] attribute = type.GetCustomAttributes (pa.Type, false);
- if (attribute.Length == 1)
- result = (ObsoleteAttribute) attribute[0];
- }
- } else {
- result = type_ds.GetObsoleteAttribute ();
- }
- }
+ public void Encode (ulong value)
+ {
+ Encode ((long) value);
+ }
- // Cannot use .Add because of corlib bootstrap
- analyzed_types_obsolete [type] = result;
- return result;
+ public void Encode (float value)
+ {
+ Encode (SingleConverter.SingleToInt32Bits (value));
}
- /// <summary>
- /// Returns instance of ObsoleteAttribute when method is obsolete
- /// </summary>
- public static ObsoleteAttribute GetMethodObsoleteAttribute (MethodBase mb)
+ public void Encode (double value)
{
- IMethodData mc = TypeManager.GetMethod (mb);
- if (mc != null)
- return mc.GetObsoleteAttribute ();
+ Encode (BitConverter.DoubleToInt64Bits (value));
+ }
- // compiler generated methods are not registered by AddMethod
- if (mb.DeclaringType is TypeBuilder)
- return null;
+ public void Encode (string value)
+ {
+ if (value == null) {
+ Encode ((byte) 0xFF);
+ return;
+ }
- MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb);
- if (mi != null)
- return GetMemberObsoleteAttribute (mi);
+ var buf = Encoding.UTF8.GetBytes(value);
+ WriteCompressedValue (buf.Length);
- mi = TypeManager.GetEventFromAccessor (mb);
- if (mi != null)
- return GetMemberObsoleteAttribute (mi);
+ if (pos + buf.Length > buffer.Length)
+ Grow (buf.Length);
- return GetMemberObsoleteAttribute (mb);
+ Buffer.BlockCopy (buf, 0, buffer, pos, buf.Length);
+ pos += buf.Length;
}
- /// <summary>
- /// Returns instance of ObsoleteAttribute when member is obsolete
- /// </summary>
- public static ObsoleteAttribute GetMemberObsoleteAttribute (MemberInfo mi)
+ public EncodedTypeProperties Encode (TypeSpec type)
{
- ObsoleteAttribute oa;
- if (analyzed_member_obsolete.TryGetValue (mi, out oa))
- return oa;
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Bool:
+ Encode ((byte) 0x02);
+ break;
+ case BuiltinTypeSpec.Type.Char:
+ Encode ((byte) 0x03);
+ break;
+ case BuiltinTypeSpec.Type.SByte:
+ Encode ((byte) 0x04);
+ break;
+ case BuiltinTypeSpec.Type.Byte:
+ Encode ((byte) 0x05);
+ break;
+ case BuiltinTypeSpec.Type.Short:
+ Encode ((byte) 0x06);
+ break;
+ case BuiltinTypeSpec.Type.UShort:
+ Encode ((byte) 0x07);
+ break;
+ case BuiltinTypeSpec.Type.Int:
+ Encode ((byte) 0x08);
+ break;
+ case BuiltinTypeSpec.Type.UInt:
+ Encode ((byte) 0x09);
+ break;
+ case BuiltinTypeSpec.Type.Long:
+ Encode ((byte) 0x0A);
+ break;
+ case BuiltinTypeSpec.Type.ULong:
+ Encode ((byte) 0x0B);
+ break;
+ case BuiltinTypeSpec.Type.Float:
+ Encode ((byte) 0x0C);
+ break;
+ case BuiltinTypeSpec.Type.Double:
+ Encode ((byte) 0x0D);
+ break;
+ case BuiltinTypeSpec.Type.String:
+ Encode ((byte) 0x0E);
+ break;
+ case BuiltinTypeSpec.Type.Type:
+ Encode ((byte) 0x50);
+ break;
+ case BuiltinTypeSpec.Type.Object:
+ Encode ((byte) 0x51);
+ break;
+ case BuiltinTypeSpec.Type.Dynamic:
+ Encode ((byte) 0x51);
+ return EncodedTypeProperties.DynamicType;
+ default:
+ if (type.IsArray) {
+ Encode ((byte) 0x1D);
+ return Encode (TypeManager.GetElementType (type));
+ }
- if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType))
- return null;
+ if (type.Kind == MemberKind.Enum) {
+ Encode ((byte) 0x55);
+ EncodeTypeName (type);
+ }
- PredefinedAttribute pa = PredefinedAttributes.Get.Obsolete;
- if (!pa.IsDefined)
- return null;
+ break;
+ }
- oa = System.Attribute.GetCustomAttribute (mi, pa.Type, false) as ObsoleteAttribute;
- analyzed_member_obsolete.Add (mi, oa);
- return oa;
+ return EncodedTypeProperties.None;
}
- /// <summary>
- /// Common method for Obsolete error/warning reporting.
- /// </summary>
- public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
+ public void EncodeTypeName (TypeSpec type)
{
- if (oa.IsError) {
- Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
- return;
- }
+ var old_type = type.GetMetaInfo ();
+ Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
+ }
- if (oa.Message == null || oa.Message.Length == 0) {
- Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
- return;
- }
- Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
+ //
+ // Encodes single property named argument per call
+ //
+ public void EncodeNamedPropertyArgument (PropertySpec property, Constant value)
+ {
+ Encode ((ushort) 1); // length
+ Encode ((byte) 0x54); // property
+ Encode (property.MemberType);
+ Encode (property.Name);
+ value.EncodeAttributeValue (null, this, property.MemberType);
}
- public static bool IsConditionalMethodExcluded (MethodBase mb, Location loc)
+ //
+ // Encodes single field named argument per call
+ //
+ public void EncodeNamedFieldArgument (FieldSpec field, Constant value)
{
- bool excluded;
- if (analyzed_method_excluded.TryGetValue (mb, out excluded))
- return excluded;
+ Encode ((ushort) 1); // length
+ Encode ((byte) 0x53); // field
+ Encode (field.MemberType);
+ Encode (field.Name);
+ value.EncodeAttributeValue (null, this, field.MemberType);
+ }
- PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
- if (!pa.IsDefined)
- return false;
+ public void EncodeNamedArguments<T> (T[] members, Constant[] values) where T : MemberSpec, IInterfaceMemberSpec
+ {
+ Encode ((ushort) members.Length);
- ConditionalAttribute[] attrs = mb.GetCustomAttributes (pa.Type, true)
- as ConditionalAttribute[];
- if (attrs.Length == 0) {
- analyzed_method_excluded.Add (mb, false);
- return false;
- }
+ for (int i = 0; i < members.Length; ++i)
+ {
+ var member = members[i];
- foreach (ConditionalAttribute a in attrs) {
- if (loc.CompilationUnit.IsConditionalDefined (a.ConditionString)) {
- analyzed_method_excluded.Add (mb, false);
- return false;
- }
+ if (member.Kind == MemberKind.Field)
+ Encode ((byte) 0x53);
+ else if (member.Kind == MemberKind.Property)
+ Encode ((byte) 0x54);
+ else
+ throw new NotImplementedException (member.Kind.ToString ());
+
+ Encode (member.MemberType);
+ Encode (member.Name);
+ values [i].EncodeAttributeValue (null, this, member.MemberType);
}
+ }
- analyzed_method_excluded.Add (mb, true);
- return true;
+ public void EncodeEmptyNamedArguments ()
+ {
+ Encode ((ushort) 0);
}
- /// <summary>
- /// Analyzes class whether it has attribute which has ConditionalAttribute
- /// and its condition is not defined.
- /// </summary>
- public static bool IsAttributeExcluded (Type type, Location loc)
+ void Grow (int inc)
{
- if (!type.IsClass)
- return false;
+ int size = System.Math.Max (pos * 4, pos + inc + 2);
+ Array.Resize (ref buffer, size);
+ }
- Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
+ void WriteCompressedValue (int value)
+ {
+ if (value < 0x80) {
+ Encode ((byte) value);
+ return;
+ }
- // TODO: add caching
- // TODO: merge all Type bases attribute caching to one cache to save memory
- PredefinedAttribute pa = PredefinedAttributes.Get.Conditional;
- if (class_decl == null && pa.IsDefined) {
- object[] attributes = type.GetCustomAttributes (pa.Type, false);
- foreach (ConditionalAttribute ca in attributes) {
- if (loc.CompilationUnit.IsConditionalDefined (ca.ConditionString))
- return false;
- }
- return attributes.Length > 0;
+ if (value < 0x4000) {
+ Encode ((byte) (0x80 | (value >> 8)));
+ Encode ((byte) value);
+ return;
}
- return class_decl.IsExcluded ();
+ Encode (value);
}
- public static Type GetCoClassAttribute (Type type)
+ public byte[] ToArray ()
{
- TypeContainer tc = TypeManager.LookupInterface (type);
- PredefinedAttribute pa = PredefinedAttributes.Get.CoClass;
- if (tc == null) {
- if (!pa.IsDefined)
- return null;
-
- object[] o = type.GetCustomAttributes (pa.Type, false);
- if (o.Length < 1)
- return null;
- return ((System.Runtime.InteropServices.CoClassAttribute)o[0]).CoClass;
- }
+ byte[] buf = new byte[pos];
+ Array.Copy (buffer, buf, pos);
+ return buf;
+ }
+ }
- if (tc.OptAttributes == null)
- return null;
- Attribute a = tc.OptAttributes.Search (pa);
- if (a == null)
- return null;
+ /// <summary>
+ /// Helper class for attribute verification routine.
+ /// </summary>
+ static class AttributeTester
+ {
+ /// <summary>
+ /// Common method for Obsolete error/warning reporting.
+ /// </summary>
+ public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc, Report Report)
+ {
+ if (oa.IsError) {
+ Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
+ return;
+ }
- return a.GetCoClassAttributeValue ();
+ if (oa.Message == null || oa.Message.Length == 0) {
+ Report.Warning (612, 1, loc, "`{0}' is obsolete", member);
+ return;
+ }
+ Report.Warning (618, 2, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
}
}
+ //
+ // Predefined attribute types
+ //
public class PredefinedAttributes
{
- // Core types
+ // Build-in attributes
public readonly PredefinedAttribute ParamArray;
public readonly PredefinedAttribute Out;
- // Optional types
+ // Optional attributes
public readonly PredefinedAttribute Obsolete;
public readonly PredefinedAttribute DllImport;
public readonly PredefinedAttribute MethodImpl;
public readonly PredefinedAttribute Guid;
public readonly PredefinedAttribute AssemblyCulture;
public readonly PredefinedAttribute AssemblyVersion;
+ public readonly PredefinedAttribute AssemblyAlgorithmId;
+ public readonly PredefinedAttribute AssemblyFlags;
+ public readonly PredefinedAttribute AssemblyFileVersion;
public readonly PredefinedAttribute ComImport;
public readonly PredefinedAttribute CoClass;
public readonly PredefinedAttribute AttributeUsage;
public readonly PredefinedAttribute DefaultParameterValue;
public readonly PredefinedAttribute OptionalParameter;
-
- // New in .NET 2.0
+ public readonly PredefinedAttribute UnverifiableCode;
public readonly PredefinedAttribute DefaultCharset;
public readonly PredefinedAttribute TypeForwarder;
public readonly PredefinedAttribute FixedBuffer;
public readonly PredefinedAttribute RuntimeCompatibility;
public readonly PredefinedAttribute DebuggerHidden;
public readonly PredefinedAttribute UnsafeValueType;
+ public readonly PredefinedAttribute UnmanagedFunctionPointer;
+ public readonly PredefinedDebuggerBrowsableAttribute DebuggerBrowsable;
// New in .NET 3.5
public readonly PredefinedAttribute Extension;
// New in .NET 4.0
- public readonly PredefinedAttribute Dynamic;
- public readonly PredefinedAttribute DynamicTransform; // DynamicAttribute with transform arguments
+ public readonly PredefinedDynamicAttribute Dynamic;
//
// Optional types which are used as types and for member lookup
//
public readonly PredefinedAttribute DefaultMember;
- public readonly PredefinedAttribute DecimalConstant;
+ public readonly PredefinedDecimalAttribute DecimalConstant;
public readonly PredefinedAttribute StructLayout;
public readonly PredefinedAttribute FieldOffset;
-
- public static PredefinedAttributes Get = new PredefinedAttributes ();
-
- private PredefinedAttributes ()
- {
- ParamArray = new PredefinedAttribute ("System", "ParamArrayAttribute");
- Out = new PredefinedAttribute ("System.Runtime.InteropServices", "OutAttribute");
-
- Obsolete = new PredefinedAttribute ("System", "ObsoleteAttribute");
- DllImport = new PredefinedAttribute ("System.Runtime.InteropServices", "DllImportAttribute");
- MethodImpl = new PredefinedAttribute ("System.Runtime.CompilerServices", "MethodImplAttribute");
- MarshalAs = new PredefinedAttribute ("System.Runtime.InteropServices", "MarshalAsAttribute");
- In = new PredefinedAttribute ("System.Runtime.InteropServices", "InAttribute");
- IndexerName = new PredefinedAttribute ("System.Runtime.CompilerServices", "IndexerNameAttribute");
- Conditional = new PredefinedAttribute ("System.Diagnostics", "ConditionalAttribute");
- CLSCompliant = new PredefinedAttribute ("System", "CLSCompliantAttribute");
- Security = new PredefinedAttribute ("System.Security.Permissions", "SecurityAttribute");
- Required = new PredefinedAttribute ("System.Runtime.CompilerServices", "RequiredAttributeAttribute");
- Guid = new PredefinedAttribute ("System.Runtime.InteropServices", "GuidAttribute");
- AssemblyCulture = new PredefinedAttribute ("System.Reflection", "AssemblyCultureAttribute");
- AssemblyVersion = new PredefinedAttribute ("System.Reflection", "AssemblyVersionAttribute");
- ComImport = new PredefinedAttribute ("System.Runtime.InteropServices", "ComImportAttribute");
- CoClass = new PredefinedAttribute ("System.Runtime.InteropServices", "CoClassAttribute");
- AttributeUsage = new PredefinedAttribute ("System", "AttributeUsageAttribute");
- DefaultParameterValue = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultParameterValueAttribute");
- OptionalParameter = new PredefinedAttribute ("System.Runtime.InteropServices", "OptionalAttribute");
-
- DefaultCharset = new PredefinedAttribute ("System.Runtime.InteropServices", "DefaultCharSetAttribute");
- TypeForwarder = new PredefinedAttribute ("System.Runtime.CompilerServices", "TypeForwardedToAttribute");
- FixedBuffer = new PredefinedAttribute ("System.Runtime.CompilerServices", "FixedBufferAttribute");
- CompilerGenerated = new PredefinedAttribute ("System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
- InternalsVisibleTo = new PredefinedAttribute ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
- RuntimeCompatibility = new PredefinedAttribute ("System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
- DebuggerHidden = new PredefinedAttribute ("System.Diagnostics", "DebuggerHiddenAttribute");
- UnsafeValueType = new PredefinedAttribute ("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
-
- Extension = new PredefinedAttribute ("System.Runtime.CompilerServices", "ExtensionAttribute");
-
- Dynamic = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
- DynamicTransform = new PredefinedAttribute ("System.Runtime.CompilerServices", "DynamicAttribute");
-
- DefaultMember = new PredefinedAttribute ("System.Reflection", "DefaultMemberAttribute");
- DecimalConstant = new PredefinedAttribute ("System.Runtime.CompilerServices", "DecimalConstantAttribute");
- StructLayout = new PredefinedAttribute ("System.Runtime.InteropServices", "StructLayoutAttribute");
- FieldOffset = new PredefinedAttribute ("System.Runtime.InteropServices", "FieldOffsetAttribute");
- }
-
- public void Initialize (CompilerContext ctx)
- {
- foreach (FieldInfo fi in GetType ().GetFields (BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) {
- ((PredefinedAttribute) fi.GetValue (this)).Initialize (ctx, true);
+ public readonly PredefinedAttribute CallerMemberNameAttribute;
+ public readonly PredefinedAttribute CallerLineNumberAttribute;
+ public readonly PredefinedAttribute CallerFilePathAttribute;
+
+ public PredefinedAttributes (ModuleContainer module)
+ {
+ ParamArray = new PredefinedAttribute (module, "System", "ParamArrayAttribute");
+ Out = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OutAttribute");
+ ParamArray.Resolve ();
+ Out.Resolve ();
+
+ Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
+ DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
+ MethodImpl = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "MethodImplAttribute");
+ MarshalAs = new PredefinedAttribute (module, "System.Runtime.InteropServices", "MarshalAsAttribute");
+ In = new PredefinedAttribute (module, "System.Runtime.InteropServices", "InAttribute");
+ IndexerName = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "IndexerNameAttribute");
+ Conditional = new PredefinedAttribute (module, "System.Diagnostics", "ConditionalAttribute");
+ CLSCompliant = new PredefinedAttribute (module, "System", "CLSCompliantAttribute");
+ Security = new PredefinedAttribute (module, "System.Security.Permissions", "SecurityAttribute");
+ Required = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RequiredAttributeAttribute");
+ Guid = new PredefinedAttribute (module, "System.Runtime.InteropServices", "GuidAttribute");
+ AssemblyCulture = new PredefinedAttribute (module, "System.Reflection", "AssemblyCultureAttribute");
+ AssemblyVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyVersionAttribute");
+ AssemblyAlgorithmId = new PredefinedAttribute (module, "System.Reflection", "AssemblyAlgorithmIdAttribute");
+ AssemblyFlags = new PredefinedAttribute (module, "System.Reflection", "AssemblyFlagsAttribute");
+ AssemblyFileVersion = new PredefinedAttribute (module, "System.Reflection", "AssemblyFileVersionAttribute");
+ ComImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "ComImportAttribute");
+ CoClass = new PredefinedAttribute (module, "System.Runtime.InteropServices", "CoClassAttribute");
+ AttributeUsage = new PredefinedAttribute (module, "System", "AttributeUsageAttribute");
+ DefaultParameterValue = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultParameterValueAttribute");
+ OptionalParameter = new PredefinedAttribute (module, "System.Runtime.InteropServices", "OptionalAttribute");
+ UnverifiableCode = new PredefinedAttribute (module, "System.Security", "UnverifiableCodeAttribute");
+
+ DefaultCharset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DefaultCharSetAttribute");
+ TypeForwarder = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "TypeForwardedToAttribute");
+ FixedBuffer = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "FixedBufferAttribute");
+ CompilerGenerated = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
+ InternalsVisibleTo = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "InternalsVisibleToAttribute");
+ RuntimeCompatibility = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "RuntimeCompatibilityAttribute");
+ DebuggerHidden = new PredefinedAttribute (module, "System.Diagnostics", "DebuggerHiddenAttribute");
+ UnsafeValueType = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "UnsafeValueTypeAttribute");
+ UnmanagedFunctionPointer = new PredefinedAttribute (module, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute");
+ DebuggerBrowsable = new PredefinedDebuggerBrowsableAttribute (module, "System.Diagnostics", "DebuggerBrowsableAttribute");
+
+ Extension = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "ExtensionAttribute");
+
+ Dynamic = new PredefinedDynamicAttribute (module, "System.Runtime.CompilerServices", "DynamicAttribute");
+
+ DefaultMember = new PredefinedAttribute (module, "System.Reflection", "DefaultMemberAttribute");
+ DecimalConstant = new PredefinedDecimalAttribute (module, "System.Runtime.CompilerServices", "DecimalConstantAttribute");
+ StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
+ FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
+
+ CallerMemberNameAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerMemberNameAttribute");
+ CallerLineNumberAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerLineNumberAttribute");
+ CallerFilePathAttribute = new PredefinedAttribute (module, "System.Runtime.CompilerServices", "CallerFilePathAttribute");
+
+ // TODO: Should define only attributes which are used for comparison
+ const System.Reflection.BindingFlags all_fields = System.Reflection.BindingFlags.Public |
+ System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly;
+
+ foreach (var fi in GetType ().GetFields (all_fields)) {
+ ((PredefinedAttribute) fi.GetValue (this)).Define ();
}
}
-
- public static void Reset ()
- {
- Get = new PredefinedAttributes ();
- }
}
- public class PredefinedAttribute
+ public class PredefinedAttribute : PredefinedType
{
- Type type;
- CustomAttributeBuilder cab;
- ConstructorInfo ctor;
- readonly string ns, name;
- CompilerContext compiler;
-
- static readonly Type NotFound = typeof (PredefinedAttribute);
+ protected MethodSpec ctor;
- public PredefinedAttribute (string ns, string name)
+ public PredefinedAttribute (ModuleContainer module, string ns, string name)
+ : base (module, MemberKind.Class, ns, name)
{
- this.ns = ns;
- this.name = name;
}
- public static bool operator == (Type type, PredefinedAttribute pa)
- {
- return type == pa.type;
+ #region Properties
+
+ public MethodSpec Constructor {
+ get {
+ return ctor;
+ }
}
- public static bool operator != (Type type, PredefinedAttribute pa)
+ #endregion
+
+ public static bool operator == (TypeSpec type, PredefinedAttribute pa)
{
- return type != pa.type;
+ return type == pa.type && pa.type != null;
}
- public ConstructorInfo Constructor {
- get { return ctor; }
+ public static bool operator != (TypeSpec type, PredefinedAttribute pa)
+ {
+ return type != pa.type;
}
public override int GetHashCode ()
return base.GetHashCode ();
}
- public string GetSignatureForError ()
- {
- return ns + "." + name;
- }
-
public override bool Equals (object obj)
{
throw new NotSupportedException ();
public void EmitAttribute (ConstructorBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (MethodBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (PropertyBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (FieldBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (TypeBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
public void EmitAttribute (AssemblyBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public void EmitAttribute (ParameterBuilder builder)
+ public void EmitAttribute (ModuleBuilder builder)
{
if (ResolveBuilder ())
- builder.SetCustomAttribute (cab);
- }
-
- public bool IsDefined {
- get { return type != null && type != NotFound; }
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public void Initialize (CompilerContext ctx, bool canFail)
+ public void EmitAttribute (ParameterBuilder builder)
{
- this.compiler = ctx;
- Resolve (canFail);
+ if (ResolveBuilder ())
+ builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public bool Resolve (bool canFail)
+ ConstructorInfo GetCtorMetaInfo ()
{
- if (type != null) {
- if (IsDefined)
- return true;
- if (canFail)
- return false;
- }
-
- type = TypeManager.CoreLookupType (compiler, ns, name, Kind.Class, !canFail);
- if (type == null) {
- type = NotFound;
- return false;
- }
-
- return true;
+ return (ConstructorInfo) ctor.GetMetaInfo ();
}
- bool ResolveBuilder ()
+ public bool ResolveBuilder ()
{
- if (cab != null)
+ if (ctor != null)
return true;
//
// Handle all parameter-less attributes as optional
//
- if (!Resolve (true))
+ if (!IsDefined)
return false;
- ConstructorInfo ci = TypeManager.GetPredefinedConstructor (type, Location.Null, Type.EmptyTypes);
- if (ci == null)
- return false;
+ ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
+ return ctor != null;
+ }
+ }
- cab = new CustomAttributeBuilder (ci, new object[0]);
- return true;
+ public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
+ {
+ public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
}
- public bool ResolveConstructor (Location loc, params Type[] argType)
+ public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
{
- if (ctor != null)
- throw new InternalErrorException ("Predefined ctor redefined");
+ var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
+ if (ctor == null)
+ return;
- if (!Resolve (false))
- return false;
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.Encode ((int) state);
+ encoder.EncodeEmptyNamedArguments ();
- ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
- return ctor != null;
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ }
+ }
+
+ public class PredefinedDecimalAttribute : PredefinedAttribute
+ {
+ public PredefinedDecimalAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
+ }
+
+ public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
+ {
+ var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
+ if (ctor == null)
+ return;
+
+ int[] bits = decimal.GetBits (value);
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.Encode ((byte) (bits[3] >> 16));
+ encoder.Encode ((byte) (bits[3] >> 31));
+ encoder.Encode ((uint) bits[2]);
+ encoder.Encode ((uint) bits[1]);
+ encoder.Encode ((uint) bits[0]);
+ encoder.EncodeEmptyNamedArguments ();
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ }
+
+ public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
+ {
+ var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
+ if (ctor == null)
+ return;
+
+ int[] bits = decimal.GetBits (value);
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.Encode ((byte) (bits[3] >> 16));
+ encoder.Encode ((byte) (bits[3] >> 31));
+ encoder.Encode ((uint) bits[2]);
+ encoder.Encode ((uint) bits[1]);
+ encoder.Encode ((uint) bits[0]);
+ encoder.EncodeEmptyNamedArguments ();
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ }
+ }
+
+ public class PredefinedDynamicAttribute : PredefinedAttribute
+ {
+ MethodSpec tctor;
+
+ public PredefinedDynamicAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
}
- public Type Type {
- get { return type; }
+ public void EmitAttribute (FieldBuilder builder, TypeSpec type, Location loc)
+ {
+ if (ResolveTransformationCtor (loc)) {
+ var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
+ builder.SetCustomAttribute (cab);
+ }
+ }
+
+ public void EmitAttribute (ParameterBuilder builder, TypeSpec type, Location loc)
+ {
+ if (ResolveTransformationCtor (loc)) {
+ var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
+ builder.SetCustomAttribute (cab);
+ }
+ }
+
+ public void EmitAttribute (PropertyBuilder builder, TypeSpec type, Location loc)
+ {
+ if (ResolveTransformationCtor (loc)) {
+ var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
+ builder.SetCustomAttribute (cab);
+ }
+ }
+
+ public void EmitAttribute (TypeBuilder builder, TypeSpec type, Location loc)
+ {
+ if (ResolveTransformationCtor (loc)) {
+ var cab = new CustomAttributeBuilder ((ConstructorInfo) tctor.GetMetaInfo (), new object[] { GetTransformationFlags (type) });
+ builder.SetCustomAttribute (cab);
+ }
+ }
+
+ //
+ // When any element of the type is a dynamic type
+ //
+ // This method builds a transformation array for dynamic types
+ // used in places where DynamicAttribute cannot be applied to.
+ // It uses bool flag when type is of dynamic type and each
+ // section always starts with "false" for some reason.
+ //
+ // LAMESPEC: This should be part of C# specification
+ //
+ // Example: Func<dynamic, int, dynamic[]>
+ // Transformation: { false, true, false, false, true }
+ //
+ static bool[] GetTransformationFlags (TypeSpec t)
+ {
+ bool[] element;
+ var ac = t as ArrayContainer;
+ if (ac != null) {
+ element = GetTransformationFlags (ac.Element);
+ if (element == null)
+ return null;
+
+ bool[] res = new bool[element.Length + 1];
+ res[0] = false;
+ Array.Copy (element, 0, res, 1, element.Length);
+ return res;
+ }
+
+ if (t == null)
+ return null;
+
+ if (t.IsGeneric) {
+ List<bool> transform = null;
+ var targs = t.TypeArguments;
+ for (int i = 0; i < targs.Length; ++i) {
+ element = GetTransformationFlags (targs[i]);
+ if (element != null) {
+ if (transform == null) {
+ transform = new List<bool> ();
+ for (int ii = 0; ii <= i; ++ii)
+ transform.Add (false);
+ }
+
+ transform.AddRange (element);
+ } else if (transform != null) {
+ transform.Add (false);
+ }
+ }
+
+ if (transform != null)
+ return transform.ToArray ();
+ }
+
+ if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
+ return new bool[] { true };
+
+ return null;
+ }
+
+ bool ResolveTransformationCtor (Location loc)
+ {
+ if (tctor != null)
+ return true;
+
+ tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
+ return tctor != null;
}
}
}