//
// Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
// Copyright 2003-2008 Novell, Inc.
+// Copyright 2011 Xamarin Inc
//
using System;
#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
if (attributes == null)
attributes = attrs;
else
- throw new NotImplementedException ();
+ attributes.AddAttributes (attrs.Attrs);
- attributes.AttachTo (this, context);
+ attrs.AttachTo (this, context);
}
public Attributes OptAttributes {
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;
public static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
- static Assembly orig_sec_assembly;
public static readonly object[] EmptyObject = new object [0];
List<KeyValuePair<MemberExpr, NamedArgument>> named_values;
- // Cache for parameter-less attributes
- static Dictionary<TypeSpec, MethodSpec> att_cache;
-
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 Location Location {
+ get {
+ return loc;
+ }
+ }
+
+ public Arguments NamedArguments {
+ get {
+ return named_args;
+ }
+ }
+
+ public Arguments PositionalArguments {
+ get {
+ return pos_args;
+ }
+ }
+
+ public bool ResolveError {
+ get {
+ return resolve_error;
+ }
+ }
+
+ public ATypeNameExpression TypeExpression {
+ get {
+ return expression;
+ }
+ }
+
void AddModuleCharSet (ResolveContext rc)
{
const string dll_import_char_set = "CharSet";
if (HasField (dll_import_char_set))
return;
- if (!rc.Module.PredefinedTypes.CharSet.IsDefined) {
+ if (!rc.Module.PredefinedTypes.CharSet.Define ()) {
return;
}
if (NamedArguments == null)
- NamedArguments = new Arguments (1);
+ 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 Attribute Clone ()
{
Attribute a = new Attribute (ExplicitTarget, expression, null, loc, nameEscaped);
- a.PosArguments = PosArguments;
- a.NamedArguments = NamedArguments;
+ a.pos_args = pos_args;
+ a.named_args = NamedArguments;
return a;
}
- static Attribute ()
- {
- Reset ();
- }
-
- public static void Reset ()
- {
- att_cache = new Dictionary<TypeSpec, MethodSpec> ();
- }
-
//
// When the same attribute is attached to multiple fiels
// we use @target field as a list of targets. The attribute
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);
}
}
- protected virtual TypeExpr ResolveAsTypeTerminal (Expression expr, IMemberContext ec)
- {
- return expr.ResolveAsTypeTerminal (ec, false);
- }
-
- TypeSpec ResolvePossibleAttributeType (ATypeNameExpression expr, ref bool is_attr)
- {
- TypeExpr te = ResolveAsTypeTerminal (expr, context);
- if (te == null)
- return null;
-
- TypeSpec t = te.Type;
- if (t.IsAttribute) {
- 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 ()
+ void ResolveAttributeType (bool comparisonOnly)
{
SessionReportPrinter resolve_printer = new SessionReportPrinter ();
- ReportPrinter prev_recorder = context.Module.Compiler.Report.SetPrinter (resolve_printer);
+ ReportPrinter prev_recorder = Report.SetPrinter (resolve_printer);
bool t1_is_attr = false;
bool t2_is_attr = false;
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.Module.Compiler.Report.SetPrinter (prev_recorder);
}
- if (t1_is_attr && t2_is_attr) {
- 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;
+ if (t1_is_attr && t2_is_attr && t1 != t2) {
+ if (!comparisonOnly) {
+ 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;
}
return;
}
- resolve_printer.Merge (prev_recorder);
+ if (comparisonOnly)
+ return;
+
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 TypeSpec ResolveType ()
+ public TypeSpec ResolveTypeForComparison ()
{
if (Type == null && !resolve_error)
- ResolveAttributeType ();
+ ResolveAttributeType (true);
return Type;
}
- public override string GetSignatureForError ()
+ public string GetSignatureForError ()
{
if (Type != null)
return TypeManager.CSharpName (Type);
public bool HasSecurityAttribute {
get {
PredefinedAttribute pa = context.Module.PredefinedAttributes.Security;
- return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false);
+ return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false);
}
}
public bool IsValidSecurityAttribute ()
{
- return HasSecurityAttribute && IsSecurityActionValid (false);
+ return HasSecurityAttribute && IsSecurityActionValid ();
}
static bool IsValidArgumentType (TypeSpec t)
t = ac.Element;
}
- switch (t.BuildinType) {
- case BuildinTypeSpec.Type.Int:
- case BuildinTypeSpec.Type.UInt:
- case BuildinTypeSpec.Type.Long:
- case BuildinTypeSpec.Type.ULong:
- case BuildinTypeSpec.Type.Float:
- case BuildinTypeSpec.Type.Double:
- case BuildinTypeSpec.Type.Char:
- case BuildinTypeSpec.Type.Short:
- case BuildinTypeSpec.Type.Bool:
- case BuildinTypeSpec.Type.SByte:
- case BuildinTypeSpec.Type.Byte:
- case BuildinTypeSpec.Type.UShort:
-
- case BuildinTypeSpec.Type.String:
- case BuildinTypeSpec.Type.Object:
- case BuildinTypeSpec.Type.Dynamic:
- case BuildinTypeSpec.Type.Type:
+ 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;
}
arg_resolved = true;
if (Type == null) {
- ResolveAttributeType ();
+ ResolveAttributeType (false);
if (Type == null)
return null;
}
AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location, Report);
}
+ ResolveContext rc = null;
+
MethodSpec ctor;
- // Try if the attribute is simple has been resolved before
- if (PosArguments == null && NamedArguments == null) {
- if (att_cache.TryGetValue (Type, out ctor)) {
- resolve_error = false;
- return 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;
}
- }
- ResolveContext rc = CreateResolveContext ();
- ctor = ResolveConstructor (rc);
- if (ctor == null) {
- return null;
+ if (pos_args == null && ctor.Parameters.IsEmpty)
+ context.Module.AttributeConstructorCache.Add (Type, ctor);
}
//
// Add [module: DefaultCharSet] to all DllImport import attributes
//
var module = context.Module;
- if (Type == module.PredefinedAttributes.DllImport && module.HasDefaultCharSet) {
+ if ((Type == module.PredefinedAttributes.DllImport || Type == module.PredefinedAttributes.UnmanagedFunctionPointer) && module.HasDefaultCharSet) {
+ if (rc == null)
+ rc = CreateResolveContext ();
+
AddModuleCharSet (rc);
}
- if (NamedArguments != null && !ResolveNamedArguments (rc)) {
- return null;
+ if (NamedArguments != null) {
+ if (rc == null)
+ rc = CreateResolveContext ();
+
+ if (!ResolveNamedArguments (rc))
+ return null;
}
resolve_error = false;
return ctor;
}
- protected virtual MethodSpec ResolveConstructor (ResolveContext ec)
+ MethodSpec ResolveConstructor (ResolveContext ec)
{
- if (PosArguments != null) {
+ if (pos_args != null) {
bool dynamic;
- PosArguments.Resolve (ec, out dynamic);
+ pos_args.Resolve (ec, out dynamic);
if (dynamic) {
Error_AttributeArgumentIsDynamic (ec.MemberContext, loc);
return null;
}
}
- return ConstructorLookup (ec, Type, ref PosArguments, loc);
+ 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 seen_names = new List<string> (named_arg_count);
a.Resolve (ec);
- Expression member = Expression.MemberLookup (ec, ec.CurrentType, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
+ Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
if (member == null) {
- member = Expression.MemberLookup (null, ec.CurrentType, Type, name, 0, MemberLookupRestrictions.ExactArity, loc);
+ member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc);
if (member != null) {
// TODO: ec.Report.SymbolRelatedToPreviousError (member);
if (resolve_error)
return DefaultUsageAttribute;
- AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)((Constant) PosArguments [0].Expr).GetValue ());
+ AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets) ((Constant) pos_args[0].Expr).GetValue ());
var field = GetNamedValue ("AllowMultiple") as BoolConstant;
if (field != null)
// 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 ((Constant) PosArguments [0].Expr).GetValue () as string;
+ return ((Constant) pos_args[0].Expr).GetValue () as string;
}
/// <summary>
if (resolve_error)
return null;
- return ((Constant) PosArguments[0].Expr).GetValue () as string;
+ return ((Constant) pos_args[0].Expr).GetValue () as string;
}
/// <summary>
{
if (!arg_resolved) {
// corlib only case when obsolete is used before is resolved
- var c = type.MemberDefinition as Class;
+ var c = Type.MemberDefinition as Class;
if (c != null && !c.HasMembersDefined)
c.Define ();
if (resolve_error)
return null;
- if (PosArguments == null)
+ if (pos_args == null)
return new ObsoleteAttribute ();
- string msg = ((Constant) PosArguments[0].Expr).GetValue () as string;
- if (PosArguments.Count == 1)
+ string msg = ((Constant) pos_args[0].Expr).GetValue () as string;
+ if (pos_args.Count == 1)
return new ObsoleteAttribute (msg);
- return new ObsoleteAttribute (msg, ((BoolConstant) PosArguments[1].Expr).Value);
+ return new ObsoleteAttribute (msg, ((BoolConstant) pos_args[1].Expr).Value);
}
/// <summary>
if (resolve_error)
return false;
- return ((BoolConstant) PosArguments[0].Expr).Value;
+ return ((BoolConstant) pos_args[0].Expr).Value;
}
public TypeSpec GetCoClassAttributeValue ()
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
System.Security.Permissions.SecurityAction GetSecurityActionValue ()
{
- return (SecurityAction) ((Constant) PosArguments[0].Expr).GetValue ();
+ return (SecurityAction) ((Constant) pos_args[0].Expr).GetValue ();
}
/// <summary>
public void ExtractSecurityPermissionSet (MethodSpec ctor, ref SecurityType permissions)
{
#if STATIC
- object[] values = new object [PosArguments.Count];
+ object[] values = new object[pos_args.Count];
for (int i = 0; i < values.Length; ++i)
- values [i] = ((Constant) PosArguments [i].Expr).GetValue ();
+ values[i] = ((Constant) pos_args[i].Expr).GetValue ();
PropertyInfo[] prop;
object[] prop_values;
public CharSet GetCharSetValue ()
{
- return (CharSet)System.Enum.Parse (typeof (CharSet), ((Constant) PosArguments [0].Expr).GetValue ().ToString ());
+ return (CharSet) System.Enum.Parse (typeof (CharSet), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
}
public bool HasField (string fieldName)
// Returns true for MethodImplAttribute with MethodImplOptions.InternalCall value
//
public bool IsInternalCall ()
+ {
+ return (GetMethodImplOptions () & MethodImplOptions.InternalCall) != 0;
+ }
+
+ public MethodImplOptions GetMethodImplOptions ()
{
MethodImplOptions options = 0;
- if (PosArguments.Count == 1) {
- options = (MethodImplOptions) System.Enum.Parse (typeof (MethodImplOptions), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+ 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 & MethodImplOptions.InternalCall) != 0;
+ return options;
}
//
//
public bool IsExplicitLayoutKind ()
{
- if (PosArguments == null || PosArguments.Count != 1)
+ if (pos_args == null || pos_args.Count != 1)
return false;
- var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+ var value = (LayoutKind) System.Enum.Parse (typeof (LayoutKind), ((Constant) pos_args[0].Expr).GetValue ().ToString ());
return value == LayoutKind.Explicit;
}
public Expression GetParameterDefaultValue ()
{
- if (PosArguments == null)
+ if (pos_args == null)
return null;
- return PosArguments[0].Expr;
+ 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>
}
byte[] cdata;
- if (PosArguments == null && named_values == null) {
+ if (pos_args == null && named_values == null) {
cdata = AttributeEncoder.Empty;
} else {
AttributeEncoder encoder = new AttributeEncoder ();
- if (PosArguments != null) {
+ if (pos_args != null) {
var param_types = ctor.Parameters.Types;
- for (int j = 0; j < PosArguments.Count; ++j) {
+ for (int j = 0; j < pos_args.Count; ++j) {
var pt = param_types[j];
- var arg_expr = PosArguments[j].Expr;
+ var arg_expr = pos_args[j].Expr;
if (j == 0) {
- if (Type == predefined.IndexerName || Type == predefined.Conditional) {
- string v = ((StringConstant) arg_expr).Value;
- if (!Tokenizer.IsValidIdentifier (v) || Tokenizer.IsKeyword (v)) {
+ 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 {
"System.AttributeUsage");
}
} else if (Type == predefined.MarshalAs) {
- if (PosArguments.Count == 1) {
- var u_type = (UnmanagedType) System.Enum.Parse (typeof (UnmanagedType), ((Constant) PosArguments[0].Expr).GetValue ().ToString ());
+ 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 (PosArguments.Count == 1) {
- var value = ((Constant) PosArguments[0].Expr).GetValue () as string;
+ 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");
+ Error_AttributeEmitError ("DllName cannot be empty or null");
}
- } else if (Type == predefined.MethodImpl && pt.BuildinType == BuildinTypeSpec.Type.Short &&
+ } 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;
foreach (Attributable target in targets)
target.ApplyAttributeBuilder (this, ctor, cdata, predefined);
} catch (Exception e) {
+ if (e is BadImageFormat && Report.Errors > 0)
+ return;
+
Error_AttributeEmitError (e.Message);
return;
}
// Here we are testing attribute arguments for array usage (error 3016)
if (Owner.IsClsComplianceRequired ()) {
- if (PosArguments != null)
- PosArguments.CheckArrayAsAttribute (context.Module.Compiler);
+ if (pos_args != null)
+ pos_args.CheckArrayAsAttribute (context.Module.Compiler);
if (NamedArguments == null)
return;
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 null;
return e.TypeArgument;
}
-
- public override Expression CreateExpressionTree (ResolveContext ec)
- {
- throw new NotSupportedException ("ET");
- }
-
- protected override Expression DoResolve (ResolveContext ec)
- {
- throw new NotImplementedException ();
- }
-
- public override void Emit (EmitContext ec)
- {
- 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 class Attributes
{
- 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;
- }
-
- 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 = attrs;
}
+ public void AddAttribute (Attribute attr)
+ {
+ Attrs.Add (attr);
+ }
+
public void AddAttributes (List<Attribute> attrs)
{
Attrs.AddRange (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 bool HasResolveError()
+ {
+ foreach (var a in Attrs) {
+ if (a.ResolveError)
+ return true;
+ }
+
+ return false;
+ }
+
public Attribute Search (PredefinedAttribute t)
{
return Search (null, t);
if (explicitTarget != null && a.ExplicitTarget != explicitTarget)
continue;
- if (a.ResolveType () == t)
+ if (a.ResolveTypeForComparison () == t)
return a;
}
return null;
List<Attribute> ar = null;
foreach (Attribute a in Attrs) {
- if (a.ResolveType () == t) {
+ if (a.ResolveTypeForComparison () == t) {
if (ar == null)
ar = new List<Attribute> (Attrs.Count);
ar.Add (a);
public EncodedTypeProperties Encode (TypeSpec type)
{
- switch (type.BuildinType) {
- case BuildinTypeSpec.Type.Bool:
+ switch (type.BuiltinType) {
+ case BuiltinTypeSpec.Type.Bool:
Encode ((byte) 0x02);
break;
- case BuildinTypeSpec.Type.Char:
+ case BuiltinTypeSpec.Type.Char:
Encode ((byte) 0x03);
break;
- case BuildinTypeSpec.Type.SByte:
+ case BuiltinTypeSpec.Type.SByte:
Encode ((byte) 0x04);
break;
- case BuildinTypeSpec.Type.Byte:
+ case BuiltinTypeSpec.Type.Byte:
Encode ((byte) 0x05);
break;
- case BuildinTypeSpec.Type.Short:
+ case BuiltinTypeSpec.Type.Short:
Encode ((byte) 0x06);
break;
- case BuildinTypeSpec.Type.UShort:
+ case BuiltinTypeSpec.Type.UShort:
Encode ((byte) 0x07);
break;
- case BuildinTypeSpec.Type.Int:
+ case BuiltinTypeSpec.Type.Int:
Encode ((byte) 0x08);
break;
- case BuildinTypeSpec.Type.UInt:
+ case BuiltinTypeSpec.Type.UInt:
Encode ((byte) 0x09);
break;
- case BuildinTypeSpec.Type.Long:
+ case BuiltinTypeSpec.Type.Long:
Encode ((byte) 0x0A);
break;
- case BuildinTypeSpec.Type.ULong:
+ case BuiltinTypeSpec.Type.ULong:
Encode ((byte) 0x0B);
break;
- case BuildinTypeSpec.Type.Float:
+ case BuiltinTypeSpec.Type.Float:
Encode ((byte) 0x0C);
break;
- case BuildinTypeSpec.Type.Double:
+ case BuiltinTypeSpec.Type.Double:
Encode ((byte) 0x0D);
break;
- case BuildinTypeSpec.Type.String:
+ case BuiltinTypeSpec.Type.String:
Encode ((byte) 0x0E);
break;
- case BuildinTypeSpec.Type.Type:
+ case BuiltinTypeSpec.Type.Type:
Encode ((byte) 0x50);
break;
- case BuildinTypeSpec.Type.Object:
+ case BuiltinTypeSpec.Type.Object:
Encode ((byte) 0x51);
break;
- case BuildinTypeSpec.Type.Dynamic:
+ case BuiltinTypeSpec.Type.Dynamic:
Encode ((byte) 0x51);
return EncodedTypeProperties.DynamicType;
default:
Encode (type.MemberDefinition.IsImported ? old_type.AssemblyQualifiedName : old_type.FullName);
}
+ public void EncodeTypeName (TypeContainer type)
+ {
+ Encode (type.GetSignatureForMetadata ());
+ }
+
+
//
// Encodes single property named argument per call
//
/// </summary>
static class AttributeTester
{
- public enum Result {
- Ok,
- RefOutArrayError,
- ArrayArrayError
- }
-
- /// <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)
- {
- TypeSpec [] types_a = pa.Types;
- TypeSpec [] 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) {
- TypeSpec aType = types_a [i];
- TypeSpec bType = types_b [i];
-
- var ac_a = aType as ArrayContainer;
- var ac_b = aType as ArrayContainer;
-
- if (ac_a != null && ac_b != null) {
- if (ac_a.Rank != ac_b.Rank && ac_a.Element == ac_b.Element) {
- result = Result.RefOutArrayError;
- continue;
- }
-
- if (ac_a.Element.IsArray || ac_b.Element.IsArray) {
- result = Result.ArrayArrayError;
- continue;
- }
- }
-
- if (aType != bType)
- return Result.Ok;
-
- 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;
- }
-
/// <summary>
/// Common method for Obsolete error/warning reporting.
/// </summary>
public readonly PredefinedAttribute DefaultParameterValue;
public readonly PredefinedAttribute OptionalParameter;
public readonly PredefinedAttribute UnverifiableCode;
-
- // New in .NET 2.0
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 PredefinedDynamicAttribute Dynamic;
+ // New in .NET 4.5
+ public readonly PredefinedStateMachineAttribute AsyncStateMachine;
+ public readonly PredefinedStateMachineAttribute IteratorStateMachine;
+
//
// Optional types which are used as types and for member lookup
//
public readonly PredefinedDecimalAttribute DecimalConstant;
public readonly PredefinedAttribute StructLayout;
public readonly PredefinedAttribute FieldOffset;
+ 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 (Location.Null);
- Out.Resolve (Location.Null);
+ ParamArray.Resolve ();
+ Out.Resolve ();
Obsolete = new PredefinedAttribute (module, "System", "ObsoleteAttribute");
DllImport = new PredefinedAttribute (module, "System.Runtime.InteropServices", "DllImportAttribute");
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");
StructLayout = new PredefinedAttribute (module, "System.Runtime.InteropServices", "StructLayoutAttribute");
FieldOffset = new PredefinedAttribute (module, "System.Runtime.InteropServices", "FieldOffsetAttribute");
+ AsyncStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "AsyncStateMachineAttribute");
+ IteratorStateMachine = new PredefinedStateMachineAttribute (module, "System.Runtime.CompilerServices", "IteratorStateMachineAttribute") {
+ IsIterator = true
+ };
+
+ 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;
public class PredefinedAttribute : PredefinedType
{
protected MethodSpec ctor;
- List<PropertySpec> properties;
public PredefinedAttribute (ModuleContainer module, string ns, string name)
: base (module, MemberKind.Class, ns, name)
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public void EmitAttribute (FieldBuilder builder, AttributeEncoder argsEncoded)
- {
- builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
- }
-
public void EmitAttribute (TypeBuilder builder)
{
if (ResolveBuilder ())
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public void EmitAttribute (TypeBuilder builder, AttributeEncoder argsEncoded)
- {
- builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
- }
-
public void EmitAttribute (AssemblyBuilder builder)
{
if (ResolveBuilder ())
builder.SetCustomAttribute (GetCtorMetaInfo (), AttributeEncoder.Empty);
}
- public void EmitAttribute (ParameterBuilder builder, AttributeEncoder argsEncoded)
- {
- builder.SetCustomAttribute (GetCtorMetaInfo (), argsEncoded.ToArray ());
- }
-
ConstructorInfo GetCtorMetaInfo ()
{
return (ConstructorInfo) ctor.GetMetaInfo ();
}
- public PropertySpec GetProperty (string name, TypeSpec memberType, Location loc)
- {
- PropertySpec spec;
-
- if (properties != null) {
- spec = properties.Find (l => l.Name == name);
- } else {
- spec = null;
- }
-
- if (spec == null) {
- spec = TypeManager.GetPredefinedProperty (type, name, loc, memberType);
-
- if (spec != null) {
- if (properties == null) {
- properties = new List<PropertySpec> ();
- }
-
- properties.Add (spec);
- }
- }
-
- return spec;
- }
-
public bool ResolveBuilder ()
{
if (ctor != null)
if (!IsDefined)
return false;
- ctor = TypeManager.GetPredefinedConstructor (type, Location.Null, TypeSpec.EmptyTypes);
+ ctor = (MethodSpec) MemberCache.FindMember (type, MemberFilter.Constructor (ParametersCompiled.EmptyReadOnlyParameters), BindingRestriction.DeclaredOnly);
return ctor != null;
}
+ }
- public bool ResolveConstructor (Location loc, params TypeSpec[] argType)
+ public class PredefinedDebuggerBrowsableAttribute : PredefinedAttribute
+ {
+ public PredefinedDebuggerBrowsableAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
{
- if (ctor != null)
- throw new InternalErrorException ("Predefined ctor redefined");
+ }
- if (Resolve (loc) == null)
- return false;
+ public void EmitAttribute (FieldBuilder builder, System.Diagnostics.DebuggerBrowsableState state)
+ {
+ var ctor = module.PredefinedMembers.DebuggerBrowsableAttributeCtor.Get ();
+ if (ctor == null)
+ return;
- ctor = TypeManager.GetPredefinedConstructor (type, loc, argType);
- return ctor != null;
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.Encode ((int) state);
+ encoder.EncodeEmptyNamedArguments ();
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
}
}
public void EmitAttribute (ParameterBuilder builder, decimal value, Location loc)
{
- if (Resolve (loc) == null)
- return;
-
- if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+ var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
+ if (ctor == null)
return;
int[] bits = decimal.GetBits (value);
encoder.Encode ((uint) bits[0]);
encoder.EncodeEmptyNamedArguments ();
- EmitAttribute (builder, encoder);
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
}
public void EmitAttribute (FieldBuilder builder, decimal value, Location loc)
{
- if (Resolve (loc) == null)
- return;
-
- if (ctor == null && !ResolveConstructor (loc, TypeManager.byte_type, TypeManager.byte_type, TypeManager.uint32_type, TypeManager.uint32_type, TypeManager.uint32_type))
+ var ctor = module.PredefinedMembers.DecimalConstantAttributeCtor.Resolve (loc);
+ if (ctor == null)
return;
int[] bits = decimal.GetBits (value);
encoder.Encode ((uint) bits[0]);
encoder.EncodeEmptyNamedArguments ();
- EmitAttribute (builder, encoder);
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
+ }
+ }
+
+ public class PredefinedStateMachineAttribute : PredefinedAttribute
+ {
+ public PredefinedStateMachineAttribute (ModuleContainer module, string ns, string name)
+ : base (module, ns, name)
+ {
+ }
+
+ public bool IsIterator { get; set; }
+
+ public void EmitAttribute (MethodBuilder builder, StateMachine type)
+ {
+ var predefined_ctor = IsIterator ?
+ module.PredefinedMembers.IteratorStateMachineAttributeCtor :
+ module.PredefinedMembers.AsyncStateMachineAttributeCtor;
+
+ var ctor = predefined_ctor.Get ();
+
+ if (ctor == null)
+ return;
+
+ AttributeEncoder encoder = new AttributeEncoder ();
+ encoder.EncodeTypeName (type);
+ encoder.EncodeEmptyNamedArguments ();
+
+ builder.SetCustomAttribute ((ConstructorInfo) ctor.GetMetaInfo (), encoder.ToArray ());
}
}
return transform.ToArray ();
}
- if (t == InternalType.Dynamic)
+ if (t.BuiltinType == BuiltinTypeSpec.Type.Dynamic)
return new bool[] { true };
return null;
if (tctor != null)
return true;
- if (Resolve (loc) == null)
- return false;
-
- tctor = TypeManager.GetPredefinedConstructor (type, Location.Null, ArrayContainer.MakeType (module, TypeManager.bool_type));
+ tctor = module.PredefinedMembers.DynamicAttributeCtor.Resolve (loc);
return tctor != null;
}
}