Example #1
0
        //
        // Factory method: if there are pending implementation methods, we return a PendingImplementation
        // object, otherwise we return null.
        //
        // Register method implementations are either abstract methods
        // flagged as such on the base class or interface methods
        //
        static public PendingImplementation GetPendingImplementations(TypeDefinition container)
        {
            TypeSpec b = container.BaseType;

            var missing_interfaces = GetMissingInterfaces(container);

            //
            // If we are implementing an abstract class, and we are not
            // ourselves abstract, and there are abstract methods (C# allows
            // abstract classes that have no abstract methods), then allocate
            // one slot.
            //
            // We also pre-compute the methods.
            //
            bool implementing_abstract = ((b != null) && b.IsAbstract && (container.ModFlags & Modifiers.ABSTRACT) == 0);

            MethodSpec[] abstract_methods = null;

            if (implementing_abstract)
            {
                var am = MemberCache.GetNotImplementedAbstractMethods(b);

                if (am == null)
                {
                    implementing_abstract = false;
                }
                else
                {
                    abstract_methods = new MethodSpec[am.Count];
                    am.CopyTo(abstract_methods, 0);
                }
            }

            int total = missing_interfaces.Length + (implementing_abstract ? 1 : 0);

            if (total == 0)
            {
                return(null);
            }

            var pending = new PendingImplementation(container, missing_interfaces, abstract_methods, total);

            //
            // check for inherited conflicting methods
            //
            foreach (var p in pending.pending_implementations)
            {
                //
                // It can happen for generic interfaces only
                //
                if (!p.type.IsGeneric)
                {
                    continue;
                }

                //
                // CLR does not distinguishes between ref and out
                //
                for (int i = 0; i < p.methods.Count; ++i)
                {
                    MethodSpec compared_method = p.methods[i];
                    if (compared_method.Parameters.IsEmpty)
                    {
                        continue;
                    }

                    for (int ii = i + 1; ii < p.methods.Count; ++ii)
                    {
                        MethodSpec tested_method = p.methods[ii];
                        if (compared_method.Name != tested_method.Name)
                        {
                            continue;
                        }

                        if (p.type != tested_method.DeclaringType)
                        {
                            continue;
                        }

                        if (!TypeSpecComparer.Override.IsSame(compared_method.Parameters.Types, tested_method.Parameters.Types))
                        {
                            continue;
                        }

                        bool exact_match         = true;
                        bool ref_only_difference = false;
                        var  cp = compared_method.Parameters.FixedParameters;
                        var  tp = tested_method.Parameters.FixedParameters;

                        for (int pi = 0; pi < cp.Length; ++pi)
                        {
                            //
                            // First check exact modifiers match
                            //
                            if ((cp[pi].ModFlags & Parameter.Modifier.RefOutMask) == (tp[pi].ModFlags & Parameter.Modifier.RefOutMask))
                            {
                                continue;
                            }

                            if (((cp[pi].ModFlags | tp[pi].ModFlags) & Parameter.Modifier.RefOutMask) == Parameter.Modifier.RefOutMask)
                            {
                                ref_only_difference = true;
                                continue;
                            }

                            exact_match = false;
                            break;
                        }

                        if (!exact_match || !ref_only_difference)
                        {
                            continue;
                        }

                        pending.Report.SymbolRelatedToPreviousError(compared_method);
                        pending.Report.SymbolRelatedToPreviousError(tested_method);
                        pending.Report.Error(767, container.Location,
                                             "Cannot implement interface `{0}' with the specified type parameters because it causes method `{1}' to differ on parameter modifiers only",
                                             p.type.GetDefinition().GetSignatureForError(), compared_method.GetSignatureForError());

                        break;
                    }
                }
            }

            return(pending);
        }
Example #2
0
		protected virtual bool DoDefineMembers ()
		{
			Debug.Assert (!IsPartialPart);

			if (iface_exprs != null) {
				foreach (var iface_type in iface_exprs) {
					if (iface_type == null)
						continue;

					// Ensure the base is always setup
					var compiled_iface = iface_type.MemberDefinition as Interface;
					if (compiled_iface != null)
						compiled_iface.Define ();

					ObsoleteAttribute oa = iface_type.GetAttributeObsolete ();
					if (oa != null && !IsObsolete)
						AttributeTester.Report_ObsoleteMessage (oa, iface_type.GetSignatureForError (), Location, Report);

					if (iface_type.Arity > 0) {
						// TODO: passing `this' is wrong, should be base type iface instead
						VarianceDecl.CheckTypeVariance (iface_type, Variance.Covariant, this);

						if (((InflatedTypeSpec) iface_type).HasDynamicArgument () && !IsCompilerGenerated) {
							Report.Error (1966, Location,
								"`{0}': cannot implement a dynamic interface `{1}'",
								GetSignatureForError (), iface_type.GetSignatureForError ());
							return false;
						}
					}

					if (iface_type.IsGenericOrParentIsGeneric) {
						foreach (var prev_iface in iface_exprs) {
							if (prev_iface == iface_type || prev_iface == null)
								break;

							if (!TypeSpecComparer.Unify.IsEqual (iface_type, prev_iface))
								continue;

							Report.Error (695, Location,
								"`{0}' cannot implement both `{1}' and `{2}' because they may unify for some type parameter substitutions",
								GetSignatureForError (), prev_iface.GetSignatureForError (), iface_type.GetSignatureForError ());
						}
					}
				}

				if (Kind == MemberKind.Interface) {
					foreach (var iface in spec.Interfaces) {
						MemberCache.AddInterface (iface);
					}
				}
			}

			if (base_type != null) {
				//
				// Run checks skipped during DefineType (e.g FullNamedExpression::ResolveAsType)
				//
				if (base_type_expr != null) {
					ObsoleteAttribute obsolete_attr = base_type.GetAttributeObsolete ();
					if (obsolete_attr != null && !IsObsolete)
						AttributeTester.Report_ObsoleteMessage (obsolete_attr, base_type.GetSignatureForError (), base_type_expr.Location, Report);

					if (IsGenericOrParentIsGeneric && base_type.IsAttribute) {
						Report.Error (698, base_type_expr.Location,
							"A generic type cannot derive from `{0}' because it is an attribute class",
							base_type.GetSignatureForError ());
					}
				}

				var baseContainer = base_type.MemberDefinition as ClassOrStruct;
				if (baseContainer != null) {
					baseContainer.Define ();

					//
					// It can trigger define of this type (for generic types only)
					//
					if (HasMembersDefined)
						return true;
				}
			}

			if (Kind == MemberKind.Struct || Kind == MemberKind.Class) {
				pending = PendingImplementation.GetPendingImplementations (this);
			}

			var count = members.Count;		
			for (int i = 0; i < count; ++i) {
				var mc = members[i] as InterfaceMemberBase;
				if (mc == null || !mc.IsExplicitImpl)
					continue;

				try {
					mc.Define ();
				} catch (Exception e) {
					throw new InternalErrorException (mc, e);
				}
			}

			for (int i = 0; i < count; ++i) {
				var mc = members[i] as InterfaceMemberBase;
				if (mc != null && mc.IsExplicitImpl)
					continue;

				if (members[i] is TypeContainer)
					continue;

				try {
					members[i].Define ();
				} catch (Exception e) {
					throw new InternalErrorException (members[i], e);
				}
			}

			if (HasOperators) {
				CheckPairedOperators ();
			}

			if (requires_delayed_unmanagedtype_check) {
				requires_delayed_unmanagedtype_check = false;
				foreach (var member in members) {
					var f = member as Field;
					if (f != null && f.MemberType != null && f.MemberType.IsPointer)
						TypeManager.VerifyUnmanaged (Module, f.MemberType, f.Location);
				}
			}

			ComputeIndexerName();

			if (HasEquals && !HasGetHashCode) {
				Report.Warning (659, 3, Location,
					"`{0}' overrides Object.Equals(object) but does not override Object.GetHashCode()", GetSignatureForError ());
			}

			if (Kind == MemberKind.Interface && iface_exprs != null) {
				MemberCache.RemoveHiddenMembers (spec);
			}

			return true;
		}
Example #3
0
		//
		// Factory method: if there are pending implementation methods, we return a PendingImplementation
		// object, otherwise we return null.
		//
		// Register method implementations are either abstract methods
		// flagged as such on the base class or interface methods
		//
		static public PendingImplementation GetPendingImplementations (TypeDefinition container)
		{
			TypeSpec b = container.BaseType;

			var missing_interfaces = GetMissingInterfaces (container);

			//
			// If we are implementing an abstract class, and we are not
			// ourselves abstract, and there are abstract methods (C# allows
			// abstract classes that have no abstract methods), then allocate
			// one slot.
			//
			// We also pre-compute the methods.
			//
			bool implementing_abstract = ((b != null) && b.IsAbstract && (container.ModFlags & Modifiers.ABSTRACT) == 0);
			MethodSpec[] abstract_methods = null;

			if (implementing_abstract){
				var am = MemberCache.GetNotImplementedAbstractMethods (b);

				if (am == null) {
					implementing_abstract = false;
				} else {
					abstract_methods = new MethodSpec[am.Count];
					am.CopyTo (abstract_methods, 0);
				}
			}
			
			int total = missing_interfaces.Length +  (implementing_abstract ? 1 : 0);
			if (total == 0)
				return null;

			var pending = new PendingImplementation (container, missing_interfaces, abstract_methods, total);

			//
			// check for inherited conflicting methods
			//
			foreach (var p in pending.pending_implementations) {
				//
				// It can happen for generic interfaces only
				//
				if (!p.type.IsGeneric)
					continue;

				//
				// CLR does not distinguishes between ref and out
				//
				for (int i = 0; i < p.methods.Count; ++i) {
					MethodSpec compared_method = p.methods[i];
					if (compared_method.Parameters.IsEmpty)
						continue;

					for (int ii = i + 1; ii < p.methods.Count; ++ii) {
						MethodSpec tested_method = p.methods[ii];
						if (compared_method.Name != tested_method.Name)
							continue;

						if (p.type != tested_method.DeclaringType)
							continue;

						if (!TypeSpecComparer.Override.IsSame (compared_method.Parameters.Types, tested_method.Parameters.Types))
							continue;

						bool exact_match = true;
						bool ref_only_difference = false;
						var cp = compared_method.Parameters.FixedParameters;
						var tp = tested_method.Parameters.FixedParameters;

						for (int pi = 0; pi < cp.Length; ++pi) {
							//
							// First check exact modifiers match
							//
							if ((cp[pi].ModFlags & Parameter.Modifier.RefOutMask) == (tp[pi].ModFlags & Parameter.Modifier.RefOutMask))
								continue;

							if (((cp[pi].ModFlags | tp[pi].ModFlags) & Parameter.Modifier.RefOutMask) == Parameter.Modifier.RefOutMask) {
								ref_only_difference = true;
								continue;
							}

							exact_match = false;
							break;
						}

						if (!exact_match || !ref_only_difference)
							continue;

						pending.Report.SymbolRelatedToPreviousError (compared_method);
						pending.Report.SymbolRelatedToPreviousError (tested_method);
						pending.Report.Error (767, container.Location,
							"Cannot implement interface `{0}' with the specified type parameters because it causes method `{1}' to differ on parameter modifiers only",
							p.type.GetDefinition().GetSignatureForError (), compared_method.GetSignatureForError ());

						break;
					}
				}
			}

			return pending;
		}