X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fattribute.cs;h=612f299403fd70fa8d4ed4409697e9760ef51b64;hb=b7461c8e10acd19aa25d0ff7946719b19fad0157;hp=2fb61c3c3bc9e6d68ec83a63861903014b1ab16d;hpb=3c36d279678523165a21110195ec91237a391386;p=mono.git diff --git a/mcs/mcs/attribute.cs b/mcs/mcs/attribute.cs index 2fb61c3c3bc..612f299403f 100644 --- a/mcs/mcs/attribute.cs +++ b/mcs/mcs/attribute.cs @@ -85,7 +85,7 @@ namespace Mono.CSharp { public readonly string Identifier; readonly ArrayList PosArguments; - readonly ArrayList NamedArguments; + ArrayList NamedArguments; public readonly Location Location; @@ -95,7 +95,7 @@ namespace Mono.CSharp { readonly bool nameEscaped; // It can contain more onwers when the attribute is applied to multiple fiels. - Attributable[] owners; + protected Attributable[] owners; static readonly AttributeUsageAttribute DefaultUsageAttribute = new AttributeUsageAttribute (AttributeTargets.All); static Assembly orig_sec_assembly; @@ -137,7 +137,7 @@ namespace Mono.CSharp { att_cache = new PtrHashtable (); } - public void AttachTo (Attributable owner) + public virtual void AttachTo (Attributable owner) { if (this.owners == null) { this.owners = new Attributable[1] { owner }; @@ -174,13 +174,24 @@ namespace Mono.CSharp { Report.Error (182, loc, "An attribute argument must be a constant expression, typeof " + "expression or array creation expression"); - } + } + + static void Error_TypeParameterInAttribute (Location loc) + { + Report.Error ( + -202, loc, "Can not use a type parameter in an attribute"); + } public void Error_MissingGuidAttribute () { Report.Error (596, Location, "The Guid attribute must be specified with the ComImport attribute"); } + public void Error_MisusedExtensionAttribute () + { + Report.Error (1112, Location, "Do not use `{0}' directly. Use parameter modifier `this' instead", GetSignatureForError ()); + } + /// /// This is rather hack. We report many emit attribute error with same error to be compatible with /// csc. But because csc has to report them this way because error came from ilasm we needn't. @@ -297,6 +308,29 @@ namespace Mono.CSharp { t == TypeManager.type_type; } + [Conditional ("GMCS_SOURCE")] + void ApplyModuleCharSet () + { + if (Type != TypeManager.dllimport_type) + return; + + if (!CodeGen.Module.HasDefaultCharSet) + return; + + const string CharSetEnumMember = "CharSet"; + if (NamedArguments == null) { + NamedArguments = new ArrayList (1); + } else { + foreach (DictionaryEntry de in NamedArguments) { + if ((string)de.Key == CharSetEnumMember) + return; + } + } + + NamedArguments.Add (new DictionaryEntry (CharSetEnumMember, + new Argument (Constant.CreateConstant (typeof (CharSet), CodeGen.Module.DefaultCharSet, Location)))); + } + public CustomAttributeBuilder Resolve () { if (resolve_error) @@ -330,15 +364,22 @@ namespace Mono.CSharp { Attributable owner = Owner; EmitContext ec = new EmitContext (owner.ResolveContext, owner.ResolveContext.DeclContainer, owner.ResolveContext.DeclContainer, - Location, null, null, owner.ResolveContext.DeclContainer.ModFlags, false); + Location, null, typeof (Attribute), owner.ResolveContext.DeclContainer.ModFlags, false); ec.IsAnonymousMethodAllowed = false; ConstructorInfo ctor = ResolveConstructor (ec); - if (ctor == null) + if (ctor == null) { + if (Type is TypeBuilder && + TypeManager.LookupDeclSpace (Type).MemberCache == null) + // The attribute type has been DefineType'd, but not Defined. Let's not treat it as an error. + // It'll be resolved again when the attached-to entity is emitted. + resolve_error = false; return null; + } - CustomAttributeBuilder cb; + ApplyModuleCharSet (); + CustomAttributeBuilder cb; try { if (NamedArguments == null) { cb = new CustomAttributeBuilder (ctor, pos_values); @@ -378,20 +419,21 @@ namespace Mono.CSharp { } } - Expression mg = Expression.MemberLookup (ec.ContainerType, + MethodGroupExpr mg = Expression.MemberLookup (ec.ContainerType, Type, ".ctor", MemberTypes.Constructor, BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly, - Location); + Location) as MethodGroupExpr; if (mg == null) return null; - MethodBase constructor = Invocation.OverloadResolve ( - ec, (MethodGroupExpr) mg, PosArguments, false, Location); - - if (constructor == null) + mg = mg.OverloadResolve (ec, PosArguments, false, Location); + if (mg == null) return null; + + ConstructorInfo constructor = (ConstructorInfo)mg; + // TODO: move to OverloadResolve ObsoleteAttribute oa = AttributeTester.GetMethodObsoleteAttribute (constructor); if (oa != null && !Owner.ResolveContext.IsInObsoleteScope) { AttributeTester.Report_ObsoleteMessage (oa, mg.GetSignatureForError (), mg.Location); @@ -399,7 +441,7 @@ namespace Mono.CSharp { if (PosArguments == null) { pos_values = EmptyObject; - return (ConstructorInfo)constructor; + return constructor; } ParameterData pd = TypeManager.GetParameterData (constructor); @@ -526,8 +568,7 @@ namespace Mono.CSharp { } if (member == null){ - Report.Error (117, Location, "`{0}' does not contain a definition for `{1}'", - TypeManager.CSharpName (Type), member_name); + Expression.Error_TypeDoesNotContainDefinition (Location, Type, member_name); return false; } @@ -536,6 +577,11 @@ namespace Mono.CSharp { return false; } + if (a.Expr is TypeParameterExpr){ + Error_TypeParameterInAttribute (Location); + return false; + } + ObsoleteAttribute obsolete_attr; if (member is PropertyExpr) { @@ -618,7 +664,7 @@ namespace Mono.CSharp { public string GetValidTargets () { StringBuilder sb = new StringBuilder (); - AttributeTargets targets = GetAttributeUsage ().ValidOn; + AttributeTargets targets = GetAttributeUsage (Type).ValidOn; if ((targets & AttributeTargets.Assembly) != 0) sb.Append ("assembly, "); @@ -670,32 +716,37 @@ namespace Mono.CSharp { } /// - /// Returns AttributeUsage attribute for this type + /// Returns AttributeUsage attribute based on types hierarchy /// - AttributeUsageAttribute GetAttributeUsage () + static AttributeUsageAttribute GetAttributeUsage (Type type) { - AttributeUsageAttribute ua = usage_attr_cache [Type] as AttributeUsageAttribute; + AttributeUsageAttribute ua = usage_attr_cache [type] as AttributeUsageAttribute; if (ua != null) return ua; - Class attr_class = TypeManager.LookupClass (Type); + Class attr_class = TypeManager.LookupClass (type); if (attr_class == null) { - object[] usage_attr = Type.GetCustomAttributes (TypeManager.attribute_usage_type, true); + object[] usage_attr = type.GetCustomAttributes (TypeManager.attribute_usage_type, true); ua = (AttributeUsageAttribute)usage_attr [0]; - usage_attr_cache.Add (Type, ua); + usage_attr_cache.Add (type, ua); return ua; } - Attribute a = attr_class.OptAttributes == null - ? null - : attr_class.OptAttributes.Search (TypeManager.attribute_usage_type); + Attribute a = null; + if (attr_class.OptAttributes != null) + a = attr_class.OptAttributes.Search (TypeManager.attribute_usage_type); - ua = a == null - ? DefaultUsageAttribute - : a.GetAttributeUsageAttribute (); + if (a == null) { + if (attr_class.TypeBuilder.BaseType != TypeManager.attribute_type) + ua = GetAttributeUsage (attr_class.TypeBuilder.BaseType); + else + ua = DefaultUsageAttribute; + } else { + ua = a.GetAttributeUsageAttribute (); + } - usage_attr_cache.Add (Type, ua); + usage_attr_cache.Add (type, ua); return ua; } @@ -841,21 +892,29 @@ namespace Mono.CSharp { /// public bool CheckSecurityActionValidity (bool for_assembly) { - SecurityAction action = GetSecurityActionValue (); + SecurityAction action = GetSecurityActionValue (); - if ((action == SecurityAction.RequestMinimum || action == SecurityAction.RequestOptional || - action == SecurityAction.RequestRefuse) && for_assembly) - return true; - - if (!for_assembly) { - if (action < SecurityAction.Demand || action > SecurityAction.InheritanceDemand) { - Error_AttributeEmitError ("SecurityAction is out of range"); - return false; - } - - if ((action != SecurityAction.RequestMinimum && action != SecurityAction.RequestOptional && - action != SecurityAction.RequestRefuse) && !for_assembly) + switch (action) { + case SecurityAction.Demand: + case SecurityAction.Assert: + case SecurityAction.Deny: + case SecurityAction.PermitOnly: + case SecurityAction.LinkDemand: + case SecurityAction.InheritanceDemand: + if (!for_assembly) + return true; + break; + + case SecurityAction.RequestMinimum: + case SecurityAction.RequestOptional: + case SecurityAction.RequestRefuse: + if (for_assembly) return true; + break; + + default: + Error_AttributeEmitError ("SecurityAction is out of range"); + return false; } Error_AttributeEmitError (String.Concat ("SecurityAction `", action, "' is not valid for this declaration")); @@ -1061,7 +1120,7 @@ namespace Mono.CSharp { return UnmanagedMarshal.DefineSafeArray (array_sub_type); case UnmanagedType.ByValArray: - FieldMember fm = attr as FieldMember; + FieldBase fm = attr as FieldBase; if (fm == null) { Error_AttributeEmitError ("Specified unmanaged type is only valid on fields"); return null; @@ -1081,11 +1140,19 @@ namespace Mono.CSharp { 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 bool IsInternalMethodImplAttribute { + get { + if (Type != TypeManager.methodimpl_attr_type) + return false; + + MethodImplOptions options; + if (pos_values[0].GetType () != typeof (MethodImplOptions)) + options = (MethodImplOptions)System.Enum.ToObject (typeof (MethodImplOptions), pos_values[0]); + else + options = (MethodImplOptions)pos_values[0]; + + return (options & MethodImplOptions.InternalCall) != 0; + } } public LayoutKind GetLayoutKindValue () @@ -1096,6 +1163,11 @@ namespace Mono.CSharp { return (LayoutKind)pos_values [0]; } + public object GetParameterDefaultValue () + { + return pos_values [0]; + } + public override bool Equals (object obj) { Attribute a = obj as Attribute; @@ -1110,11 +1182,6 @@ namespace Mono.CSharp { return base.GetHashCode (); } - public object GetParameterDefaultValue () - { - return pos_values [0]; - } - /// /// Emit attribute for Attributable symbol /// @@ -1124,7 +1191,7 @@ namespace Mono.CSharp { if (cb == null) return; - AttributeUsageAttribute usage_attr = GetAttributeUsage (); + AttributeUsageAttribute usage_attr = GetAttributeUsage (Type); if ((usage_attr.ValidOn & Target) == 0) { Report.Error (592, Location, "The attribute `{0}' is not valid on this declaration type. " + "It is valid on `{1}' declarations only", @@ -1189,121 +1256,6 @@ namespace Mono.CSharp { } } } - - public MethodBuilder DefinePInvokeMethod (TypeBuilder builder, string name, - MethodAttributes flags, Type ret_type, Type [] param_types) - { - 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 (); - - if (resolve_error) - return null; - - string dll_name = (string)pos_values [0]; - - // Default settings - CallingConvention cc = CallingConvention.Winapi; - CharSet charset = CodeGen.Module.DefaultCharSet; - bool preserve_sig = true; - string entry_point = name; - bool best_fit_mapping = false; - bool throw_on_unmappable = false; - bool exact_spelling = false; - 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 (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 ((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; - } - } - - 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; - } - catch (ArgumentException e) { - Error_AttributeEmitError (e.Message); - return null; - } - } private Expression GetValue () { @@ -1316,16 +1268,16 @@ namespace Mono.CSharp { public string GetString () { Expression e = GetValue (); - if (e is StringLiteral) - return (e as StringLiteral).Value; + if (e is StringConstant) + return ((StringConstant)e).Value; return null; } public bool GetBoolean () { Expression e = GetValue (); - if (e is BoolLiteral) - return (e as BoolLiteral).Value; + if (e is BoolConstant) + return ((BoolConstant)e).Value; return false; } @@ -1352,26 +1304,40 @@ namespace Mono.CSharp { base (target, left_expr, identifier, args, loc, nameEscaped) { this.ns = ns; + this.owners = new Attributable[1]; + } + + public override void AttachTo (Attributable owner) + { + if (ExplicitTarget == "assembly") { + owners [0] = CodeGen.Assembly; + return; + } + if (ExplicitTarget == "module") { + owners [0] = CodeGen.Module; + return; + } + throw new NotImplementedException ("Unknown global explicit target " + ExplicitTarget); } void Enter () { - // RootContext.Tree.Types has a single NamespaceEntry which gets overwritten + // RootContext.ToplevelTypes has a single NamespaceEntry which gets overwritten // each time a new file is parsed. However, we need to use the NamespaceEntry // in effect where the attribute was used. Since code elsewhere cannot assume // that the NamespaceEntry is right, just overwrite it. // - // Precondition: RootContext.Tree.Types == null + // Precondition: RootContext.ToplevelTypes == null - if (RootContext.Tree.Types.NamespaceEntry != null) + if (RootContext.ToplevelTypes.NamespaceEntry != null) throw new InternalErrorException (Location + " non-null NamespaceEntry"); - RootContext.Tree.Types.NamespaceEntry = ns; + RootContext.ToplevelTypes.NamespaceEntry = ns; } void Leave () { - RootContext.Tree.Types.NamespaceEntry = null; + RootContext.ToplevelTypes.NamespaceEntry = null; } protected override TypeExpr ResolveAsTypeTerminal (Expression expr, IResolveContext ec, bool silent) @@ -1492,7 +1458,8 @@ namespace Mono.CSharp { Report.SymbolRelatedToPreviousError (collision.Location, ""); Attribute a = (Attribute)d.Key; - Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", a.GetSignatureForError ()); + Report.Error (579, a.Location, "The attribute `{0}' cannot be applied multiple times", + a.GetSignatureForError ()); } } @@ -1618,8 +1585,10 @@ namespace Mono.CSharp { } bool result; - if (type.IsArray || type.IsByRef) { + if (type.IsArray || type.IsByRef) { result = IsClsCompliant (TypeManager.GetElementType (type)); + } else if (TypeManager.IsNullableType (type)) { + result = IsClsCompliant (TypeManager.GetTypeArguments (type) [0]); } else { result = AnalyzeTypeCompliance (type); } @@ -1632,15 +1601,22 @@ namespace Mono.CSharp { /// public static IFixedBuffer GetFixedBuffer (FieldInfo fi) { + // Fixed buffer helper type is generated as value type + if (!fi.FieldType.IsValueType) + return null; + FieldBase fb = TypeManager.GetField (fi); if (fb != null) { return fb as IFixedBuffer; } + + if (TypeManager.GetConstant (fi) != null) + return null; #if NET_2_0 object o = fixed_buffer_cache [fi]; if (o == null) { - if (System.Attribute.GetCustomAttribute (fi, TypeManager.fixed_buffer_attr_type) == null) { + if (!fi.IsDefined (TypeManager.fixed_buffer_attr_type, false)) { fixed_buffer_cache.Add (fi, FALSE); return null; } @@ -1656,7 +1632,7 @@ namespace Mono.CSharp { return (IFixedBuffer)o; #else return null; -#endif +#endif } public static void VerifyModulesClsCompliance () @@ -1700,11 +1676,15 @@ namespace Mono.CSharp { static bool AnalyzeTypeCompliance (Type type) { + type = TypeManager.DropGenericTypeArguments (type); DeclSpace ds = TypeManager.LookupDeclSpace (type); if (ds != null) { return ds.IsClsComplianceRequired (); } + if (TypeManager.IsGenericParameter (type)) + return true; + object[] CompliantAttribute = type.GetCustomAttributes (TypeManager.cls_compliant_attribute_type, false); if (CompliantAttribute.Length == 0) return IsClsCompliant (type.Assembly); @@ -1712,6 +1692,13 @@ namespace Mono.CSharp { return ((CLSCompliantAttribute)CompliantAttribute[0]).IsCompliant; } + // Registers the core type as we assume that they will never be obsolete which + // makes things easier for bootstrap and faster (we don't need to query Obsolete attribute). + public static void RegisterNonObsoleteType (Type type) + { + analyzed_types_obsolete [type] = FALSE; + } + /// /// Returns instance of ObsoleteAttribute when type is obsolete /// @@ -1725,9 +1712,11 @@ namespace Mono.CSharp { return (ObsoleteAttribute)type_obsolete; ObsoleteAttribute result = null; - if (type.IsByRef || type.IsArray || type.IsPointer) { + if (TypeManager.HasElementType (type)) { result = GetObsoleteAttribute (TypeManager.GetElementType (type)); - } else { + } else if (TypeManager.IsGenericParameter (type) || TypeManager.IsGenericType (type)) + return null; + else { DeclSpace type_ds = TypeManager.LookupDeclSpace (type); // Type is external, we can get attribute directly @@ -1736,9 +1725,7 @@ namespace Mono.CSharp { if (attribute.Length == 1) result = (ObsoleteAttribute)attribute [0]; } else { - // Is null during corlib bootstrap - if (TypeManager.obsolete_attribute_type != null) - result = type_ds.GetObsoleteAttribute (); + result = type_ds.GetObsoleteAttribute (); } } @@ -1760,14 +1747,13 @@ namespace Mono.CSharp { if (mb.DeclaringType is TypeBuilder) return null; - 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); - } - } + MemberInfo mi = TypeManager.GetPropertyFromAccessor (mb); + if (mi != null) + return GetMemberObsoleteAttribute (mi); + + mi = TypeManager.GetEventFromAccessor (mb); + if (mi != null) + return GetMemberObsoleteAttribute (mi); return GetMemberObsoleteAttribute (mb); } @@ -1784,6 +1770,9 @@ namespace Mono.CSharp { if (type_obsolete != null) return (ObsoleteAttribute)type_obsolete; + if ((mi.DeclaringType is TypeBuilder) || TypeManager.IsGenericType (mi.DeclaringType)) + return null; + ObsoleteAttribute oa = System.Attribute.GetCustomAttribute (mi, TypeManager.obsolete_attribute_type, false) as ObsoleteAttribute; analyzed_member_obsolete.Add (mi, oa == null ? FALSE : oa); @@ -1809,10 +1798,15 @@ namespace Mono.CSharp { public static bool IsConditionalMethodExcluded (MethodBase mb) { + mb = TypeManager.DropGenericMethodArguments (mb); + // TODO: Has to be fixed for partial methods + if ((mb is MethodBuilder) || (mb is ConstructorBuilder)) + return false; + object excluded = analyzed_method_excluded [mb]; if (excluded != null) return excluded == TRUE ? true : false; - + ConditionalAttribute[] attrs = mb.GetCustomAttributes (TypeManager.conditional_attribute_type, true) as ConditionalAttribute[]; if (attrs.Length == 0) {