X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fattribute.cs;h=b939cf436ba46b09f46ef580e6a2f015cf3f41a5;hb=f282c09a4f474c0994bf739e0b300043fd342b80;hp=5709c7fcaaae683cec1a9e89369fa06533cfc833;hpb=423bf2960e669c0120fd6f628528c2abc82d9c1d;p=mono.git diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs index 5709c7fcaaa..b939cf436ba 100644 --- a/mcs/mcs/attribute.cs +++ b/mcs/mcs/attribute.cs @@ -10,6 +10,7 @@ // using System; +using System.Diagnostics; using System.Collections; using System.Reflection; using System.Reflection.Emit; @@ -36,8 +37,6 @@ namespace Mono.CSharp { bool Inherited; bool UsageAttr = false; - public bool StructLayout = false; - public TypeAttributes StructLayoutAttributes = 0; MethodImplOptions ImplOptions; UnmanagedType UnmanagedType; @@ -50,7 +49,7 @@ namespace Mono.CSharp { Location = loc; } - void error617 (string name) + void Error_InvalidNamedArgument (string name) { Report.Error (617, Location, "'" + name + "' is not a valid named attribute " + "argument. Named attribute arguments must be fields which are not " + @@ -58,13 +57,20 @@ namespace Mono.CSharp { "are not static."); } - void error182 () + void Error_AttributeArgumentNotValid () { Report.Error (182, Location, "An attribute argument must be a constant expression, typeof " + "expression or array creation expression"); } + static void Error_AttributeConstructorMismatch (Location loc) + { + Report.Error ( + -6, loc, + "Could not find a constructor for this argument list."); + } + private Type CheckAttributeType (EmitContext ec) { Type t; bool isattributeclass = true; @@ -94,56 +100,54 @@ namespace Mono.CSharp { return null; } + public Type ResolveType (EmitContext ec) + { + Type = CheckAttributeType (ec); + return Type; + } + + public CustomAttributeBuilder Resolve (EmitContext ec) { - // - // We might call resolve twice, because Structs will call - // things in advance, so they can find out any attribute information - // that needs to be encoded in the TypeAttribute (TypeAttribute.AnsiClass, - // TypeAttribute.UnicodeClass, or TypeAttribute.AutoClass - // - if (cb != null) - return cb; - + if (Type == null) + Type = CheckAttributeType (ec); + if (Type == null) + return null; + bool MethodImplAttr = false; bool MarshalAsAttr = false; UsageAttr = false; - Type = CheckAttributeType (ec); - if (Type == null) - return null; - if (Type == TypeManager.attribute_usage_type) UsageAttr = true; if (Type == TypeManager.methodimpl_attr_type) MethodImplAttr = true; if (Type == TypeManager.marshal_as_attr_type) MarshalAsAttr = true; - if (Type == TypeManager.structlayout_type){ - StructLayout = true; - StructLayoutAttributes = TypeAttributes.AnsiClass; - } - + // Now we extract the positional and named arguments ArrayList pos_args = new ArrayList (); ArrayList named_args = new ArrayList (); + int pos_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]; } - - object [] pos_values = new object [pos_args.Count]; + + object [] pos_values = new object [pos_arg_count]; // // First process positional arguments // - + int i; - for (i = 0; i < pos_args.Count; i++) { + for (i = 0; i < pos_arg_count; i++) { Argument a = (Argument) pos_args [i]; Expression e; @@ -151,12 +155,13 @@ namespace Mono.CSharp { return null; e = a.Expr; + if (e is Constant) { pos_values [i] = ((Constant) e).GetValue (); } else if (e is TypeOf) { pos_values [i] = ((TypeOf) e).TypeArg; } else { - error182 (); + Error_AttributeArgumentNotValid (); return null; } @@ -196,7 +201,7 @@ namespace Mono.CSharp { Location); if (member == null || !(member is PropertyExpr || member is FieldExpr)) { - error617 (member_name); + Error_InvalidNamedArgument (member_name); return null; } @@ -206,7 +211,7 @@ namespace Mono.CSharp { PropertyInfo pi = pe.PropertyInfo; if (!pi.CanWrite) { - error617 (member_name); + Error_InvalidNamedArgument (member_name); return null; } @@ -221,8 +226,10 @@ namespace Mono.CSharp { this.Inherited = (bool) o; } - } else { - error182 (); + } else if (e is TypeOf) { + prop_values.Add (((TypeOf) e).TypeArg); + } else { + Error_AttributeArgumentNotValid (); return null; } @@ -233,7 +240,7 @@ namespace Mono.CSharp { FieldInfo fi = fe.FieldInfo; if (fi.IsInitOnly) { - error617 (member_name); + Error_InvalidNamedArgument (member_name); return null; } @@ -243,44 +250,24 @@ namespace Mono.CSharp { if (e is Constant){ object value = ((Constant) e).GetValue (); - if (StructLayout && fi.Name == "CharSet"){ - CharSet cs = (CharSet) value; - - switch (cs){ - case CharSet.Ansi: - case CharSet.None: - StructLayoutAttributes = - TypeAttributes.AnsiClass; - break; - case CharSet.Auto: - StructLayoutAttributes = - TypeAttributes.AutoClass; - break; - case CharSet.Unicode: - StructLayoutAttributes = - TypeAttributes.UnicodeClass; - break; - } - continue; - } field_values.Add (value); - } else { - error182 (); + } else if (e is TypeOf) { + field_values.Add (((TypeOf) e).TypeArg); + } else { + Error_AttributeArgumentNotValid (); return null; } field_infos.Add (fi); } } - + Expression mg = Expression.MemberLookup ( ec, Type, ".ctor", MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance, Location); if (mg == null) { - Report.Error ( - -6, Location, - "Could not find a constructor for this argument list."); + Error_AttributeConstructorMismatch (Location); return null; } @@ -288,11 +275,26 @@ namespace Mono.CSharp { ec, (MethodGroupExpr) mg, pos_args, Location); if (constructor == null) { - Report.Error ( - -6, Location, - "Could not find a constructor for this argument list."); + Error_AttributeConstructorMismatch (Location); return null; } + + // + // Now we perform some checks on the positional args as they + // cannot be null for a constructor which expects a parameter + // of type object + // + + ParameterData pd = Invocation.GetParameterData (constructor); + + 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 (); + return null; + } + } PropertyInfo [] prop_info_arr = new PropertyInfo [prop_infos.Count]; FieldInfo [] field_info_arr = new FieldInfo [field_infos.Count]; @@ -304,11 +306,31 @@ namespace Mono.CSharp { prop_values.CopyTo (prop_values_arr, 0); prop_infos.CopyTo (prop_info_arr, 0); - - cb = new CustomAttributeBuilder ( - (ConstructorInfo) constructor, pos_values, - prop_info_arr, prop_values_arr, - field_info_arr, field_values_arr); + + try { + cb = new CustomAttributeBuilder ( + (ConstructorInfo) constructor, pos_values, + prop_info_arr, prop_values_arr, + field_info_arr, field_values_arr); + + } catch (NullReferenceException) { + // + // Don't know what to do here + // + Report.Warning ( + -100, Location, "NullReferenceException while trying to create attribute. Something's wrong!"); + } catch { + // + // Sample: + // using System.ComponentModel; + // [DefaultValue (CollectionChangeAction.Add)] + // class X { static void Main () {} } + // + Report.Warning ( + -23, Location, + "The compiler can not encode this attribute in .NET due to\n" + + "\ta bug in the .NET runtime. Try the Mono runtime"); + } return cb; } @@ -335,8 +357,10 @@ namespace Mono.CSharp { } foreach (System.Attribute tmp in attrs) - if (tmp is AttributeUsageAttribute) + if (tmp is AttributeUsageAttribute) { targets = ((AttributeUsageAttribute) tmp).ValidOn; + break; + } } else targets = a.Targets; @@ -447,12 +471,12 @@ namespace Mono.CSharp { return true; else return false; - } else if (element is Event) { + } else if (element is Event || element is InterfaceEvent) { if ((targets & AttributeTargets.Event) != 0) return true; else return false; - } else if (element is Field) { + } else if (element is Field || element is FieldBuilder) { if ((targets & AttributeTargets.Field) != 0) return true; else @@ -462,7 +486,7 @@ namespace Mono.CSharp { return true; else return false; - } else if (element is Method || element is Operator) { + } else if (element is Method || element is Operator || element is InterfaceMethod || element is Accessor) { if ((targets & AttributeTargets.Method) != 0) return true; else @@ -472,7 +496,8 @@ namespace Mono.CSharp { return true; else return false; - } else if (element is Property || element is Indexer) { + } else if (element is Property || element is Indexer || + element is InterfaceProperty || element is InterfaceIndexer) { if ((targets & AttributeTargets.Property) != 0) return true; else @@ -488,46 +513,139 @@ namespace Mono.CSharp { } // - // Returns TypeAttributes that might be encoded on the attributes. Ugly, ugly + // This method should be invoked to pull the IndexerName attribute from an + // Indexer if it exists. // - public static TypeAttributes GetExtraTypeInfo (EmitContext ec, Attributes opt_attrs) + public static string ScanForIndexerName (EmitContext ec, Attributes opt_attrs) { + if (opt_attrs == null) + return null; if (opt_attrs.AttributeSections == null) - return 0; + return null; foreach (AttributeSection asec in opt_attrs.AttributeSections) { - if (asec.Attributes == null) continue; - if (asec.Target == "assembly") - continue; - - foreach (Attribute a in asec.Attributes) { - CustomAttributeBuilder cb = a.Resolve (ec); - - if (cb == null) + foreach (Attribute a in asec.Attributes){ + if (a.ResolveType (ec) == null) + return null; + + if (a.Type != TypeManager.indexer_name_type) continue; - if (a.StructLayout) - return a.StructLayoutAttributes; + // + // So we have found an IndexerName, pull the data out. + // + if (a.Arguments == null || a.Arguments [0] == null){ + Error_AttributeConstructorMismatch (a.Location); + return null; + } + ArrayList pos_args = (ArrayList) a.Arguments [0]; + if (pos_args.Count == 0){ + Error_AttributeConstructorMismatch (a.Location); + return null; + } + + Argument arg = (Argument) pos_args [0]; + if (!arg.Resolve (ec, a.Location)) + return null; + + Expression e = arg.Expr; + if (!(e is StringConstant)){ + Error_AttributeConstructorMismatch (a.Location); + return null; + } + + // + // Remove the attribute from the list + // + asec.Attributes.Remove (a); + + return (((StringConstant) e).Value); } } + return null; + } + + // + // This pulls the condition name out of a Conditional attribute + // + public string Conditional_GetConditionName () + { + // + // So we have a Conditional, pull the data out. + // + if (Arguments == null || Arguments [0] == null){ + Error_AttributeConstructorMismatch (Location); + return null; + } - return 0; + ArrayList pos_args = (ArrayList) Arguments [0]; + if (pos_args.Count != 1){ + Error_AttributeConstructorMismatch (Location); + return null; + } + + Argument arg = (Argument) pos_args [0]; + if (!(arg.Expr is StringConstant)){ + Error_AttributeConstructorMismatch (Location); + return null; + } + + return ((StringConstant) arg.Expr).Value; } - + + // + // This pulls the obsolete message and error flag out of an Obsolete attribute + // + public string Obsolete_GetObsoleteMessage (out bool is_error) + { + is_error = false; + // + // So we have an Obsolete, pull the data out. + // + if (Arguments == null || Arguments [0] == null) + return ""; + + ArrayList pos_args = (ArrayList) Arguments [0]; + if (pos_args.Count == 0) + return ""; + else if (pos_args.Count > 2){ + Error_AttributeConstructorMismatch (Location); + return null; + } + + Argument arg = (Argument) pos_args [0]; + if (!(arg.Expr is StringConstant)){ + Error_AttributeConstructorMismatch (Location); + return null; + } + + if (pos_args.Count == 2){ + Argument arg2 = (Argument) pos_args [1]; + if (!(arg2.Expr is BoolConstant)){ + Error_AttributeConstructorMismatch (Location); + return null; + } + is_error = ((BoolConstant) arg2.Expr).Value; + } + + return ((StringConstant) arg.Expr).Value; + } + + // + // Applies the attributes to the `builder'. + // public static void ApplyAttributes (EmitContext ec, object builder, object kind, Attributes opt_attrs, Location loc) { if (opt_attrs == null) return; - if (opt_attrs.AttributeSections == null) return; foreach (AttributeSection asec in opt_attrs.AttributeSections) { - if (asec.Attributes == null) continue; @@ -542,28 +660,29 @@ namespace Mono.CSharp { if (!(kind is TypeContainer)) if (!CheckAttribute (a, kind)) { - Console.WriteLine ("Kind is: " + kind); Error_AttributeNotValidForElement (a, loc); return; } - if (kind is Method || kind is Operator) { - + if (kind is Method || kind is Operator || kind is InterfaceMethod || + kind is Accessor) { if (a.Type == TypeManager.methodimpl_attr_type) { if (a.ImplOptions == MethodImplOptions.InternalCall) - ((MethodBuilder) builder).SetImplementationFlags ( - MethodImplAttributes.InternalCall | - MethodImplAttributes.Runtime); - } else if (a.Type != TypeManager.dllimport_type) + ((MethodBuilder) builder). + SetImplementationFlags ( + MethodImplAttributes.InternalCall | + MethodImplAttributes.Runtime); + } else if (a.Type != TypeManager.dllimport_type){ ((MethodBuilder) builder).SetCustomAttribute (cb); - + } } else if (kind is Constructor) { ((ConstructorBuilder) builder).SetCustomAttribute (cb); } else if (kind is Field) { ((FieldBuilder) builder).SetCustomAttribute (cb); - } else if (kind is Property || kind is Indexer) { + } else if (kind is Property || kind is Indexer || + kind is InterfaceProperty || kind is InterfaceIndexer) { ((PropertyBuilder) builder).SetCustomAttribute (cb); - } else if (kind is Event) { + } else if (kind is Event || kind is InterfaceEvent) { ((MyEventBuilder) builder).SetCustomAttribute (cb); } else if (kind is ParameterBuilder) { @@ -600,13 +719,43 @@ namespace Mono.CSharp { return; } } + + try { + ((TypeBuilder) builder).SetCustomAttribute (cb); + } catch (System.ArgumentException) { + Report.Warning ( + -21, loc, + "The CharSet named property on StructLayout\n"+ + "\tdoes not work correctly on Microsoft.NET\n"+ + "\tYou might want to remove the CharSet declaration\n"+ + "\tor compile using the Mono runtime instead of the\n"+ + "\tMicrosoft .NET runtime"); + } + } else if (kind is Interface) { + Interface iface = (Interface) kind; + + if ((a.Type == TypeManager.default_member_type) && + (iface.InterfaceIndexers != null)) { + Report.Error ( + 646, loc, + "Cannot specify the DefaultMember attribute on" + + " a type containing an indexer"); + return; + } + + if (!CheckAttribute (a, kind)) { + Error_AttributeNotValidForElement (a, loc); + return; + } + ((TypeBuilder) builder).SetCustomAttribute (cb); - } else if (kind is AssemblyBuilder){ ((AssemblyBuilder) builder).SetCustomAttribute (cb); } else if (kind is ModuleBuilder) { ((ModuleBuilder) builder).SetCustomAttribute (cb); + } else if (kind is FieldBuilder) { + ((FieldBuilder) builder).SetCustomAttribute (cb); } else throw new Exception ("Unknown kind: " + kind); } @@ -646,7 +795,7 @@ namespace Mono.CSharp { if (tmp.Expr is Constant) dll_name = (string) ((Constant) tmp.Expr).GetValue (); else { - error182 (); + Error_AttributeArgumentNotValid (); return null; } @@ -675,7 +824,7 @@ namespace Mono.CSharp { Location); if (member == null || !(member is FieldExpr)) { - error617 (member_name); + Error_InvalidNamedArgument (member_name); return null; } @@ -684,7 +833,7 @@ namespace Mono.CSharp { FieldInfo fi = fe.FieldInfo; if (fi.IsInitOnly) { - error617 (member_name); + Error_InvalidNamedArgument (member_name); return null; } @@ -704,15 +853,18 @@ namespace Mono.CSharp { else if (member_name == "PreserveSig") preserve_sig = (bool) c.GetValue (); } else { - error182 (); + Error_AttributeArgumentNotValid (); return null; } } } + if (entry_point == null) + entry_point = name; + MethodBuilder mb = builder.DefinePInvokeMethod ( - name, dll_name, flags | MethodAttributes.HideBySig, + name, dll_name, entry_point, flags | MethodAttributes.HideBySig, CallingConventions.Standard, ret_type, param_types,