using System.Security;
using System.Security.Permissions;
using System.Text;
+using System.IO;
namespace Mono.CSharp {
public readonly string ExplicitTarget;
public AttributeTargets Target;
+ // TODO: remove this member
public readonly string Name;
public readonly Expression LeftExpr;
public readonly string Identifier;
bool resolve_error;
- public AttributeUsageAttribute UsageAttribute;
- public static AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
+ readonly bool nameEscaped;
+
+ static AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All);
+ static Assembly orig_sec_assembly;
- MethodImplOptions ImplOptions;
- UnmanagedType UnmanagedType;
- CustomAttributeBuilder cb;
-
// non-null if named args present after Resolve () is called
PropertyInfo [] prop_info_arr;
FieldInfo [] field_info_arr;
static PtrHashtable usage_attr_cache = new PtrHashtable ();
- public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc)
+ public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped)
{
LeftExpr = left_expr;
Identifier = identifier;
Arguments = args;
Location = loc;
ExplicitTarget = target;
+ this.nameEscaped = nameEscaped;
}
void Error_InvalidNamedArgument (string name)
{
- 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);
+ Report.Error (617, Location, "`{0}' is not a valid named attribute argument. Named attribute arguments must be fields which are not readonly, static, const or read-write properties which are public and not static",
+ name);
+ }
+
+ void Error_InvalidNamedAgrumentType (string name)
+ {
+ Report.Error (655, Location, "`{0}' is not a valid named attribute argument because it is not a valid attribute parameter type", name);
}
static void Error_AttributeArgumentNotValid (string extra, Location loc)
/// </summary>
public void Error_AttributeEmitError (string inner)
{
- Report.Error (647, Location, "Error emitting '{0}' attribute because '{1}'", Name, inner);
+ Report.Error (647, Location, "Error during emitting `{0}' attribute. The reason is `{1}'", TypeManager.CSharpName (Type), inner);
}
public void Error_InvalidSecurityParent ()
Error_AttributeEmitError ("it is attached to invalid parent");
}
- void Error_AttributeConstructorMismatch ()
+ protected virtual FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent)
{
- Report.Error (-6, Location,
- "Could not find a constructor for this argument list.");
+ return expr.ResolveAsTypeTerminal (ec, silent);
}
- void ResolvePossibleAttributeTypes (EmitContext ec, out Type t1, out Type t2)
+ protected virtual FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent)
{
- t1 = null;
- t2 = null;
+ return expr.ResolveAsTypeStep (ec, silent);
+ }
- FullNamedExpression n1 = null;
- FullNamedExpression n2 = null;
- string IdentifierAttribute = Identifier + "Attribute";
+ Type ResolvePossibleAttributeType (EmitContext ec, string name, bool silent, ref bool is_attr)
+ {
+ FullNamedExpression fn;
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);
+ fn = ResolveAsTypeTerminal (new SimpleName (name, Location), ec, silent);
} 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);
+ fn = ResolveAsTypeStep (LeftExpr, ec, silent);
+ if (fn == null)
+ return null;
+ fn = new MemberAccess (fn, name, Location).ResolveAsTypeTerminal (ec, silent);
}
- TypeExpr te1 = n1 == null ? null : n1 as TypeExpr;
- TypeExpr te2 = n2 == null ? null : n2 as TypeExpr;
+ TypeExpr te = fn as TypeExpr;
+ if (te == null)
+ return null;
- if (te1 != null)
- t1 = te1.ResolveType (ec);
- if (te2 != null)
- t2 = te2.ResolveType (ec);
+ Type t = te.Type;
+ if (t.IsSubclassOf (TypeManager.attribute_type)) {
+ is_attr = true;
+ } else if (!silent) {
+ 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>
- Type CheckAttributeType (EmitContext ec)
+ /// Tries to resolve the type of the attribute. Flags an error if it can't, and complain is true.
+ /// </summary>
+ void ResolveAttributeType (EmitContext ec)
{
- Type t1, t2;
-
- ResolvePossibleAttributeTypes (ec, out t1, out t2);
-
- string NameAttribute = Name + "Attribute";
+ bool t1_is_attr = false;
+ Type t1 = ResolvePossibleAttributeType (ec, Identifier, true, ref t1_is_attr);
- String err0616 = null;
+ bool t2_is_attr = false;
+ Type t2 = nameEscaped ? null :
+ ResolvePossibleAttributeType (ec, Identifier + "Attribute", true, ref t2_is_attr);
- if (t1 != null && ! t1.IsSubclassOf (TypeManager.attribute_type)) {
- t1 = null;
- err0616 = "'" + Name + "': is not an attribute class";
- }
- if (t2 != null && ! t2.IsSubclassOf (TypeManager.attribute_type)) {
- t2 = null;
- err0616 = (err0616 != null)
- ? "Neither '" + Name + "' nor '" + NameAttribute +"' is an attribute class"
- : "'" + Name + "Attribute': is not an attribute class";
+ if (t1_is_attr && t2_is_attr) {
+ Report.Error (1614, Location, "`{0}' is ambiguous between `{0}' and `{0}Attribute'. Use either `@{0}' or `{0}Attribute'", GetSignatureForError ());
+ resolve_error = true;
+ return;
}
- if (t1 != null && t2 != null) {
- Report.Error(1614, Location, "'" + Name + "': is ambiguous; "
- + " use either '@" + Name + "' or '" + NameAttribute + "'");
- return null;
+ if (t1_is_attr) {
+ Type = t1;
+ return;
}
- if (t1 != null)
- return t1;
- if (t2 != null)
- return t2;
- if (err0616 != null) {
- Report.Error (616, Location, err0616);
- return null;
+ if (t2_is_attr) {
+ Type = t2;
+ return;
}
- Report.Error (246, Location,
- "Could not find attribute '" + Name
- + "' (are you missing a using directive or an assembly reference ?)");
+ if (t1 == null && t2 == null)
+ ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);
+ if (t1 != null)
+ ResolvePossibleAttributeType (ec, Identifier, false, ref t1_is_attr);
+ if (t2 != null)
+ ResolvePossibleAttributeType (ec, Identifier + "Attribute", false, ref t2_is_attr);
resolve_error = true;
- return null;
}
public virtual Type ResolveType (EmitContext ec)
{
- if (Type == null)
- Type = CheckAttributeType (ec);
+ if (Type == null && !resolve_error)
+ ResolveAttributeType (ec);
return Type;
}
- /// <summary>
- /// Validates the guid string
- /// </summary>
- bool ValidateGuid (string guid)
+ public string GetSignatureForError ()
{
- try {
- new Guid (guid);
- return true;
- } catch {
- Report.Error (647, Location, "Format of GUID is invalid: " + guid);
- return false;
- }
- }
-
- string GetFullMemberName (string member)
- {
- return Type.FullName + '.' + member;
+ return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier;
}
//
//
public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result)
{
- if (e is EnumConstant) {
- if (RootContext.StdLib)
- result = ((EnumConstant)e).GetValueAsEnumType ();
- else
- result = ((EnumConstant)e).GetValue ();
-
- return true;
- }
-
Constant constant = e as Constant;
if (constant != null) {
- if (e.Type != arg_type) {
- constant = Const.ChangeType (loc, constant, arg_type);
- if (constant == null) {
- result = null;
- Error_AttributeArgumentNotValid (loc);
- return false;
- }
+ constant = constant.ToType (arg_type, loc);
+ if (constant == null) {
+ result = null;
+ return false;
}
- result = constant.GetValue ();
+ result = constant.GetTypedValue ();
return true;
} else if (e is TypeOf) {
result = ((TypeOf) e).TypeArg;
} else if (e is EmptyCast) {
Expression child = ((EmptyCast)e).Child;
return GetAttributeArgumentExpression (child, loc, child.Type, out result);
+ } else if (e is As) {
+ As as_e = (As) e;
+ return GetAttributeArgumentExpression (as_e.Expr, loc, as_e.ProbeType.Type, out result);
}
result = null;
Error_AttributeArgumentNotValid (loc);
return false;
}
-
- public virtual CustomAttributeBuilder Resolve (EmitContext ec)
+
+ bool IsValidArgumentType (Type t)
+ {
+ if (t.IsArray)
+ t = t.GetElementType ();
+
+ return TypeManager.IsPrimitiveType (t) ||
+ TypeManager.IsEnumType (t) ||
+ t == TypeManager.string_type ||
+ t == TypeManager.object_type ||
+ t == TypeManager.type_type;
+ }
+
+ // Cache for parameter-less attributes
+ static PtrHashtable att_cache = new PtrHashtable ();
+
+ public CustomAttributeBuilder Resolve (EmitContext ec)
{
if (resolve_error)
return null;
resolve_error = true;
- Type oldType = Type;
-
- // Sanity check.
- Type = CheckAttributeType (ec); // TODO: I really don't think we need such expensive double check
+ if (Type == null) {
+ ResolveAttributeType (ec);
+ if (Type == null)
+ return null;
+ }
- if (oldType == null && Type == null)
- return null;
- if (oldType != null && oldType != Type){
- Report.Error (-27, Location,
- "Attribute {0} resolved to different types at different times: {1} vs. {2}",
- Name, oldType, Type);
+ if (Type.IsAbstract) {
+ Report.Error (653, Location, "Cannot apply attribute class `{0}' because it is abstract", GetSignatureForError ());
return null;
}
- if (Type.IsAbstract) {
- Report.Error (653, Location, "Cannot apply attribute class '{0}' because it is abstract", Name);
+ if (Arguments == null) {
+ object o = att_cache [Type];
+ if (o != null) {
+ resolve_error = false;
+ return (CustomAttributeBuilder)o;
+ }
+ }
+
+ ConstructorInfo ctor = ResolveArguments (ec);
+ if (ctor == null)
+ return null;
+
+ CustomAttributeBuilder cb;
+
+ try {
+ if (prop_info_arr != null || field_info_arr != null) {
+ cb = new CustomAttributeBuilder (
+ ctor, pos_values,
+ prop_info_arr, prop_values_arr,
+ field_info_arr, field_values_arr);
+ } else {
+ cb = new CustomAttributeBuilder (
+ ctor, pos_values);
+
+ if (pos_values.Length == 0)
+ att_cache.Add (Type, cb);
+ }
+ }
+ catch (Exception) {
+ Error_AttributeArgumentNotValid (Location);
return null;
}
- bool MethodImplAttr = false;
- bool MarshalAsAttr = false;
- bool GuidAttr = false;
- bool usage_attr = false;
-
- bool DoCompares = true;
-
- //
- // If we are a certain special attribute, we
- // set the information accordingly
- //
-
- if (Type == TypeManager.attribute_usage_type)
- usage_attr = true;
- else if (Type == TypeManager.methodimpl_attr_type)
- MethodImplAttr = true;
- else if (Type == TypeManager.marshal_as_attr_type)
- MarshalAsAttr = true;
- else if (Type == TypeManager.guid_attr_type)
- GuidAttr = true;
- else
- DoCompares = false;
+ resolve_error = false;
+ return cb;
+ }
+ protected virtual ConstructorInfo ResolveArguments (EmitContext ec)
+ {
// Now we extract the positional and named arguments
- ArrayList pos_args = new ArrayList ();
- ArrayList named_args = new ArrayList ();
+ ArrayList pos_args = null;
+ ArrayList named_args = null;
int pos_arg_count = 0;
+ int named_arg_count = 0;
if (Arguments != null) {
pos_args = (ArrayList) Arguments [0];
if (pos_args != null)
pos_arg_count = pos_args.Count;
- if (Arguments.Count > 1)
+ if (Arguments.Count > 1) {
named_args = (ArrayList) Arguments [1];
+ named_arg_count = named_args.Count;
+ }
}
pos_values = new object [pos_arg_count];
pos_values [i] = val;
- if (DoCompares){
- if (usage_attr) {
- if ((int)val == 0) {
- Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
- return null;
- }
- UsageAttribute = new AttributeUsageAttribute ((AttributeTargets)val);
- } else if (MethodImplAttr) {
- this.ImplOptions = (MethodImplOptions) val;
- } else if (GuidAttr){
- //
- // we will later check the validity of the type
- //
- if (val is string){
- if (!ValidateGuid ((string) val))
- return null;
- }
-
- } else if (MarshalAsAttr)
- this.UnmanagedType =
- (System.Runtime.InteropServices.UnmanagedType) val;
+ if (i == 0 && Type == TypeManager.attribute_usage_type && (int)val == 0) {
+ Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute");
+ return null;
}
}
ArrayList prop_infos = null;
ArrayList field_values = null;
ArrayList prop_values = null;
+ Hashtable seen_names = null;
- if (named_args.Count > 0) {
+ if (named_arg_count > 0) {
field_infos = new ArrayList ();
prop_infos = new ArrayList ();
field_values = new ArrayList ();
prop_values = new ArrayList ();
- }
- Hashtable seen_names = new Hashtable();
+ seen_names = new Hashtable();
+ }
- for (i = 0; i < named_args.Count; i++) {
+ for (i = 0; i < named_arg_count; i++) {
DictionaryEntry de = (DictionaryEntry) named_args [i];
string member_name = (string) de.Key;
Argument a = (Argument) de.Value;
Location);
if (member != null) {
- Report.Error (122, Location, "'{0}' is inaccessible due to its protection level", GetFullMemberName (member_name));
+ Expression.ErrorIsInaccesible (Location, member.GetSignatureForError ());
return null;
}
}
if (member == null){
- Report.Error (117, Location, "Attribute `{0}' does not contain a definition for `{1}'",
+ Report.Error (117, Location, "`{0}' does not contain a definition for `{1}'",
Type, member_name);
return null;
}
return null;
}
+ if (!IsValidArgumentType (pi.PropertyType)) {
+ Report.SymbolRelatedToPreviousError (pi);
+ Error_InvalidNamedAgrumentType (member_name);
+ return null;
+ }
+
object value;
if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value))
return null;
- if (UsageAttribute != null) {
- if (member_name == "AllowMultiple")
- UsageAttribute.AllowMultiple = (bool) value;
- if (member_name == "Inherited")
- UsageAttribute.Inherited = (bool) value;
- }
-
prop_values.Add (value);
prop_infos.Add (pi);
return null;
}
+ if (!IsValidArgumentType (fi.FieldType)) {
+ Report.SymbolRelatedToPreviousError (fi);
+ Error_InvalidNamedAgrumentType (member_name);
+ return null;
+ }
+
object value;
if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value))
return null;
BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly,
Location);
- if (mg == null) {
- Error_AttributeConstructorMismatch ();
- return null;
- }
-
MethodBase constructor = Invocation.OverloadResolve (
ec, (MethodGroupExpr) mg, pos_args, false, Location);
return null;
}
+
+ // 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.
+
+ if (Type == TypeManager.guid_attr_type) {
+ try {
+ new Guid ((string)pos_values [0]);
+ }
+ catch (Exception e) {
+ Error_AttributeEmitError (e.Message);
+ }
+ }
+// TODO: reenable
+// if (Type == TypeManager.methodimpl_attr_type &&
+// pos_values.Length == 1 && ((Argument)pos_args [0]).Type == TypeManager.short_type &&
+// !System.Enum.IsDefined (TypeManager.method_impl_options, pos_values [0])) {
+// Error_AttributeEmitError ("Incorrect argument value.");
+// }
+
//
// Now we perform some checks on the positional args as they
// cannot be null for a constructor which expects a parameter
}
object value = pos_values [j];
- if (value != null && a.Type != value.GetType () && a.Type.IsPrimitive) {
+ if (value != null && a.Type != value.GetType () && TypeManager.IsPrimitiveType (a.Type)) {
bool fail;
pos_values [j] = TypeManager.ChangeType (value, a.Type, out fail);
if (fail) {
pos_values = new_pos_values;
}
- try {
- if (named_args.Count > 0) {
- 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 (named_arg_count > 0) {
+ 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];
- prop_values.CopyTo (prop_values_arr, 0);
- prop_infos.CopyTo (prop_info_arr, 0);
+ field_infos.CopyTo (field_info_arr, 0);
+ field_values.CopyTo (field_values_arr, 0);
- cb = new CustomAttributeBuilder (
- (ConstructorInfo) constructor, pos_values,
- prop_info_arr, prop_values_arr,
- field_info_arr, field_values_arr);
- }
- else
- cb = new CustomAttributeBuilder (
- (ConstructorInfo) constructor, pos_values);
- } catch (Exception e) {
- //
- // Sample:
- // using System.ComponentModel;
- // [DefaultValue (CollectionChangeAction.Add)]
- // class X { static void Main () {} }
- //
- Error_AttributeArgumentNotValid (Location);
- return null;
- }
-
- if (!usage_attr) {
- UsageAttribute = DefaultUsageAttribute;
+ prop_values.CopyTo (prop_values_arr, 0);
+ prop_infos.CopyTo (prop_info_arr, 0);
}
- resolve_error = false;
- return cb;
+ return (ConstructorInfo) constructor;
}
/// <summary>
public string GetValidTargets ()
{
StringBuilder sb = new StringBuilder ();
- AttributeTargets targets = UsageAttribute.ValidOn;
+ AttributeTargets targets = GetAttributeUsage (null).ValidOn;
if ((targets & AttributeTargets.Assembly) != 0)
- sb.Append ("'assembly' ");
+ sb.Append ("assembly, ");
- if ((targets & AttributeTargets.Class) != 0)
- sb.Append ("'class' ");
+ if ((targets & AttributeTargets.Module) != 0)
+ sb.Append ("module, ");
- if ((targets & AttributeTargets.Constructor) != 0)
- sb.Append ("'constructor' ");
+ if ((targets & AttributeTargets.Class) != 0)
+ sb.Append ("class, ");
- if ((targets & AttributeTargets.Delegate) != 0)
- sb.Append ("'delegate' ");
+ if ((targets & AttributeTargets.Struct) != 0)
+ sb.Append ("struct, ");
if ((targets & AttributeTargets.Enum) != 0)
- sb.Append ("'enum' ");
+ sb.Append ("enum, ");
- if ((targets & AttributeTargets.Event) != 0)
- sb.Append ("'event' ");
+ if ((targets & AttributeTargets.Constructor) != 0)
+ sb.Append ("constructor, ");
- if ((targets & AttributeTargets.Field) != 0)
- sb.Append ("'field' ");
+ if ((targets & AttributeTargets.Method) != 0)
+ sb.Append ("method, ");
- if ((targets & AttributeTargets.Interface) != 0)
- sb.Append ("'interface' ");
+ if ((targets & AttributeTargets.Property) != 0)
+ sb.Append ("property, indexer, ");
- if ((targets & AttributeTargets.Method) != 0)
- sb.Append ("'method' ");
+ if ((targets & AttributeTargets.Field) != 0)
+ sb.Append ("field, ");
- if ((targets & AttributeTargets.Module) != 0)
- sb.Append ("'module' ");
+ if ((targets & AttributeTargets.Event) != 0)
+ sb.Append ("event, ");
+
+ if ((targets & AttributeTargets.Interface) != 0)
+ sb.Append ("interface, ");
if ((targets & AttributeTargets.Parameter) != 0)
- sb.Append ("'parameter' ");
+ sb.Append ("parameter, ");
- if ((targets & AttributeTargets.Property) != 0)
- sb.Append ("'property' ");
+ if ((targets & AttributeTargets.Delegate) != 0)
+ sb.Append ("delegate, ");
if ((targets & AttributeTargets.ReturnValue) != 0)
- sb.Append ("'return' ");
-
- if ((targets & AttributeTargets.Struct) != 0)
- sb.Append ("'struct' ");
-
- return sb.ToString ();
+ sb.Append ("return, ");
+#if NET_2_0
+ if ((targets & AttributeTargets.GenericParameter) != 0)
+ sb.Append ("type parameter, ");
+#endif
+ return sb.Remove (sb.Length - 2, 2).ToString ();
}
/// <summary>
/// Returns AttributeUsage attribute for this type
/// </summary>
- public AttributeUsageAttribute GetAttributeUsage (EmitContext ec)
+ AttributeUsageAttribute GetAttributeUsage (EmitContext ec)
{
AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute;
if (ua != null)
return ua;
}
- ua = attr_class.ResolveAttributeUsage (ec);
+ Attribute a = attr_class.OptAttributes == null
+ ? null
+ : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type, attr_class.EmitContext);
+
+ ua = a == null
+ ? DefaultUsageAttribute
+ : a.GetAttributeUsageAttribute (attr_class.EmitContext);
+
usage_attr_cache.Add (Type, ua);
return ua;
}
+ AttributeUsageAttribute GetAttributeUsageAttribute (EmitContext ec)
+ {
+ 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);
+
+ if (resolve_error)
+ return DefaultUsageAttribute;
+
+ AttributeUsageAttribute usage_attribute = new AttributeUsageAttribute ((AttributeTargets)pos_values [0]);
+
+ object field = GetPropertyValue ("AllowMultiple");
+ if (field != null)
+ usage_attribute.AllowMultiple = (bool)field;
+
+ field = GetPropertyValue ("Inherited");
+ if (field != null)
+ usage_attribute.Inherited = (bool)field;
+
+ return usage_attribute;
+ }
+
/// <summary>
/// Returns custom name of indexer
/// </summary>
// But because a lot of attribute class code must be rewritten will be better to wait...
Resolve (ec);
+ if (resolve_error)
+ return null;
+
return pos_values [0] as string;
}
// 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)
+ if (resolve_error)
return null;
return (string)pos_values [0];
// 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)
+ if (resolve_error)
return null;
- if (pos_values.Length == 0)
+ if (pos_values == null || pos_values.Length == 0)
return new ObsoleteAttribute ();
if (pos_values.Length == 1)
// 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)
+ if (resolve_error)
return false;
return (bool)pos_values [0];
/// <returns></returns>
public void ExtractSecurityPermissionSet (ListDictionary permissions)
{
- if (TypeManager.LookupDeclSpace (Type) != null && RootContext.StdLib) {
- Error_AttributeEmitError ("security custom attributes can not be referenced from defining assembly");
- return;
+ 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 assemblies except corlib we can avoid all hacks
- if (RootContext.StdLib) {
+ // 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) {
}
}
} else {
- Type temp_type = Type.GetType (Type.FullName);
- // HACK: All mscorlib attributes have same ctor syntax
- sa = (SecurityAttribute) Activator.CreateInstance (temp_type, new object[] { GetSecurityActionValue () } );
+ // HACK: All security attributes have same ctor syntax
+ sa = (SecurityAttribute) Activator.CreateInstance (orig_assembly_type, new object[] { GetSecurityActionValue () } );
- // All types are from newly created corlib but for invocation with old we need to convert them
+ // 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];
- PropertyInfo pi = temp_type.GetProperty (emited_pi.Name, emited_pi.PropertyType);
+ PropertyInfo pi = orig_assembly_type.GetProperty (emited_pi.Name, emited_pi.PropertyType);
object old_instance = pi.PropertyType.IsEnum ?
System.Enum.ToObject (pi.PropertyType, prop_values_arr [i]) :
}
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;
- }
+ perm = sa.CreatePermission ();
SecurityAction action = GetSecurityActionValue ();
// IS is correct because for corlib we are using an instance from old corlib
ps = new PermissionSet (PermissionState.None);
permissions.Add (action, ps);
- } else if (!ps.IsUnrestricted () && sa.Unrestricted) {
+ } else if (!ps.IsUnrestricted () && (sa is PermissionSetAttribute) && sa.Unrestricted) {
ps = ps.Union (new PermissionSet (PermissionState.Unrestricted));
permissions [action] = ps;
}
return value;
}
- public object GetPositionalValue (int i)
+ object GetPropertyValue (string name)
{
- return (pos_values == null) ? null : pos_values[i];
+ 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];
+ }
+
+ return null;
}
object GetFieldValue (string name)
- {
+ {
int i;
if (field_info_arr == null)
return null;
return null;
}
+ //
+ // 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.
+ //
public UnmanagedMarshal GetMarshal (Attributable attr)
{
+ 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");
}
object o = GetFieldValue ("ArraySubType");
- UnmanagedType array_sub_type = o == null ? UnmanagedType.I4 : (UnmanagedType) o;
-
+ UnmanagedType array_sub_type = o == null ? (UnmanagedType) 0x50 /* NATIVE_MAX */ : (UnmanagedType) o;
+
switch (UnmanagedType) {
- case UnmanagedType.CustomMarshaler:
+ case UnmanagedType.CustomMarshaler: {
MethodInfo define_custom = typeof (UnmanagedMarshal).GetMethod ("DefineCustom",
- BindingFlags.Static | BindingFlags.Public);
+ BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (define_custom == null) {
Report.RuntimeMissingSupport (Location, "set marshal info");
return null;
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;
+ }
- case UnmanagedType.LPArray:
- return UnmanagedMarshal.DefineLPArray (array_sub_type);
-
+ 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:
FieldMember fm = attr as FieldMember;
if (fm == null) {
return null;
}
return UnmanagedMarshal.DefineByValArray ((int) GetFieldValue ("SizeConst"));
-
+
case UnmanagedType.ByValTStr:
return UnmanagedMarshal.DefineByValTStr ((int) GetFieldValue ("SizeConst"));
-
+
default:
return UnmanagedMarshal.DefineUnmanagedMarshal (UnmanagedType);
}
}
- public bool IsInternalCall
+ public CharSet GetCharSetValue ()
+ {
+ return (CharSet)System.Enum.Parse (typeof (CharSet), pos_values [0].ToString ());
+ }
+
+ public MethodImplOptions GetMethodImplOptions ()
+ {
+ if (pos_values [0].GetType () != typeof (MethodImplOptions))
+ return (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values [0]);
+ return (MethodImplOptions)pos_values [0];
+ }
+
+ public LayoutKind GetLayoutKindValue ()
{
- get { return ImplOptions == MethodImplOptions.InternalCall; }
+ if (!RootContext.StdLib || pos_values [0].GetType () != typeof (LayoutKind))
+ return (LayoutKind)System.Enum.ToObject (typeof (LayoutKind), pos_values [0]);
+
+ return (LayoutKind)pos_values [0];
}
/// <summary>
AttributeUsageAttribute usage_attr = GetAttributeUsage (ec);
if ((usage_attr.ValidOn & Target) == 0) {
- Report.Error (592, Location, "Attribute '{0}' is not valid on this declaration type. It is valid on {1} declarations only.", Name, GetValidTargets ());
+ Report.Error (592, Location, "Attribute `{0}' is not valid on this declaration type. It is valid on `{1}' declarations only",
+ GetSignatureForError (), GetValidTargets ());
return;
}
- ias.ApplyAttributeBuilder (this, cb);
+ try {
+ ias.ApplyAttributeBuilder (this, cb);
+ }
+ catch (Exception e) {
+ Error_AttributeEmitError (e.Message);
+ return;
+ }
if (!usage_attr.AllowMultiple) {
ArrayList emitted_targets = (ArrayList)emitted_attr [Type];
emitted_targets = new ArrayList ();
emitted_attr.Add (Type, emitted_targets);
} else if (emitted_targets.Contains (Target)) {
- Report.Error (579, Location, "Duplicate '" + Name + "' attribute");
+ Report.Error (579, Location, "Duplicate `{0}' attribute", GetSignatureForError ());
return;
}
emitted_targets.Add (Target);
}
}
}
-
- public object GetValue (EmitContext ec, Constant c, Type target)
- {
- if (Convert.ImplicitConversionExists (ec, c, target))
- return c.GetValue ();
-
- Convert.Error_CannotImplicitConversion (Location, c.Type, target);
- return null;
- }
public MethodBuilder DefinePInvokeMethod (EmitContext ec, TypeBuilder builder, string name,
MethodAttributes flags, Type ret_type, Type [] param_types)
{
- //
- // We extract from the attribute the information we need
- //
-
- if (Arguments == null) {
- Console.WriteLine ("Internal error : this is not supposed to happen !");
- return 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);
- ResolveType (ec);
- if (Type == null)
+ if (resolve_error)
return null;
- ArrayList named_args = new ArrayList ();
-
- ArrayList pos_args = (ArrayList) Arguments [0];
- if (Arguments.Count > 1)
- named_args = (ArrayList) Arguments [1];
-
+ string dll_name = (string)pos_values [0];
- string dll_name = null;
-
- Argument tmp = (Argument) pos_args [0];
-
- if (!tmp.Resolve (ec, Location))
- return null;
-
- if (tmp.Expr is Constant)
- dll_name = (string) ((Constant) tmp.Expr).GetValue ();
- else {
- 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
+ // Default settings
CallingConvention cc = CallingConvention.Winapi;
- CharSet charset = CharSet.Ansi;
+ CharSet charset = CodeGen.Module.DefaultCharSet;
bool preserve_sig = true;
-#if FIXME
+ string entry_point = name;
+ bool best_fit_mapping = false;
+ bool throw_on_unmappable = false;
bool exact_spelling = false;
-#endif
- bool set_last_err = false;
- string entry_point = null;
-
- for (int i = 0; i < named_args.Count; i++) {
-
- DictionaryEntry de = (DictionaryEntry) named_args [i];
-
- string member_name = (string) de.Key;
- Argument a = (Argument) de.Value;
-
- if (!a.Resolve (ec, Location))
- return null;
-
- Expression member = Expression.MemberLookup (
- ec, Type, member_name,
- MemberTypes.Field | MemberTypes.Property,
- BindingFlags.Public | BindingFlags.Instance,
- Location);
-
- if (member == null || !(member is FieldExpr)) {
- Error_InvalidNamedArgument (member_name);
- return null;
+ bool set_last_error = false;
+
+ bool best_fit_mapping_set = false;
+ bool throw_on_unmappable_set = false;
+ bool exact_spelling_set = false;
+ bool set_last_error_set = false;
+
+ MethodInfo set_best_fit = null;
+ MethodInfo set_throw_on = null;
+ MethodInfo set_exact_spelling = null;
+ MethodInfo set_set_last_error = null;
+
+ if (field_info_arr != null) {
+
+ for (int i = 0; i < field_info_arr.Length; i++) {
+ switch (field_info_arr [i].Name) {
+ case "BestFitMapping":
+ best_fit_mapping = (bool) field_values_arr [i];
+ best_fit_mapping_set = true;
+ break;
+ case "CallingConvention":
+ cc = (CallingConvention) field_values_arr [i];
+ break;
+ case "CharSet":
+ charset = (CharSet) field_values_arr [i];
+ break;
+ case "EntryPoint":
+ entry_point = (string) field_values_arr [i];
+ break;
+ case "ExactSpelling":
+ exact_spelling = (bool) field_values_arr [i];
+ exact_spelling_set = true;
+ break;
+ case "PreserveSig":
+ preserve_sig = (bool) field_values_arr [i];
+ break;
+ case "SetLastError":
+ set_last_error = (bool) field_values_arr [i];
+ set_last_error_set = true;
+ break;
+ case "ThrowOnUnmappableChar":
+ throw_on_unmappable = (bool) field_values_arr [i];
+ throw_on_unmappable_set = true;
+ break;
+ default:
+ throw new InternalErrorException (field_info_arr [i].ToString ());
+ }
}
+ }
- if (member is FieldExpr) {
- FieldExpr fe = (FieldExpr) member;
- FieldInfo fi = fe.FieldInfo;
-
- if (fi.IsInitOnly) {
- Error_InvalidNamedArgument (member_name);
- return null;
- }
+ if (throw_on_unmappable_set || best_fit_mapping_set || exact_spelling_set || set_last_error_set) {
+ set_best_fit = typeof (MethodBuilder).GetMethod ("set_BestFitMapping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ set_throw_on = typeof (MethodBuilder).GetMethod ("set_ThrowOnUnmappableChar", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ set_exact_spelling = typeof (MethodBuilder).GetMethod ("set_ExactSpelling", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
+ set_set_last_error = typeof (MethodBuilder).GetMethod ("set_SetLastError", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
- if (a.Expr is Constant) {
- Constant c = (Constant) a.Expr;
-
- try {
- if (member_name == "CallingConvention"){
- object val = GetValue (ec, c, typeof (CallingConvention));
- if (val == null)
- return null;
- cc = (CallingConvention) val;
- } else if (member_name == "CharSet"){
- charset = (CharSet) c.GetValue ();
- } else if (member_name == "EntryPoint")
- entry_point = (string) c.GetValue ();
- else if (member_name == "SetLastError")
- set_last_err = (bool) c.GetValue ();
-#if FIXME
- else if (member_name == "ExactSpelling")
- exact_spelling = (bool) c.GetValue ();
-#endif
- else if (member_name == "PreserveSig")
- preserve_sig = (bool) c.GetValue ();
- } catch (InvalidCastException){
- Error_InvalidNamedArgument (member_name);
- Error_AttributeArgumentNotValid (Location);
- }
- } else {
- Error_AttributeArgumentNotValid (Location);
- return null;
- }
-
+ if ((set_best_fit == null) || (set_throw_on == null) || (set_exact_spelling == null) || (set_set_last_error == null)) {
+ Report.Error (-1, Location,
+ "The ThrowOnUnmappableChar, BestFitMapping, SetLastError, and ExactSpelling attributes can only be emitted when running on the mono runtime.");
+ return null;
}
}
- if (entry_point == null)
- entry_point = name;
- if (set_last_err)
- charset = (CharSet)((int)charset | 0x40);
-
- MethodBuilder mb = builder.DefinePInvokeMethod (
- name, dll_name, entry_point, flags | MethodAttributes.HideBySig,
- CallingConventions.Standard,
- ret_type,
- param_types,
- cc,
- charset);
-
- if (preserve_sig)
- mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
+ try {
+ MethodBuilder mb = builder.DefinePInvokeMethod (
+ name, dll_name, entry_point, flags | MethodAttributes.HideBySig | MethodAttributes.PinvokeImpl,
+ CallingConventions.Standard, ret_type, param_types, cc, charset);
+
+ if (preserve_sig)
+ mb.SetImplementationFlags (MethodImplAttributes.PreserveSig);
+
+ if (throw_on_unmappable_set)
+ set_throw_on.Invoke (mb, 0, null, new object [] { throw_on_unmappable }, null);
+ if (best_fit_mapping_set)
+ set_best_fit.Invoke (mb, 0, null, new object [] { best_fit_mapping }, null);
+ if (exact_spelling_set)
+ set_exact_spelling.Invoke (mb, 0, null, new object [] { exact_spelling }, null);
+ if (set_last_error_set)
+ set_set_last_error.Invoke (mb, 0, null, new object [] { set_last_error }, null);
- return mb;
+ return mb;
+ }
+ catch (ArgumentException e) {
+ Error_AttributeEmitError (e.Message);
+ return null;
+ }
}
private Expression GetValue ()
public readonly NamespaceEntry ns;
public GlobalAttribute (TypeContainer container, string target,
- Expression left_expr, string identifier, ArrayList args, Location loc):
- base (target, left_expr, identifier, args, loc)
+ Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped):
+ base (target, left_expr, identifier, args, loc, nameEscaped)
{
ns = container.NamespaceEntry;
}
RootContext.Tree.Types.NamespaceEntry = null;
}
- public override Type ResolveType (EmitContext ec)
+ protected override FullNamedExpression ResolveAsTypeStep (Expression expr, EmitContext ec, bool silent)
{
- Enter ();
- Type retval = base.ResolveType (ec);
- Leave ();
- return retval;
+ try {
+ Enter ();
+ return base.ResolveAsTypeStep (expr, ec, silent);
+ }
+ finally {
+ Leave ();
+ }
}
- public override CustomAttributeBuilder Resolve (EmitContext ec)
+
+ protected override FullNamedExpression ResolveAsTypeTerminal (Expression expr, EmitContext ec, bool silent)
{
- Enter ();
- CustomAttributeBuilder retval = base.Resolve (ec);
- Leave ();
- return retval;
+ try {
+ Enter ();
+ return base.ResolveAsTypeTerminal (expr, ec, silent);
+ }
+ finally {
+ Leave ();
+ }
+ }
+
+ protected override ConstructorInfo ResolveArguments (EmitContext ec)
+ {
+ try {
+ Enter ();
+ return base.ResolveArguments (ec);
+ }
+ finally {
+ Leave ();
+ }
}
}
sb.Append (", ");
}
sb.Remove (sb.Length - 2, 2);
- Report.Error (657, a.Location, "'{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are '{1}'", a.ExplicitTarget, sb.ToString ());
+ Report.Error (657, a.Location, "`{0}' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are `{1}'", a.ExplicitTarget, sb.ToString ());
return false;
}
return true;
public void Emit (EmitContext ec, Attributable ias)
{
- if (!CheckTargets (ias))
- return;
+ CheckTargets (ias);
ListDictionary ld = new ListDictionary ();
static PtrHashtable analyzed_types_obsolete = new PtrHashtable ();
static PtrHashtable analyzed_member_obsolete = new PtrHashtable ();
static PtrHashtable analyzed_method_excluded = new PtrHashtable ();
+
+#if NET_2_0
static PtrHashtable fixed_buffer_cache = new PtrHashtable ();
+#endif
static object TRUE = new object ();
static object FALSE = new object ();
{
}
+ 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 bool AreOverloadedMethodParamsClsCompliant (Type[] types_a, Type[] types_b)
+ public static Result AreOverloadedMethodParamsClsCompliant (Type[] types_a, Type[] types_b)
{
if (types_a == null || types_b == null)
- return true;
+ return Result.Ok;
if (types_a.Length != types_b.Length)
- return true;
+ 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 && aType.GetArrayRank () != bType.GetArrayRank () && aType.GetElementType () == bType.GetElementType ()) {
- return false;
+ if (aType.IsArray && bType.IsArray) {
+ Type a_el_type = aType.GetElementType ();
+ Type b_el_type = bType.GetElementType ();
+ 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;
+ }
}
Type aBaseType = aType;
}
if (aBaseType != bBaseType)
- continue;
+ return Result.Ok;
if (is_either_ref_or_out)
- return false;
+ result = Result.RefOutArrayError;
}
- return true;
+ return result;
}
/// <summary>
foreach (Parameter arg in fixedParameters) {
if (!AttributeTester.IsClsCompliant (arg.ParameterType)) {
- Report.Error (3001, loc, "Argument type '{0}' is not CLS-compliant", arg.GetSignatureForError ());
+ Report.Error (3001, loc, "Argument type `{0}' is not CLS-compliant", arg.GetSignatureForError ());
return false;
}
}
}
}
- /// <summary>
- /// Tests container name for CLS-Compliant name (differing only in case)
- /// </summary>
- public static void VerifyTopLevelNameClsCompliance ()
+ public static Type GetImportedIgnoreCaseClsType (string name)
{
- Hashtable locase_table = new Hashtable ();
-
- // Convert imported type names to lower case and ignore not cls compliant
- foreach (DictionaryEntry de in TypeManager.all_imported_types) {
- Type t = (Type)de.Value;
- if (!AttributeTester.IsClsCompliant (t))
- continue;
-
- locase_table.Add (((string)de.Key).ToLower (System.Globalization.CultureInfo.InvariantCulture), t);
- }
-
- foreach (DictionaryEntry de in RootContext.Tree.Decls) {
- DeclSpace decl = (DeclSpace)de.Value;
- if (!decl.IsClsCompliaceRequired (decl))
+ foreach (Assembly a in TypeManager.GetAssemblies ()) {
+ Type t = a.GetType (name, false, true);
+ if (t == null)
continue;
- string lcase = decl.Name.ToLower (System.Globalization.CultureInfo.InvariantCulture);
- if (!locase_table.Contains (lcase)) {
- locase_table.Add (lcase, decl);
- continue;
- }
-
- object conflict = locase_table [lcase];
- if (conflict is Type)
- Report.SymbolRelatedToPreviousError ((Type)conflict);
- else
- Report.SymbolRelatedToPreviousError ((MemberCore)conflict);
-
- Report.Error (3005, decl.Location, "Identifier '{0}' differing only in case is not CLS-compliant", decl.GetSignatureForError ());
+ if (IsClsCompliant (t))
+ return t;
}
+ return null;
}
static bool IsClsCompliant (ICustomAttributeProvider attribute_provider)
if (mb.DeclaringType is TypeBuilder)
return null;
- PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo;
- if (pi != null)
- return GetMemberObsoleteAttribute (pi);
+ if (mb.IsSpecialName) {
+ PropertyInfo pi = PropertyExpr.AccessorTable [mb] as PropertyInfo;
+ if (pi != null) {
+ // FIXME: This is buggy as properties from this assembly are included as well
+ return null;
+ //return GetMemberObsoleteAttribute (pi);
+ }
+ }
return GetMemberObsoleteAttribute (mb);
}
public static void Report_ObsoleteMessage (ObsoleteAttribute oa, string member, Location loc)
{
if (oa.IsError) {
- Report.Error (619, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
+ Report.Error (619, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
return;
}
if (oa.Message == null) {
- Report.Warning (612, loc, "'{0}' is obsolete", member);
+ Report.Warning (612, loc, "`{0}' is obsolete", member);
return;
}
if (RootContext.WarningLevel >= 2)
- Report.Warning (618, loc, "'{0}' is obsolete: '{1}'", member, oa.Message);
+ Report.Warning (618, loc, "`{0}' is obsolete: `{1}'", member, oa.Message);
}
public static bool IsConditionalMethodExcluded (MethodBase mb)
analyzed_method_excluded.Add (mb, TRUE);
return true;
}
+
+ /// <summary>
+ /// Analyzes class whether it has attribute which has ConditionalAttribute
+ /// and its condition is not defined.
+ /// </summary>
+ public static bool IsAttributeExcluded (Type type)
+ {
+ if (!type.IsClass)
+ return false;
+
+ Class class_decl = TypeManager.LookupDeclSpace (type) as Class;
+
+ // TODO: add caching
+ // TODO: merge all Type bases attribute caching to one cache to save memory
+ if (class_decl == null) {
+ object[] attributes = type.GetCustomAttributes (TypeManager.conditional_attribute_type, false);
+ foreach (ConditionalAttribute ca in attributes) {
+ if (RootContext.AllDefines.Contains (ca.ConditionString))
+ return false;
+ }
+ return attributes.Length > 0;
+ }
+
+ return class_decl.IsExcluded ();
+ }
}
}