diff options
author | Marek Safar <marek.safar@gmail.com> | 2006-02-28 01:44:20 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2006-02-28 01:44:20 +0300 |
commit | ce9291281593887d381a429ab947004424c376d2 (patch) | |
tree | cf2f86f36cdd3343d7053e87679ae8505039f93f /mcs | |
parent | 385e817034a3625fbbe1f65bafe7d94359840269 (diff) |
2006-02-27 Marek Safar <marek.safar@seznam.cz>
* attribute.cs (Attribute.PosArguments, Attribute.NamedArguments): Use
these two separated members to simplify the code.
(Attribute.Resolve): Refactored to use new fields and methods.
(Attribute.ResolveConstructor): Extracted from ResolveArguments and
implemented obsolete attribute checking.
(Attribute.ResolveNamedArguments): Extracted from ResolveArguments and
implemented obsolete checking again. It look line never ending quest ;-)
(GlobalAttribute.ResolveConstructor): Need to override as the rest.
* cfold.cs (BinaryFold): TryReduce throws an exception to indicate error.
* constanct.cs (TryReduce): Throws OverflowException to indicate error.
*class.cs (Property.Define): Add RegisterProperty call.
* cs-parser.jay: Replaced ArrayList with fixed array for attribute
argument groups (only 2).
* ecore.cs (Expression.GetAttributableValue): New virtual method used for
encoding expression to arguments.
(Expression.ExprClassToResolveFlags): Just turned to property.
* expression.cs (ArrayCreation.ValidateInitializers): Slightly optimized.
(ArrayCreation.GetAttributableValue): Renamed from EncodeAsAttribute and
optimized as well as implemented support for zero-length attributes.
* typemanager.cs (TypeManager.RegisterProperty, TypeManager.GetProperty):
Add caching of PropertyInfo's.
svn path=/trunk/mcs/; revision=57358
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/mcs/ChangeLog | 31 | ||||
-rw-r--r-- | mcs/mcs/attribute.cs | 470 | ||||
-rw-r--r-- | mcs/mcs/cfold.cs | 20 | ||||
-rw-r--r-- | mcs/mcs/class.cs | 1 | ||||
-rw-r--r-- | mcs/mcs/constant.cs | 18 | ||||
-rw-r--r-- | mcs/mcs/cs-parser.jay | 25 | ||||
-rw-r--r-- | mcs/mcs/ecore.cs | 59 | ||||
-rw-r--r-- | mcs/mcs/expression.cs | 77 | ||||
-rw-r--r-- | mcs/mcs/typemanager.cs | 16 |
9 files changed, 371 insertions, 346 deletions
diff --git a/mcs/mcs/ChangeLog b/mcs/mcs/ChangeLog index 8b9423aa8e2..315b25dad1c 100644 --- a/mcs/mcs/ChangeLog +++ b/mcs/mcs/ChangeLog @@ -1,3 +1,34 @@ +2006-02-27 Marek Safar <marek.safar@seznam.cz> + + * attribute.cs (Attribute.PosArguments, Attribute.NamedArguments): Use + these two separated members to simplify the code. + (Attribute.Resolve): Refactored to use new fields and methods. + (Attribute.ResolveConstructor): Extracted from ResolveArguments and + implemented obsolete attribute checking. + (Attribute.ResolveNamedArguments): Extracted from ResolveArguments and + implemented obsolete checking again. It look line never ending quest ;-) + (GlobalAttribute.ResolveConstructor): Need to override as the rest. + + * cfold.cs (BinaryFold): TryReduce throws an exception to indicate error. + + * constanct.cs (TryReduce): Throws OverflowException to indicate error. + + *class.cs (Property.Define): Add RegisterProperty call. + + * cs-parser.jay: Replaced ArrayList with fixed array for attribute + argument groups (only 2). + + * ecore.cs (Expression.GetAttributableValue): New virtual method used for + encoding expression to arguments. + (Expression.ExprClassToResolveFlags): Just turned to property. + + * expression.cs (ArrayCreation.ValidateInitializers): Slightly optimized. + (ArrayCreation.GetAttributableValue): Renamed from EncodeAsAttribute and + optimized as well as implemented support for zero-length attributes. + + * typemanager.cs (TypeManager.RegisterProperty, TypeManager.GetProperty): + Add caching of PropertyInfo's. + 2006-02-25 Marek Safar <marek.safar@seznam.cz> * delegate.cs (DelegateCreation.ResolveMethodGroupExpr): Don't report diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs index c474d0c4d84..2b8c8031ea4 100644 --- a/mcs/mcs/attribute.cs +++ b/mcs/mcs/attribute.cs @@ -83,7 +83,8 @@ namespace Mono.CSharp { public readonly Expression LeftExpr; public readonly string Identifier; - public readonly ArrayList Arguments; + readonly ArrayList PosArguments; + readonly ArrayList NamedArguments; public readonly Location Location; @@ -93,8 +94,9 @@ namespace Mono.CSharp { readonly bool nameEscaped; Attributable owner; - static AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All); + static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All); static Assembly orig_sec_assembly; + public static readonly object[] EmptyObject = new object [0]; // non-null if named args present after Resolve () is called PropertyInfo [] prop_info_arr; @@ -104,13 +106,19 @@ namespace Mono.CSharp { object [] pos_values; static PtrHashtable usage_attr_cache = new PtrHashtable (); + + // Cache for parameter-less attributes + static PtrHashtable att_cache = new PtrHashtable (); - public Attribute (string target, Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped) + public Attribute (string target, Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped) { LeftExpr = left_expr; Identifier = identifier; Name = LeftExpr == null ? identifier : LeftExpr + "." + identifier; - Arguments = args; + if (args != null) { + PosArguments = (ArrayList)args [0]; + NamedArguments = (ArrayList)args [1]; + } Location = loc; ExplicitTarget = target; this.nameEscaped = nameEscaped; @@ -135,18 +143,12 @@ namespace Mono.CSharp { "attribute parameter type", name); } - static void Error_AttributeArgumentNotValid (string extra, Location loc) + public static void Error_AttributeArgumentNotValid (Location loc) { Report.Error (182, loc, "An attribute argument must be a constant expression, typeof " + - "expression or array creation expression" + extra); - } - - static void Error_AttributeArgumentNotValid (Location loc) - { - Error_AttributeArgumentNotValid ("", loc); - } - + "expression or array creation expression"); + } /// <summary> /// This is rather hack. We report many emit attribute error with same error to be compatible with @@ -255,41 +257,6 @@ namespace Mono.CSharp { return LeftExpr == null ? Identifier : LeftExpr.GetSignatureForError () + "." + Identifier; } - // - // Given an expression, if the expression is a valid attribute-argument-expression - // returns an object that can be used to encode it, or null on failure. - // - public static bool GetAttributeArgumentExpression (Expression e, Location loc, Type arg_type, out object result) - { - Constant constant = e as Constant; - if (constant != null) { - constant = constant.ToType (arg_type, loc); - if (constant == null) { - result = null; - return false; - } - result = constant.GetTypedValue (); - return true; - } else if (e is TypeOf) { - result = ((TypeOf) e).TypeArg; - return true; - } else if (e is ArrayCreation){ - result = ((ArrayCreation) e).EncodeAsAttribute (); - if (result != null) - return true; - } 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; - } - bool IsValidArgumentType (Type t) { if (t.IsArray) @@ -302,9 +269,6 @@ namespace Mono.CSharp { t == TypeManager.type_type; } - // Cache for parameter-less attributes - static PtrHashtable att_cache = new PtrHashtable (); - public CustomAttributeBuilder Resolve () { if (resolve_error) @@ -328,7 +292,7 @@ namespace Mono.CSharp { AttributeTester.Report_ObsoleteMessage (obsolete_attr, TypeManager.CSharpName (Type), Location); } - if (Arguments == null) { + if (PosArguments == null && NamedArguments == null) { object o = att_cache [Type]; if (o != null) { resolve_error = false; @@ -336,118 +300,177 @@ namespace Mono.CSharp { } } - ConstructorInfo ctor = ResolveArguments (); + EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer, + Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false); + + ConstructorInfo ctor = ResolveConstructor (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 (NamedArguments == null) { + cb = new CustomAttributeBuilder (ctor, pos_values); if (pos_values.Length == 0) att_cache.Add (Type, cb); + + resolve_error = false; + return cb; + } + + if (!ResolveNamedArguments (ec)) { + return null; } + + cb = new CustomAttributeBuilder (ctor, pos_values, + prop_info_arr, prop_values_arr, + field_info_arr, field_values_arr); + + resolve_error = false; + return cb; } catch (Exception) { Error_AttributeArgumentNotValid (Location); return null; } - - resolve_error = false; - return cb; } - protected virtual ConstructorInfo ResolveArguments () + protected virtual ConstructorInfo ResolveConstructor (EmitContext ec) { - // Now we extract the positional and named arguments - - 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) { - named_args = (ArrayList) Arguments [1]; - named_arg_count = named_args.Count; + if (PosArguments != null) { + for (int i = 0; i < PosArguments.Count; i++) { + Argument a = (Argument) PosArguments [i]; + + if (!a.Resolve (ec, Location)) + return null; } } - pos_values = new object [pos_arg_count]; + Expression mg = Expression.MemberLookup (ec.ContainerType, + Type, ".ctor", MemberTypes.Constructor, + BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, + Location); - // - // First process positional arguments - // + MethodBase constructor = Invocation.OverloadResolve ( + ec, (MethodGroupExpr) mg, PosArguments, false, Location); - EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer, - Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false); + if (constructor == null) + return null; - int i; - for (i = 0; i < pos_arg_count; i++) { - Argument a = (Argument) pos_args [i]; - Expression e; + ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor); + if (oa != null && !owner.ResolveContext.IsInObsoleteScope) { + AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location); + } - if (!a.Resolve (ec, Location)) - return null; + if (PosArguments == null) { + pos_values = EmptyObject; + return (ConstructorInfo)constructor; + } - e = a.Expr; + ParameterData pd = TypeManager.GetParameterData (constructor); - object val; - if (!GetAttributeArgumentExpression (e, Location, a.Type, out val)) - return null; + int pos_arg_count = PosArguments.Count; + int last_real_param = pd.Count; + + pos_values = new object [pos_arg_count]; - pos_values [i] = val; + if (pd.HasParams) { + // When the params is not filled we need to put one + if (last_real_param > pos_arg_count) { + object [] new_pos_values = new object [pos_arg_count + 1]; + pos_values.CopyTo (new_pos_values, 0); + new_pos_values [pos_arg_count] = new object [] {} ; + pos_values = new_pos_values; + } + last_real_param--; + } + + for (int j = 0; j < pos_arg_count; ++j) { + Argument a = (Argument) PosArguments [j]; - if (i == 0 && Type == TypeManager.attribute_usage_type && (int)val == 0) { - Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute"); + if (!a.Expr.GetAttributableValue (out pos_values [j])) return null; + + if (TypeManager.IsPrimitiveType (a.Type) && a.Type != pos_values [j].GetType ()) { + bool fail; + // This can happen only for constants in same range + pos_values [j] = TypeManager.ChangeType (pos_values [j], a.Type, out fail); } + + if (j < last_real_param) + continue; + + if (j == last_real_param) { + object [] array = new object [pos_arg_count - last_real_param]; + array [0] = pos_values [j]; + pos_values [j] = array; + continue; + } + + object [] params_array = (object []) pos_values [last_real_param]; + params_array [j - last_real_param] = pos_values [j]; } - // - // Now process named arguments - // + // Adjust the size of the pos_values if it had params + if (last_real_param != pos_arg_count) { + object [] new_pos_values = new object [last_real_param + 1]; + Array.Copy (pos_values, new_pos_values, last_real_param + 1); + pos_values = new_pos_values; + } - ArrayList field_infos = null; - ArrayList prop_infos = null; - ArrayList field_values = null; - ArrayList prop_values = null; - Hashtable seen_names = 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); + return null; + } + } - if (named_arg_count > 0) { - field_infos = new ArrayList (4); - prop_infos = new ArrayList (4); - field_values = new ArrayList (4); - prop_values = new ArrayList (4); + if (Type == TypeManager.attribute_usage_type && (int)pos_values [0] == 0) { + Report.Error (591, Location, "Invalid value for argument to 'System.AttributeUsage' attribute"); + return null; + } - seen_names = new Hashtable(4); + if (Type == TypeManager.methodimpl_attr_type && pos_values.Length == 1 && + pd.ParameterType (0) == TypeManager.short_type && + !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0].ToString ())) { + Error_AttributeEmitError ("Incorrect argument value."); + return null; } + + return (ConstructorInfo)constructor; + } + + protected virtual bool ResolveNamedArguments (EmitContext ec) + { + int named_arg_count = NamedArguments.Count; + + ArrayList field_infos = new ArrayList (named_arg_count); + ArrayList prop_infos = new ArrayList (named_arg_count); + ArrayList field_values = new ArrayList (named_arg_count); + ArrayList prop_values = new ArrayList (named_arg_count); + + ArrayList seen_names = new ArrayList(named_arg_count); - for (i = 0; i < named_arg_count; i++) { - DictionaryEntry de = (DictionaryEntry) named_args [i]; + foreach (DictionaryEntry de in NamedArguments) { string member_name = (string) de.Key; - Argument a = (Argument) de.Value; - Expression e; if (seen_names.Contains(member_name)) { Report.Error(643, Location, "'" + member_name + "' duplicate named attribute argument"); - return null; + return false; } - seen_names.Add(member_name, 1); - + seen_names.Add(member_name); + + Argument a = (Argument) de.Value; if (!a.Resolve (ec, Location)) - return null; + return false; Expression member = Expression.MemberLookup ( ec.ContainerType, Type, member_name, @@ -462,175 +485,103 @@ namespace Mono.CSharp { if (member != null) { Expression.ErrorIsInaccesible (Location, member.GetSignatureForError ()); - return null; + return false; } } if (member == null){ Report.Error (117, Location, "`{0}' does not contain a definition for `{1}'", TypeManager.CSharpName (Type), member_name); - return null; + return false; } if (!(member is PropertyExpr || member is FieldExpr)) { Error_InvalidNamedArgument (member_name); - return null; + return false; } - e = a.Expr; + ObsoleteAttribute obsolete_attr; + if (member is PropertyExpr) { - PropertyExpr pe = (PropertyExpr) member; - PropertyInfo pi = pe.PropertyInfo; + PropertyInfo pi = ((PropertyExpr) member).PropertyInfo; if (!pi.CanWrite || !pi.CanRead) { Report.SymbolRelatedToPreviousError (pi); Error_InvalidNamedArgument (member_name); - return null; + return false; } if (!IsValidArgumentType (pi.PropertyType)) { Report.SymbolRelatedToPreviousError (pi); Error_InvalidNamedAgrumentType (member_name); - return null; + return false; } + Expression e = Convert.ImplicitConversionRequired (ec, a.Expr, pi.PropertyType, a.Expr.Location); + if (e == null) + return false; + object value; - if (!GetAttributeArgumentExpression (e, Location, pi.PropertyType, out value)) - return null; + if (!e.GetAttributableValue (out value)) + return false; + + PropertyBase pb = TypeManager.GetProperty (pi); + if (pb != null) + obsolete_attr = pb.GetObsoleteAttribute (); + else + obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (pi); prop_values.Add (value); prop_infos.Add (pi); - } else if (member is FieldExpr) { - FieldExpr fe = (FieldExpr) member; - FieldInfo fi = fe.FieldInfo; + } else { + FieldInfo fi = ((FieldExpr) member).FieldInfo; if (fi.IsInitOnly) { Error_InvalidNamedArgument (member_name); - return null; + return false; } if (!IsValidArgumentType (fi.FieldType)) { Report.SymbolRelatedToPreviousError (fi); Error_InvalidNamedAgrumentType (member_name); - return null; + return false; } + Expression e = Convert.ImplicitConversionRequired (ec, a.Expr, fi.FieldType, a.Expr.Location); + if (e == null) + return false; + object value; - if (!GetAttributeArgumentExpression (e, Location, fi.FieldType, out value)) - return null; + if (!e.GetAttributableValue (out value)) + return false; + + FieldBase fb = TypeManager.GetField (fi); + if (fb != null) + obsolete_attr = fb.GetObsoleteAttribute (); + else + obsolete_attr = AttributeTester.GetMemberObsoleteAttribute (fi); field_values.Add (value); field_infos.Add (fi); } - } - - Expression mg = Expression.MemberLookup (ec.ContainerType, - Type, ".ctor", MemberTypes.Constructor, - BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, - Location); - - MethodBase constructor = Invocation.OverloadResolve ( - ec, (MethodGroupExpr) mg, pos_args, false, Location); - if (constructor == null) { - 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); - return null; - } + if (obsolete_attr != null && !owner.ResolveContext.IsInObsoleteScope) + AttributeTester.Report_ObsoleteMessage (obsolete_attr, member.GetSignatureForError (), member.Location); } - if (Type == TypeManager.methodimpl_attr_type && - pos_values.Length == 1 && ((Argument)pos_args [0]).Type == TypeManager.short_type && - !System.Enum.IsDefined (typeof (MethodImplOptions), pos_values [0])) { - Error_AttributeEmitError ("Incorrect argument value."); - return null; - } + 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]; - // - // Now we perform some checks on the positional args as they - // cannot be null for a constructor which expects a parameter - // of type object - // + field_infos.CopyTo (field_info_arr, 0); + field_values.CopyTo (field_values_arr, 0); - ParameterData pd = TypeManager.GetParameterData (constructor); + prop_values.CopyTo (prop_values_arr, 0); + prop_infos.CopyTo (prop_info_arr, 0); - int last_real_param = pd.Count; - if (pd.HasParams) { - // When the params is not filled we need to put one - if (last_real_param > pos_arg_count) { - object [] new_pos_values = new object [pos_arg_count + 1]; - pos_values.CopyTo (new_pos_values, 0); - new_pos_values [pos_arg_count] = new object [] {} ; - pos_values = new_pos_values; - } - last_real_param--; - } - - for (int j = 0; j < pos_arg_count; ++j) { - Argument a = (Argument) pos_args [j]; - - if (a.Expr is NullLiteral && pd.ParameterType (j) == TypeManager.object_type) { - Error_AttributeArgumentNotValid (Location); - return null; - } - - object value = pos_values [j]; - 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) { - // TODO: Can failed ? - throw new NotImplementedException (); - } - } - - if (j < last_real_param) - continue; - - if (j == last_real_param) { - object [] array = new object [pos_arg_count - last_real_param]; - array [0] = pos_values [j]; - pos_values [j] = array; - continue; - } - - object [] params_array = (object []) pos_values [last_real_param]; - params_array [j - last_real_param] = pos_values [j]; - } - - // Adjust the size of the pos_values if it had params - if (last_real_param != pos_arg_count) { - object [] new_pos_values = new object [last_real_param + 1]; - Array.Copy (pos_values, new_pos_values, last_real_param + 1); - pos_values = new_pos_values; - } - - 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]; - - field_infos.CopyTo (field_info_arr, 0); - field_values.CopyTo (field_values_arr, 0); - - prop_values.CopyTo (prop_values_arr, 0); - prop_infos.CopyTo (prop_info_arr, 0); - } - - return (ConstructorInfo) constructor; + return true; } /// <summary> @@ -1174,12 +1125,8 @@ namespace Mono.CSharp { // Here we are testing attribute arguments for array usage (error 3016) if (owner.IsClsComplianceRequired ()) { - if (Arguments == null) - return; - - ArrayList pos_args = (ArrayList) Arguments [0]; - if (pos_args != null) { - foreach (Argument arg in pos_args) { + if (PosArguments != null) { + foreach (Argument arg in PosArguments) { // Type is undefined (was error 246) if (arg.Type == null) return; @@ -1191,11 +1138,10 @@ namespace Mono.CSharp { } } - if (Arguments.Count < 2) + if (NamedArguments == null) return; - ArrayList named_args = (ArrayList) Arguments [1]; - foreach (DictionaryEntry de in named_args) { + foreach (DictionaryEntry de in NamedArguments) { Argument arg = (Argument) de.Value; // Type is undefined (was error 246) @@ -1327,15 +1273,10 @@ namespace Mono.CSharp { private Expression GetValue () { - if ((Arguments == null) || (Arguments.Count < 1)) - return null; - ArrayList al = (ArrayList) Arguments [0]; - if ((al == null) || (al.Count < 1)) - return null; - Argument arg = (Argument) al [0]; - if ((arg == null) || (arg.Expr == null)) + if (PosArguments == null || PosArguments.Count < 1) return null; - return arg.Expr; + + return ((Argument) PosArguments [0]).Expr; } public string GetString () @@ -1365,7 +1306,7 @@ namespace Mono.CSharp { public readonly NamespaceEntry ns; public GlobalAttribute (NamespaceEntry ns, string target, - Expression left_expr, string identifier, ArrayList args, Location loc, bool nameEscaped): + Expression left_expr, string identifier, object[] args, Location loc, bool nameEscaped): base (target, left_expr, identifier, args, loc, nameEscaped) { this.ns = ns; @@ -1414,11 +1355,22 @@ namespace Mono.CSharp { } } - protected override ConstructorInfo ResolveArguments () + protected override ConstructorInfo ResolveConstructor (EmitContext ec) + { + try { + Enter (); + return base.ResolveConstructor (ec); + } + finally { + Leave (); + } + } + + protected override bool ResolveNamedArguments (EmitContext ec) { try { Enter (); - return base.ResolveArguments (); + return base.ResolveNamedArguments (ec); } finally { Leave (); diff --git a/mcs/mcs/cfold.cs b/mcs/mcs/cfold.cs index 303002901a6..aba3ad37c48 100644 --- a/mcs/mcs/cfold.cs +++ b/mcs/mcs/cfold.cs @@ -550,8 +550,14 @@ namespace Mono.CSharp { Error_CompileTimeOverflow (loc); } - if (wrap_as != null) - return result.TryReduce (ec, wrap_as, loc); + if (wrap_as != null) { + try { + return result.TryReduce (ec, wrap_as, loc); + } + catch (OverflowException) { + return null; + } + } else return result; @@ -682,8 +688,14 @@ namespace Mono.CSharp { Error_CompileTimeOverflow (loc); } - if (wrap_as != null) - return result.TryReduce (ec, wrap_as, loc); + if (wrap_as != null) { + try { + return result.TryReduce (ec, wrap_as, loc); + } + catch (OverflowException) { + return null; + } + } return result; diff --git a/mcs/mcs/class.cs b/mcs/mcs/class.cs index 514388e8a2f..d98381da6c6 100644 --- a/mcs/mcs/class.cs +++ b/mcs/mcs/class.cs @@ -6194,6 +6194,7 @@ namespace Mono.CSharp { if (!Set.IsDummy) PropertyBuilder.SetSetMethod (SetBuilder); + TypeManager.RegisterProperty (PropertyBuilder, this); return true; } } diff --git a/mcs/mcs/constant.cs b/mcs/mcs/constant.cs index 76c2c5667a8..0ccf630311d 100644 --- a/mcs/mcs/constant.cs +++ b/mcs/mcs/constant.cs @@ -39,6 +39,12 @@ namespace Mono.CSharp { return this.GetType ().Name + " (" + AsString () + ")"; } + public override bool GetAttributableValue (out object value) + { + value = GetTypedValue (); + return true; + } + /// <summary> /// This is used to obtain the actual value of the literal /// cast into an object. @@ -233,6 +239,10 @@ namespace Mono.CSharp { throw new OverflowException (); } + /// <summary> + /// Maybe ConvertTo name is better. It tries to convert `this' constant to target_type. + /// It throws OverflowException + /// </summary> public abstract Constant Reduce (EmitContext ec, Type target_type); /// <summary> @@ -244,11 +254,9 @@ namespace Mono.CSharp { return TryReduce (ec, target_type); } catch (OverflowException) { - if (ec.ConstantCheckState) { - Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", - GetValue ().ToString (), TypeManager.CSharpName (target_type)); - } - return null; + Report.Error (221, loc, "Constant value `{0}' cannot be converted to a `{1}' (use `unchecked' syntax to override)", + GetValue ().ToString (), TypeManager.CSharpName (target_type)); + throw; } } diff --git a/mcs/mcs/cs-parser.jay b/mcs/mcs/cs-parser.jay index 2b709ec23bb..3b1c82ec761 100644 --- a/mcs/mcs/cs-parser.jay +++ b/mcs/mcs/cs-parser.jay @@ -620,7 +620,7 @@ attribute : attribute_name opt_attribute_arguments { MemberName mname = (MemberName) $1; - ArrayList arguments = (ArrayList) $2; + object[] arguments = (object[]) $2; MemberName left = mname.Left; string identifier = mname.Name; @@ -654,29 +654,18 @@ attribute_arguments if ($1 == null) $$ = null; else { - ArrayList args = new ArrayList (4); - args.Add ($1); - - $$ = args; + $$ = new object [] { $1, null }; } } - | positional_argument_list COMMA named_argument_list + | positional_argument_list COMMA named_argument_list { - ArrayList args = new ArrayList (4); - args.Add ($1); - args.Add ($3); - - $$ = args; + $$ = new object[] { $1, $3 }; } - | named_argument_list + | named_argument_list { - ArrayList args = new ArrayList (4); - args.Add (null); - args.Add ($1); - - $$ = args; + $$ = new object [] { null, $1 }; } - ; + ; opt_positional_argument_list diff --git a/mcs/mcs/ecore.cs b/mcs/mcs/ecore.cs index dc2324a363b..8b3e61aa012 100644 --- a/mcs/mcs/ecore.cs +++ b/mcs/mcs/ecore.cs @@ -137,6 +137,13 @@ namespace Mono.CSharp { // Not nice but we have broken hierarchy public virtual void CheckMarshallByRefAccess (Type container) {} + public virtual bool GetAttributableValue (out object value) + { + Attribute.Error_AttributeArgumentNotValid (loc); + value = null; + return false; + } + public virtual string GetSignatureForError () { return TypeManager.CSharpName (type); @@ -315,28 +322,29 @@ namespace Mono.CSharp { TypeManager.CSharpName (type), name); } - ResolveFlags ExprClassToResolveFlags () + ResolveFlags ExprClassToResolveFlags { - switch (eclass) { - case ExprClass.Type: - case ExprClass.Namespace: - return ResolveFlags.Type; + get { + switch (eclass) { + case ExprClass.Type: + case ExprClass.Namespace: + return ResolveFlags.Type; - case ExprClass.MethodGroup: - return ResolveFlags.MethodGroup; + case ExprClass.MethodGroup: + return ResolveFlags.MethodGroup; - case ExprClass.Value: - case ExprClass.Variable: - case ExprClass.PropertyAccess: - case ExprClass.EventAccess: - case ExprClass.IndexerAccess: - return ResolveFlags.VariableOrValue; + case ExprClass.Value: + case ExprClass.Variable: + case ExprClass.PropertyAccess: + case ExprClass.EventAccess: + case ExprClass.IndexerAccess: + return ResolveFlags.VariableOrValue; - default: - throw new Exception ("Expression " + GetType () + - " ExprClass is Invalid after resolve"); + default: + throw new Exception ("Expression " + GetType () + + " ExprClass is Invalid after resolve"); + } } - } /// <summary> @@ -360,10 +368,10 @@ namespace Mono.CSharp { ec.OmitStructFlowAnalysis = true; Expression e; - bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; - if (this is SimpleName) + if (this is SimpleName) { + bool intermediate = (flags & ResolveFlags.Intermediate) == ResolveFlags.Intermediate; e = ((SimpleName) this).DoResolve (ec, intermediate); - + } else e = DoResolve (ec); @@ -373,7 +381,7 @@ namespace Mono.CSharp { if (e == null) return null; - if ((flags & e.ExprClassToResolveFlags ()) == 0) { + if ((flags & e.ExprClassToResolveFlags) == 0) { e.Error_UnexpectedKind (flags, loc); return null; } @@ -1123,7 +1131,7 @@ namespace Mono.CSharp { /// /// </summary> public class EmptyCast : Expression { - protected Expression child; + protected readonly Expression child; public Expression Child { get { @@ -1151,6 +1159,12 @@ namespace Mono.CSharp { { child.Emit (ec); } + + public override bool GetAttributableValue (out object value) + { + return child.GetAttributableValue (out value); + } + } /// <summary> /// This is a numeric cast to a Decimal @@ -3194,6 +3208,7 @@ namespace Mono.CSharp { // We also perform the permission checking here, as the PropertyInfo does not // hold the information for the accessibility of its setter/getter // + // TODO: can use TypeManager.GetProperty to boost performance void ResolveAccessors (Type containerType) { FindAccessors (containerType); diff --git a/mcs/mcs/expression.cs b/mcs/mcs/expression.cs index 432c83d840c..9005f6641e6 100644 --- a/mcs/mcs/expression.cs +++ b/mcs/mcs/expression.cs @@ -1252,7 +1252,12 @@ namespace Mono.CSharp { Error_CannotConvertType (etype, probe_type, loc); return null; - } + } + + public override bool GetAttributableValue (out object value) + { + return expr.GetAttributableValue (out value); + } } /// <summary> @@ -1327,9 +1332,14 @@ namespace Mono.CSharp { Constant c = expr as Constant; if (c != null) { - c = c.TryReduce (ec, type, loc); - if (c != null) - return c; + try { + c = c.TryReduce (ec, type, loc); + if (c != null) + return c; + } + catch (OverflowException) { + return null; + } } if (type.IsPointer && !ec.InUnsafe) { @@ -6014,10 +6024,7 @@ namespace Mono.CSharp { public bool ValidateInitializers (EmitContext ec, Type array_type) { if (initializers == null) { - if (expect_initializers) - return false; - else - return true; + return !expect_initializers; } if (underlying_type == null) @@ -6030,17 +6037,12 @@ namespace Mono.CSharp { array_data = new ArrayList (); bounds = new Hashtable (); - bool ret; - if (arguments != null) { - ret = CheckIndices (ec, initializers, 0, true); - return ret; + return CheckIndices (ec, initializers, 0, true); } else { arguments = new ArrayList (); - ret = CheckIndices (ec, initializers, 0, false); - - if (!ret) + if (!CheckIndices (ec, initializers, 0, false)) return false; UpdateIndices (ec); @@ -6050,7 +6052,7 @@ namespace Mono.CSharp { return false; } - return ret; + return true; } } @@ -6508,32 +6510,33 @@ namespace Mono.CSharp { } } - public object EncodeAsAttribute () + public override bool GetAttributableValue (out object value) { if (!is_one_dimensional){ - Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); - return null; +// Report.Error (-211, Location, "attribute can not encode multi-dimensional arrays"); + return base.GetAttributableValue (out value); } - if (array_data == null){ - Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); - return null; + if (array_data == null) { + Constant c = (Constant)((Argument)arguments [0]).Expr; + if (c.IsDefaultValue) { + value = new object [0]; + return true; + } +// Report.Error (-212, Location, "array should be initialized when passing it to an attribute"); + return base.GetAttributableValue (out value); } object [] ret = new object [array_data.Count]; - int i = 0; - foreach (Expression e in array_data){ - object v; - - if (e is NullLiteral) - v = null; - else { - if (!Attribute.GetAttributeArgumentExpression (e, Location, array_element_type, out v)) - return null; + for (int i = 0; i < ret.Length; ++i) + { + if (!((Expression)array_data [i]).GetAttributableValue (out ret [i])) { + value = null; + return false; } - ret [i++] = v; } - return ret; + value = ret; + return true; } } @@ -6794,7 +6797,7 @@ namespace Mono.CSharp { /// Implements the typeof operator /// </summary> public class TypeOf : Expression { - public Expression QueriedType; + readonly Expression QueriedType; protected Type typearg; public TypeOf (Expression queried_type, Location l) @@ -6834,8 +6837,10 @@ namespace Mono.CSharp { ec.ig.Emit (OpCodes.Call, TypeManager.system_type_get_type_from_handle); } - public Type TypeArg { - get { return typearg; } + public override bool GetAttributableValue (out object value) + { + value = typearg; + return true; } } diff --git a/mcs/mcs/typemanager.cs b/mcs/mcs/typemanager.cs index f132af41948..e797fd0c0e2 100644 --- a/mcs/mcs/typemanager.cs +++ b/mcs/mcs/typemanager.cs @@ -244,7 +244,9 @@ public class TypeManager { public static Hashtable AllClsTopLevelTypes; static Hashtable fieldbuilders_to_fields; + static Hashtable propertybuilder_to_property; static Hashtable fields; + static Hashtable events; struct Signature { public string name; @@ -266,6 +268,7 @@ public class TypeManager { events = null; priv_fields_events = null; type_hash = null; + propertybuilder_to_property = null; TypeHandle.CleanUp (); } @@ -360,6 +363,7 @@ public class TypeManager { builder_to_ifaces = new PtrHashtable (); fieldbuilders_to_fields = new Hashtable (); + propertybuilder_to_property = new Hashtable (); fields = new Hashtable (); type_hash = new DoubleHash (); @@ -1553,6 +1557,16 @@ public class TypeManager { return (IConstant)fields [fb]; } + public static void RegisterProperty (PropertyInfo pi, PropertyBase pb) + { + propertybuilder_to_property.Add (pi, pb); + } + + public static PropertyBase GetProperty (PropertyInfo pi) + { + return (PropertyBase)propertybuilder_to_property [pi]; + } + static public bool RegisterFieldBase (FieldBuilder fb, FieldBase f) { if (fieldbuilders_to_fields.Contains (fb)) @@ -1572,8 +1586,6 @@ public class TypeManager { return (FieldBase) fieldbuilders_to_fields [fb]; } - static Hashtable events; - static public void RegisterEvent (MyEventBuilder eb, MethodBase add, MethodBase remove) { if (events == null) |