public AttributeTargets Target;
public readonly string Name;
+ public readonly Expression LeftExpr;
+ public readonly string Identifier;
+
public readonly ArrayList Arguments;
public readonly Location Location;
public Type Type;
+ bool resolve_error;
+
// Is non-null if type is AttributeUsageAttribute
AttributeUsageAttribute usage_attribute;
static PtrHashtable usage_attr_cache = new PtrHashtable ();
- public Attribute (string target, string name, ArrayList args, Location loc)
+ public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc)
{
- Name = name;
+ LeftExpr = left_expr;
+ Identifier = identifier;
+ Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier;
Arguments = args;
Location = loc;
ExplicitTarget = target;
{
Report.Error (617, Location, "Invalid attribute argument: '{0}'. Argument must be fields " +
"fields which are not readonly, static or const; or read-write instance properties.",
- Name);
+ name);
}
- static void Error_AttributeArgumentNotValid (Location loc)
+ static void Error_AttributeArgumentNotValid (string extra, Location loc)
{
Report.Error (182, loc,
"An attribute argument must be a constant expression, typeof " +
- "expression or array creation expression");
+ "expression or array creation expression" + extra);
}
+ static void Error_AttributeArgumentNotValid (Location loc)
+ {
+ Error_AttributeArgumentNotValid ("", loc);
+ }
+
static void Error_TypeParameterInAttribute (Location loc)
{
Report.Error (
"Could not find a constructor for this argument list.");
}
+ void ResolvePossibleAttributeTypes (EmitContext ec, out Type t1, out Type t2)
+ {
+ t1 = null;
+ t2 = null;
+
+ FullNamedExpression n1 = null;
+ FullNamedExpression n2 = null;
+ string IdentifierAttribute = Identifier + "Attribute";
+ if (LeftExpr == null) {
+ n1 = new SimpleName (Identifier, Location).ResolveAsTypeStep (ec);
+
+ // FIXME: Shouldn't do this for quoted attributes: [@A]
+ n2 = new SimpleName (IdentifierAttribute, Location).ResolveAsTypeStep (ec);
+ } else {
+ FullNamedExpression l = LeftExpr.ResolveAsTypeStep (ec);
+ if (l == null) {
+ Report.Error (246, Location, "Couldn't find namespace or type '{0}'", LeftExpr);
+ return;
+ }
+ n1 = new MemberAccess (l, Identifier, Location).ResolveNamespaceOrType (ec, true);
+
+ // FIXME: Shouldn't do this for quoted attributes: [X.@A]
+ n2 = new MemberAccess (l, IdentifierAttribute, Location).ResolveNamespaceOrType (ec, true);
+ }
+
+ TypeExpr te1 = n1 == null ? null : n1 as TypeExpr;
+ TypeExpr te2 = n2 == null ? null : n2 as TypeExpr;
+
+ if (te1 != null)
+ t1 = te1.ResolveType (ec);
+ if (te2 != null)
+ t2 = te2.ResolveType (ec);
+ }
+
/// <summary>
/// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
/// </summary>
- protected virtual Type CheckAttributeType (EmitContext ec)
+ Type CheckAttributeType (EmitContext ec)
{
- string NameAttribute = Name + "Attribute";
- Type t1 = ec.ResolvingTypeTree
- ? ec.DeclSpace.FindType (Location, Name)
- : RootContext.LookupType (ec.DeclSpace, Name, true, Location);
+ Type t1, t2;
+ ResolvePossibleAttributeTypes (ec, out t1, out t2);
- // FIXME: Shouldn't do this for quoted attributes: [@A]
- Type t2 = ec.ResolvingTypeTree
- ? ec.DeclSpace.FindType (Location, NameAttribute)
- : RootContext.LookupType (ec.DeclSpace, NameAttribute, true, Location);
+ string NameAttribute = Name + "Attribute";
String err0616 = null;
if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
"Could not find attribute '" + Name
+ "' (are you missing a using directive or an assembly reference ?)");
+ resolve_error = true;
return null;
}
- public Type ResolveType (EmitContext ec)
+ public virtual Type ResolveType (EmitContext ec)
{
if (Type == null)
Type = CheckAttributeType (ec);
return false;
}
- public CustomAttributeBuilder Resolve (EmitContext ec)
+ public virtual CustomAttributeBuilder Resolve (EmitContext ec)
{
+ if (resolve_error)
+ return null;
+
+ resolve_error = true;
+
Type oldType = Type;
// Sanity check.
if (DoCompares){
if (usage_attr) {
+ if ((int)val == 0) {
+ Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
+ return null;
+ }
usage_attribute = new AttributeUsageAttribute ((AttributeTargets)val);
} else if (MethodImplAttr) {
this.ImplOptions = (MethodImplOptions) val;
// of type object
//
- ParameterData pd = Invocation.GetParameterData (constructor);
+ ParameterData pd = TypeManager.GetParameterData (constructor);
int last_real_param = pd.Count;
if (pd.HasParams) {
return null;
}
+ object value = pos_values [j];
+ if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+ bool fail;
+ pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
+ if (fail) {
+ // TODO: Can failed ?
+ throw new NotImplementedException ();
+ }
+ }
+
if (j < last_real_param)
continue;
else
cb = new CustomAttributeBuilder (
(ConstructorInfo) constructor, pos_values);
- } catch (NullReferenceException) {
- //
- // Don't know what to do here
- //
- Report.Warning (
- -101, Location, "NullReferenceException while trying to create attribute." +
- "Something's wrong!");
} catch (Exception e) {
//
// Sample:
// [DefaultValue (CollectionChangeAction.Add)]
// class X { static void Main () {} }
//
- Report.Warning (
- -23, Location, "The compiler can not encode this attribute in .NET due to a bug in the .NET runtime. Try the Mono runtime. The exception was: " + e.Message);
+ Error_AttributeArgumentNotValid (Location);
+ return null;
}
+ resolve_error = false;
return cb;
}
/// </summary>
public string GetIndexerAttributeValue (EmitContext ec)
{
- if (pos_values == null) {
+ if (pos_values == null)
// 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 (ec);
- }
return pos_values [0] as string;
}
/// <summary>
/// Returns condition of ConditionalAttribute
/// </summary>
- public string GetConditionalAttributeValue (DeclSpace ds)
+ public string GetConditionalAttributeValue (EmitContext ec)
{
- if (pos_values == null) {
- EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
-
+ if (pos_values == null)
// 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 (ec);
- }
// Some error occurred
if (pos_values [0] == null)
/// <summary>
/// Creates the instance of ObsoleteAttribute from this attribute instance
/// </summary>
- public ObsoleteAttribute GetObsoleteAttribute (DeclSpace ds)
+ public ObsoleteAttribute GetObsoleteAttribute (EmitContext ec)
{
- if (pos_values == null) {
- EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
-
+ if (pos_values == null)
// 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 (ec);
- }
// Some error occurred
if (pos_values == null)
/// before ApplyAttribute. We need to resolve the arguments.
/// This situation occurs when class deps is differs from Emit order.
/// </summary>
- public bool GetClsCompliantAttributeValue (DeclSpace ds)
+ public bool GetClsCompliantAttributeValue (EmitContext ec)
{
- if (pos_values == null) {
- EmitContext ec = new EmitContext (ds, ds, Location, null, null, 0, false);
-
+ if (pos_values == null)
// 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 (ec);
- }
// Some error occurred
if (pos_values [0] == null)
}
}
- IPermission perm = sa.CreatePermission ();
- SecurityAction action;
+ IPermission perm;
+ try {
+ perm = sa.CreatePermission ();
+ }
+ catch (Exception e) {
+ Error_AttributeEmitError (String.Format ("{0} was thrown during attribute processing: {1}", e.GetType (), e.Message));
+ return;
+ }
+ SecurityAction action = GetSecurityActionValue ();
// IS is correct because for corlib we are using an instance from old corlib
- if (perm is System.Security.CodeAccessPermission) {
- action = GetSecurityActionValue ();
- } else {
- switch (GetSecurityActionValue ()) {
+ if (!(perm is System.Security.CodeAccessPermission)) {
+ switch (action) {
case SecurityAction.Demand:
action = (SecurityAction)13;
break;
case SecurityAction.InheritanceDemand:
action = (SecurityAction)15;
break;
- default:
- Error_AttributeEmitError ("Invalid SecurityAction for non-Code Access Security permission");
- return;
}
}
PermissionSet ps = (PermissionSet)permissions [action];
if (ps == null) {
- ps = new PermissionSet (PermissionState.None);
+ 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.Unrestricted) {
+ ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
+ permissions [action] = ps;
}
- ps.AddPermission (sa.CreatePermission ());
+ ps.AddPermission (perm);
}
object GetValue (object value)
Error_AttributeArgumentNotValid (Location);
return null;
}
-
+ if (dll_name == null || dll_name == ""){
+ Error_AttributeArgumentNotValid (": DllImport requires a non-empty string", Location);
+ return null;
+ }
+
// Now we process the named arguments
CallingConvention cc = CallingConvention.Winapi;
CharSet charset = CharSet.Ansi;
{
public readonly NamespaceEntry ns;
- public GlobalAttribute (TypeContainer container, string target, string name, ArrayList args, Location loc):
- base (target, name, args, loc)
+ public GlobalAttribute (TypeContainer container, string target,
+ Expression left_expr, string identifier, ArrayList args, Location loc):
+ base (target, left_expr, identifier, args, loc)
{
ns = container.NamespaceEntry;
}
- protected override Type CheckAttributeType (EmitContext ec)
+ void Enter ()
{
// RootContext.Tree.Types 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.
//
- // FIXME: Check every place the NamespaceEntry of RootContext.Tree.Types is used
- // to ensure the right one is used.
- if (ec.DeclSpace == RootContext.Tree.Types)
- ec.DeclSpace.NamespaceEntry = ns;
+ // Precondition: RootContext.Tree.Types == null
+
+ if (RootContext.Tree.Types.NamespaceEntry != null)
+ throw new InternalErrorException (Location + " non-null NamespaceEntry");
+
+ RootContext.Tree.Types.NamespaceEntry = ns;
+ }
+
+ void Leave ()
+ {
+ RootContext.Tree.Types.NamespaceEntry = null;
+ }
+
+ public override Type ResolveType (EmitContext ec)
+ {
+ Enter ();
+ Type retval = base.ResolveType (ec);
+ Leave ();
+ return retval;
+ }
- return base.CheckAttributeType (ec);
+ public override CustomAttributeBuilder Resolve (EmitContext ec)
+ {
+ Enter ();
+ CustomAttributeBuilder retval = base.Resolve (ec);
+ Leave ();
+ return retval;
}
}
static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+ static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+
+ static object TRUE = new object ();
+ static object FALSE = new object ();
private AttributeTester ()
{
}
analyzed_types.Add (type, result ? TRUE : FALSE);
return result;
- }
+ }
+
+ /// <summary>
+ /// Returns IFixedBuffer implementation if field is fixed buffer else null.
+ /// </summary>
+ public static IFixedBuffer GetFixedBuffer (FieldInfo fi)
+ {
+ FieldBase fb = TypeManager.GetField (fi);
+ if (fb != null) {
+ return fb as IFixedBuffer;
+ }
- static object TRUE = new object ();
- static object FALSE = new object ();
+#if NET_2_0
+ object o = fixed_buffer_cache [fi];
+ if (o == null) {
+ if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) {
+ fixed_buffer_cache.Add (fi, FALSE);
+ return null;
+ }
+
+ IFixedBuffer iff = new FixedFieldExternal (fi);
+ fixed_buffer_cache.Add (fi, iff);
+ return iff;
+ }
+
+ if (o == FALSE)
+ return null;
+
+ return (IFixedBuffer)o;
+#else
+ return null;
+#endif
+ }
public static void VerifyModulesClsCompliance ()
{
if (mb.DeclaringType is TypeBuilder)
return null;
+ PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo;
+ if (pi != null)
+ return GetMemberObsoleteAttribute (pi);
+
return GetMemberObsoleteAttribute (mb);
}