X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fmcs%2Fimport.cs;h=72538a2da18ecf16cded87dfe6ee278b9feffbfa;hb=3fbd4b873c76d01f900a10a6e02dd6d38c376914;hp=4880b3fa021ba4fc1c38ca0236e57bba410e524a;hpb=c94081e227618d45ce0c0b42ebe5fd2fb3ba24ae;p=mono.git diff --git a/mcs/mcs/import.cs b/mcs/mcs/import.cs index 4880b3fa021..72538a2da18 100644 --- a/mcs/mcs/import.cs +++ b/mcs/mcs/import.cs @@ -6,7 +6,7 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2009-2011 Novell, Inc -// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) +// Copyright 2011-2012 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -32,7 +32,7 @@ namespace Mono.CSharp // Dynamic types reader with additional logic to reconstruct a dynamic // type using DynamicAttribute values // - struct DynamicTypeReader + protected struct DynamicTypeReader { static readonly bool[] single_attribute = { true }; @@ -56,10 +56,10 @@ namespace Mono.CSharp // // Returns true when object at local position has dynamic attribute flag // - public bool IsDynamicObject (MetadataImporter importer) + public bool IsDynamicObject () { if (provider != null) - ReadAttribute (importer); + ReadAttribute (); return flags != null && Position < flags.Length && flags[Position]; } @@ -67,15 +67,15 @@ namespace Mono.CSharp // // Returns true when DynamicAttribute exists // - public bool HasDynamicAttribute (MetadataImporter importer) + public bool HasDynamicAttribute () { if (provider != null) - ReadAttribute (importer); + ReadAttribute (); return flags != null; } - void ReadAttribute (MetadataImporter importer) + void ReadAttribute () { IList cad; if (provider is MemberInfo) { @@ -120,7 +120,7 @@ namespace Mono.CSharp protected readonly Dictionary import_cache; protected readonly Dictionary compiled_types; protected readonly Dictionary assembly_2_definition; - readonly ModuleContainer module; + protected readonly ModuleContainer module; public static readonly string CompilerServicesNamespace = "System.Runtime.CompilerServices"; @@ -152,7 +152,7 @@ namespace Mono.CSharp public FieldSpec CreateField (FieldInfo fi, TypeSpec declaringType) { - Modifiers mod = 0; + Modifiers mod; var fa = fi.Attributes; switch (fa & FieldAttributes.FieldAccessMask) { case FieldAttributes.Public: @@ -220,7 +220,7 @@ namespace Mono.CSharp // TODO: Sanity check on field_type (only few types are allowed) var element_field = CreateField (fi.FieldType.GetField (FixedField.FixedElementName), declaringType); - return new FixedFieldSpec (declaringType, definition, fi, element_field, mod); + return new FixedFieldSpec (module, declaringType, definition, fi, element_field, mod); } } @@ -324,10 +324,9 @@ namespace Mono.CSharp // IFoo> foo; // A is definition in this case // } // - // TODO: Is full logic from CreateType needed here as well? - // if (!IsMissingType (type) && type.IsGenericTypeDefinition) { - var targs = CreateGenericArguments (0, type.GetGenericArguments (), dtype); + var start_pos = spec.DeclaringType == null ? 0 : spec.DeclaringType.MemberDefinition.TypeParametersCount; + var targs = CreateGenericArguments (start_pos, type.GetGenericArguments (), dtype); spec = spec.MakeGenericType (module, targs); } } @@ -420,7 +419,7 @@ namespace Mono.CSharp } } - IMemberDefinition definition; + IMethodDefinition definition; if (tparams != null) { var gmd = new ImportedGenericMethodDefinition ((MethodInfo) mb, returnType, parameters, tparams, this); foreach (var tp in gmd.TypeParameters) { @@ -429,10 +428,10 @@ namespace Mono.CSharp definition = gmd; } else { - definition = new ImportedParameterMemberDefinition (mb, returnType, parameters, this); + definition = new ImportedMethodDefinition (mb, returnType, parameters, this); } - MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, mb, parameters, mod); + MethodSpec ms = new MethodSpec (kind, declaringType, definition, returnType, parameters, mod); if (tparams != null) ms.IsGeneric = true; @@ -491,7 +490,7 @@ namespace Mono.CSharp // var el = p.ParameterType.GetElementType (); types[i] = ImportType (el, new DynamicTypeReader (p)); // TODO: 1-based positio to be csc compatible - } else if (i == 0 && method.IsStatic && parent.IsStatic && parent.MemberDefinition.DeclaringAssembly.HasExtensionMethod && + } else if (i == 0 && method.IsStatic && (parent.Modifiers & Modifiers.METHOD_EXTENSION) != 0 && HasAttribute (CustomAttributeData.GetCustomAttributes (method), "ExtensionAttribute", CompilerServicesNamespace)) { mod = Parameter.Modifier.This; types[i] = ImportType (p.ParameterType); @@ -510,7 +509,7 @@ namespace Mono.CSharp var ptype = types[i]; if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeSpec.IsReferenceType (ptype))) { if (value == null) { - default_value = Constant.CreateConstant (ptype, null, Location.Null); + default_value = Constant.CreateConstantFromValue (ptype, null, Location.Null); } else { default_value = ImportParameterConstant (value); @@ -518,6 +517,21 @@ namespace Mono.CSharp default_value = new EnumConstant ((Constant) default_value, ptype); } } + + var attrs = CustomAttributeData.GetCustomAttributes (p); + for (int ii = 0; ii < attrs.Count; ++ii) { + var attr = attrs[ii]; + var dt = attr.Constructor.DeclaringType; + if (dt.Namespace != CompilerServicesNamespace) + continue; + + if (dt.Name == "CallerLineNumberAttribute" && (ptype.BuiltinType == BuiltinTypeSpec.Type.Int || Convert.ImplicitNumericConversionExists (module.Compiler.BuiltinTypes.Int, ptype))) + mod |= Parameter.Modifier.CallerLineNumber; + else if (dt.Name == "CallerFilePathAttribute" && Convert.ImplicitReferenceConversionExists (module.Compiler.BuiltinTypes.String, ptype)) + mod |= Parameter.Modifier.CallerFilePath; + else if (dt.Name == "CallerMemberNameAttribute" && Convert.ImplicitReferenceConversionExists (module.Compiler.BuiltinTypes.String, ptype)) + mod |= Parameter.Modifier.CallerMemberName; + } } else if (value == Missing.Value) { default_value = EmptyExpression.MissingValue; } else if (value == null) { @@ -620,26 +634,41 @@ namespace Mono.CSharp PropertySpec spec = null; if (!param.IsEmpty) { - var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember (); - if (index_name == null) { - is_valid_property = false; - } else { - if (get != null) { - if (get.IsStatic) - is_valid_property = false; - if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) - is_valid_property = false; + if (is_valid_property) { + var index_name = declaringType.MemberDefinition.GetAttributeDefaultMember (); + if (index_name == null) { + is_valid_property = false; + } else { + if (get != null) { + if (get.IsStatic) + is_valid_property = false; + if (get.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } + if (set != null) { + if (set.IsStatic) + is_valid_property = false; + if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) + is_valid_property = false; + } } - if (set != null) { - if (set.IsStatic) - is_valid_property = false; - if (set.Name.IndexOf (index_name, StringComparison.Ordinal) != 4) - is_valid_property = false; + + if (is_valid_property) { + spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod); + } else if (declaringType.MemberDefinition.IsComImport && param.FixedParameters[0].HasDefaultValue) { + // + // Enables support for properties with parameters (must have default value) of COM-imported types + // + is_valid_property = true; + + for (int i = 0; i < param.FixedParameters.Length; ++i) { + if (!param.FixedParameters[i].HasDefaultValue) { + is_valid_property = false; + break; + } + } } } - - if (is_valid_property) - spec = new IndexerSpec (declaringType, new ImportedParameterMemberDefinition (pi, type, param, this), type, param, pi, mod); } if (spec == null) @@ -679,12 +708,12 @@ namespace Mono.CSharp return CreateType (type, declaring_type, dtype, canImportBaseType); } - TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) + protected TypeSpec CreateType (MetaType type, TypeSpec declaringType, DynamicTypeReader dtype, bool canImportBaseType) { TypeSpec spec; if (import_cache.TryGetValue (type, out spec)) { if (spec.BuiltinType == BuiltinTypeSpec.Type.Object) { - if (dtype.IsDynamicObject (this)) + if (dtype.IsDynamicObject ()) return module.Compiler.BuiltinTypes.Dynamic; return spec; @@ -693,7 +722,7 @@ namespace Mono.CSharp if (!spec.IsGeneric || type.IsGenericTypeDefinition) return spec; - if (!dtype.HasDynamicAttribute (this)) + if (!dtype.HasDynamicAttribute ()) return spec; // We've found same object in the cache but this one has a dynamic custom attribute @@ -744,24 +773,34 @@ namespace Mono.CSharp for (int i = nested_hierarchy.Count; i != 0; --i) { var t = nested_hierarchy [i - 1]; - spec = MemberCache.FindNestedType (spec, t.Name, t.Arity); + if (t.Kind == MemberKind.MissingType) + spec = t; + else + spec = MemberCache.FindNestedType (spec, t.Name, t.Arity); + if (t.Arity > 0) { spec = spec.MakeGenericType (module, targs.Skip (targs_pos).Take (spec.Arity).ToArray ()); targs_pos += t.Arity; } } - string name = type.Name; - int index = name.IndexOf ('`'); - if (index > 0) - name = name.Substring (0, index); + if (spec.Kind == MemberKind.MissingType) { + spec = new TypeSpec (MemberKind.MissingType, spec, new ImportedTypeDefinition (type_def, this), type_def, Modifiers.PUBLIC); + spec.MemberCache = MemberCache.Empty; + } else { + if ((type_def.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedPrivate && IgnorePrivateMembers) + return null; + + string name = type.Name; + int index = name.IndexOf ('`'); + if (index > 0) + name = name.Substring (0, index); - spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos); - if (spec == null) - return null; + spec = MemberCache.FindNestedType (spec, name, targs.Length - targs_pos); - if (spec.Arity > 0) { - spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ()); + if (spec.Arity > 0) { + spec = spec.MakeGenericType (module, targs.Skip (targs_pos).ToArray ()); + } } } @@ -817,9 +856,10 @@ namespace Mono.CSharp if (kind == MemberKind.Class) { if ((ma & TypeAttributes.Sealed) != 0) { - mod |= Modifiers.SEALED; if ((ma & TypeAttributes.Abstract) != 0) mod |= Modifiers.STATIC; + else + mod |= Modifiers.SEALED; } else if ((ma & TypeAttributes.Abstract) != 0) { mod |= Modifiers.ABSTRACT; } @@ -976,53 +1016,6 @@ namespace Mono.CSharp spec.BaseType = base_type; } - MetaType[] ifaces; -#if STATIC - ifaces = type.__GetDeclaredInterfaces (); - if (ifaces.Length != 0) { - foreach (var iface in ifaces) { - var it = CreateType (iface); - if (it == null) - continue; - - spec.AddInterface (it); - - // Unfortunately not all languages expand inherited interfaces - var bifaces = it.Interfaces; - if (bifaces != null) { - foreach (var biface in bifaces) { - spec.AddInterface (biface); - } - } - } - } - - if (spec.BaseType != null) { - var bifaces = spec.BaseType.Interfaces; - if (bifaces != null) { - // - // Before adding base class interfaces close defined interfaces - // on type parameter - // - var tp = spec as TypeParameterSpec; - if (tp != null && tp.InterfacesDefined == null) { - tp.InterfacesDefined = TypeSpec.EmptyTypes; - } - - foreach (var iface in bifaces) - spec.AddInterface (iface); - } - } -#else - ifaces = type.GetInterfaces (); - - if (ifaces.Length > 0) { - foreach (var iface in ifaces) { - spec.AddInterface (CreateType (iface)); - } - } -#endif - if (spec.MemberDefinition.TypeParametersCount > 0) { foreach (var tp in spec.MemberDefinition.TypeParameters) { ImportTypeParameterTypeConstraints (tp, tp.GetMetaInfo ()); @@ -1030,7 +1023,7 @@ namespace Mono.CSharp } } - protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool hasExtensionTypes) + protected void ImportTypes (MetaType[] types, Namespace targetNamespace, bool importExtensionTypes) { Namespace ns = targetNamespace; string prev_namespace = null; @@ -1054,12 +1047,14 @@ namespace Mono.CSharp prev_namespace = t.Namespace; } - ns.AddType (module, it); - - if (it.IsStatic && hasExtensionTypes && + // Cannot rely on assembly level Extension attribute or static modifier because they + // are not followed by other compilers (e.g. F#). + if (it.IsClass && it.Arity == 0 && importExtensionTypes && HasAttribute (CustomAttributeData.GetCustomAttributes (t), "ExtensionAttribute", CompilerServicesNamespace)) { it.SetExtensionMethodContainer (); } + + ns.AddType (module, it); } } @@ -1377,7 +1372,7 @@ namespace Mono.CSharp protected AttributesBag cattrs; protected readonly MetadataImporter importer; - public ImportedDefinition (MemberInfo provider, MetadataImporter importer) + protected ImportedDefinition (MemberInfo provider, MetadataImporter importer) { this.provider = provider; this.importer = importer; @@ -1523,7 +1518,6 @@ namespace Mono.CSharp readonly Assembly assembly; readonly AssemblyName aname; bool cls_compliant; - bool contains_extension_methods; List internals_visible_to; Dictionary internals_visible_to_cache; @@ -1548,12 +1542,6 @@ namespace Mono.CSharp } } - public bool HasExtensionMethod { - get { - return contains_extension_methods; - } - } - public bool HasStrongName { get { return aname.GetPublicKey ().Length != 0; @@ -1671,13 +1659,6 @@ namespace Mono.CSharp internals_visible_to.Add (an); continue; } - - if (name == "ExtensionAttribute") { - if (dt.Namespace == MetadataImporter.CompilerServicesNamespace) - contains_extension_methods = true; - - continue; - } } } @@ -1712,7 +1693,7 @@ namespace Mono.CSharp { readonly AParametersCollection parameters; - public ImportedParameterMemberDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + protected ImportedParameterMemberDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) : base (provider, type, importer) { this.parameters = parameters; @@ -1735,7 +1716,21 @@ namespace Mono.CSharp #endregion } - class ImportedGenericMethodDefinition : ImportedParameterMemberDefinition, IGenericMethodDefinition + class ImportedMethodDefinition : ImportedParameterMemberDefinition, IMethodDefinition + { + public ImportedMethodDefinition (MethodBase provider, TypeSpec type, AParametersCollection parameters, MetadataImporter importer) + : base (provider, type, parameters, importer) + { + } + + MethodBase IMethodDefinition.Metadata { + get { + return (MethodBase) provider; + } + } + } + + class ImportedGenericMethodDefinition : ImportedMethodDefinition, IGenericMethodDefinition { readonly TypeParameterSpec[] tparams; @@ -1780,12 +1775,29 @@ namespace Mono.CSharp } } + bool ITypeDefinition.IsComImport { + get { + return ((MetaType) provider).IsImport; + } + } + + bool ITypeDefinition.IsPartial { get { return false; } } + bool ITypeDefinition.IsTypeForwarder { + get { +#if STATIC + return ((MetaType) provider).__IsTypeForwarder; +#else + return false; +#endif + } + } + public override string Name { get { if (name == null) { @@ -1824,7 +1836,64 @@ namespace Mono.CSharp #endregion - public static void Error_MissingDependency (IMemberContext ctx, List types, Location loc) + public void DefineInterfaces (TypeSpec spec) + { + var type = (MetaType) provider; + MetaType[] ifaces; +#if STATIC + ifaces = type.__GetDeclaredInterfaces (); + if (ifaces.Length != 0) { + foreach (var iface in ifaces) { + var it = importer.CreateType (iface); + if (it == null) + continue; + + spec.AddInterfaceDefined (it); + + // Unfortunately not all languages expand inherited interfaces + var bifaces = it.Interfaces; + if (bifaces != null) { + foreach (var biface in bifaces) { + spec.AddInterfaceDefined (biface); + } + } + } + } + + // + // It's impossible to get declared interfaces only using System.Reflection + // hence we need to mimic the behavior with ikvm-reflection too to keep + // our type look-up logic same + // + if (spec.BaseType != null) { + var bifaces = spec.BaseType.Interfaces; + if (bifaces != null) { + // + // Before adding base class interfaces close defined interfaces + // on type parameter + // + var tp = spec as TypeParameterSpec; + if (tp != null && tp.InterfacesDefined == null) { + tp.InterfacesDefined = TypeSpec.EmptyTypes; + } + + foreach (var iface in bifaces) + spec.AddInterfaceDefined (iface); + } + } +#else + ifaces = type.GetInterfaces (); + + if (ifaces.Length > 0) { + foreach (var iface in ifaces) { + spec.AddInterface (importer.CreateType (iface)); + } + } +#endif + + } + + public static void Error_MissingDependency (IMemberContext ctx, List missing, Location loc) { // // Report details about missing type and most likely cause of the problem. @@ -1832,27 +1901,40 @@ namespace Mono.CSharp // or referenced from the user core in which case compilation error has to // be reported because compiler cannot continue anyway // - for (int i = 0; i < types.Count; ++i) { - var t = types [i]; + + var report = ctx.Module.Compiler.Report; + + for (int i = 0; i < missing.Count; ++i) { + var t = missing [i].Type; // - // Report missing types only once per type + // Report missing types only once // - if (i > 0 && types.IndexOf (t) < i) + if (report.Printer.MissingTypeReported (t.MemberDefinition)) continue; string name = t.GetSignatureForError (); + var caller = missing[i].Caller; + if (caller.Kind != MemberKind.MissingType) + report.SymbolRelatedToPreviousError (caller); + if (t.MemberDefinition.DeclaringAssembly == ctx.Module.DeclaringAssembly) { - ctx.Module.Compiler.Report.Error (1683, loc, + report.Error (1683, loc, "Reference to type `{0}' claims it is defined in this assembly, but it is not defined in source or any added modules", name); } else if (t.MemberDefinition.DeclaringAssembly.IsMissing) { - ctx.Module.Compiler.Report.Error (12, loc, - "The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'", - name, t.MemberDefinition.DeclaringAssembly.FullName); + if (t.MemberDefinition.IsTypeForwarder) { + report.Error (1070, loc, + "The type `{0}' has been forwarded to an assembly that is not referenced. Consider adding a reference to assembly `{1}'", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } else { + report.Error (12, loc, + "The type `{0}' is defined in an assembly that is not referenced. Consider adding a reference to assembly `{1}'", + name, t.MemberDefinition.DeclaringAssembly.FullName); + } } else { - ctx.Module.Compiler.Report.Error (1684, loc, + report.Error (1684, loc, "Reference to type `{0}' claims it is defined assembly `{1}', but it could not be found", name, t.MemberDefinition.DeclaringAssembly.FullName); } @@ -2029,7 +2111,13 @@ namespace Mono.CSharp if (get == null && set == null) continue; - imported = importer.CreateProperty (p, declaringType, get, set); + try { + imported = importer.CreateProperty (p, declaringType, get, set); + } catch (Exception ex) { + throw new InternalErrorException (ex, "Could not import property `{0}' inside `{1}'", + p.Name, declaringType.GetSignatureForError ()); + } + if (imported == null) continue; @@ -2125,12 +2213,24 @@ namespace Mono.CSharp } } + bool ITypeDefinition.IsComImport { + get { + return false; + } + } + bool ITypeDefinition.IsPartial { get { return false; } } + bool ITypeDefinition.IsTypeForwarder { + get { + return false; + } + } + public string Namespace { get { return null;