Exemple #1
0
		public DocumentationParameter (Parameter.Modifier modifier, FullNamedExpression type)
			: this (type)
		{
			this.Modifier = modifier;
		}
		public ParameterData (string name, Parameter.Modifier modifiers)
		{
			this.name = name;
			this.modifiers = modifiers;
		}
Exemple #3
0
        /// <summary>
        ///   This function tells whether one of our base classes implements
        ///   the given method (which turns out, it is valid to have an interface
        ///   implementation in a base
        /// </summary>
        bool BaseImplements(TypeSpec iface_type, MethodSpec mi, out MethodSpec base_method)
        {
            base_method = null;
            var base_type = container.BaseType;

            //
            // Setup filter with no return type to give better error message
            // about mismatch at return type when the check bellow rejects them
            //
            var parameters = mi.Parameters;

            while (true)
            {
                var candidates = MemberCache.FindMembers(base_type, mi.Name, false);
                if (candidates == null)
                {
                    return(false);
                }

                MethodSpec similar_candidate = null;
                foreach (var candidate in candidates)
                {
                    if (candidate.Kind != MemberKind.Method)
                    {
                        continue;
                    }

                    if (candidate.Arity != mi.Arity)
                    {
                        continue;
                    }

                    var candidate_param = ((MethodSpec)candidate).Parameters;
                    if (!TypeSpecComparer.Override.IsSame(parameters.Types, candidate_param.Types))
                    {
                        continue;
                    }

                    bool modifiers_match = true;
                    for (int i = 0; i < parameters.Count; ++i)
                    {
                        //
                        // First check exact ref/out match
                        //
                        const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
                        if ((parameters.FixedParameters[i].ModFlags & ref_out) == (candidate_param.FixedParameters[i].ModFlags & ref_out))
                        {
                            continue;
                        }

                        modifiers_match = false;

                        //
                        // Different in ref/out only
                        //
                        if ((parameters.FixedParameters[i].ModFlags & candidate_param.FixedParameters[i].ModFlags & Parameter.Modifier.ISBYREF) != 0)
                        {
                            if (similar_candidate == null)
                            {
                                if (!candidate.IsPublic)
                                {
                                    break;
                                }

                                if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, ((MethodSpec)candidate).ReturnType))
                                {
                                    break;
                                }

                                // It's used for ref/out ambiguity overload check
                                similar_candidate = (MethodSpec)candidate;
                            }

                            continue;
                        }

                        similar_candidate = null;
                        break;
                    }

                    if (!modifiers_match)
                    {
                        continue;
                    }

                    //
                    // From this point on the candidate is used for detailed error reporting
                    // because it's very close match to what we are looking for
                    //
                    base_method = (MethodSpec)candidate;

                    if (!candidate.IsPublic)
                    {
                        return(false);
                    }

                    if (!TypeSpecComparer.Override.IsEqual(mi.ReturnType, base_method.ReturnType))
                    {
                        return(false);
                    }

                    if (mi.IsGeneric && !Method.CheckImplementingMethodConstraints(container, base_method, mi))
                    {
                        return(true);
                    }
                }

                if (base_method != null)
                {
                    if (similar_candidate != null)
                    {
                        Report.SymbolRelatedToPreviousError(similar_candidate);
                        Report.SymbolRelatedToPreviousError(mi);
                        Report.SymbolRelatedToPreviousError(container);
                        Report.Warning(1956, 1, ((MemberCore)base_method.MemberDefinition).Location,
                                       "The interface method `{0}' implementation is ambiguous between following methods: `{1}' and `{2}' in type `{3}'",
                                       mi.GetSignatureForError(), base_method.GetSignatureForError(), similar_candidate.GetSignatureForError(), container.GetSignatureForError());
                    }

                    break;
                }

                base_type = candidates[0].DeclaringType.BaseType;
                if (base_type == null)
                {
                    return(false);
                }
            }

            if (!base_method.IsVirtual)
            {
#if STATIC
                var base_builder = base_method.GetMetaInfo() as MethodBuilder;
                if (base_builder != null)
                {
                    //
                    // We can avoid creating a proxy if base_method can be marked 'final virtual'. This can
                    // be done for all methods from compiled assembly
                    //
                    base_builder.__SetAttributes(base_builder.Attributes | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot);
                    return(true);
                }
#endif
                DefineProxy(iface_type, base_method, mi);
            }

            return(true);
        }
		PendingImplementation (TypeContainer container, MissingInterfacesInfo [] missing_ifaces, ArrayList abstract_methods, int total)
		{
			TypeBuilder type_builder = container.TypeBuilder;
			
			this.container = container;
			pending_implementations = new TypeAndMethods [total];

			int i = 0;
			if (abstract_methods != null) {
				int count = abstract_methods.Count;
				pending_implementations [i].methods = new MethodInfo [count];
				pending_implementations [i].need_proxy = new MethodInfo [count];
				
				abstract_methods.CopyTo (pending_implementations [i].methods, 0);
				pending_implementations [i].found = new MethodData [count];
				pending_implementations [i].args = new Type [count][];
				pending_implementations [i].mods = new Parameter.Modifier [count][];
				pending_implementations [i].type = type_builder;

				int j = 0;
				foreach (MemberInfo m in abstract_methods) {
					MethodInfo mi = (MethodInfo) m;
					
					AParametersCollection pd = TypeManager.GetParameterData (mi);
					Type [] types = pd.Types;
					
					pending_implementations [i].args [j] = types;
					pending_implementations [i].mods [j] = null;
					if (pd.Count > 0) {
						Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
						for (int k = 0; k < pd.Count; k++)
							pm [k] = pd.FixedParameters[k].ModFlags;
						pending_implementations [i].mods [j] = pm;
					}
						
					j++;
				}
				++i;
			}

			foreach (MissingInterfacesInfo missing in missing_ifaces) {
				MethodInfo [] mi;
				Type t = missing.Type;
				
				if (!t.IsInterface)
					continue;

				if (t is TypeBuilder){
					TypeContainer iface;

					iface = TypeManager.LookupInterface (t);
					
					mi = iface.GetMethods ();
				} else 
					mi = t.GetMethods ();
				
				int count = mi.Length;
				pending_implementations [i].type = t;
				pending_implementations [i].optional = missing.Optional;
				pending_implementations [i].methods = mi;
				pending_implementations [i].args = new Type [count][];
				pending_implementations [i].mods = new Parameter.Modifier [count][];
				pending_implementations [i].found = new MethodData [count];
				pending_implementations [i].need_proxy = new MethodInfo [count];
				
				int j = 0;
				foreach (MethodInfo m in mi){
  					pending_implementations [i].args [j] = Type.EmptyTypes;
					pending_implementations [i].mods [j] = null;

					// If there is a previous error, just ignore
					if (m == null)
						continue;

 					AParametersCollection pd = TypeManager.GetParameterData (m);
					pending_implementations [i].args [j] = pd.Types;
 					
 					if (pd.Count > 0){
 						Parameter.Modifier [] pm = new Parameter.Modifier [pd.Count];
 						for (int k = 0; k < pd.Count; k++)
 							pm [k] = pd.FixedParameters [k].ModFlags;
 						pending_implementations [i].mods [j] = pm;
 					}
			
					j++;
				}
				i++;
			}
		}
Exemple #5
0
 public DocumentationParameter(Parameter.Modifier modifier, FullNamedExpression type)
     : this(type)
 {
     this.Modifier = modifier;
 }
Exemple #6
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(TypeContainer 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
                            //
                            const Parameter.Modifier ref_out = Parameter.Modifier.REF | Parameter.Modifier.OUT;
                            if ((cp[pi].ModFlags & ref_out) == (tp[pi].ModFlags & ref_out))
                            {
                                continue;
                            }

                            if ((cp[pi].ModFlags & tp[pi].ModFlags & Parameter.Modifier.ISBYREF) != 0)
                            {
                                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);
        }
Exemple #7
0
 public static ParameterAttributes GetParameterAttribute(Parameter.Modifier modFlags)
 {
     return((modFlags & Parameter.Modifier.OUT) == Parameter.Modifier.OUT ?
            ParameterAttributes.Out : ParameterAttributes.None);
 }
Exemple #8
0
 public ParameterData(string name, Parameter.Modifier modifiers, Expression defaultValue)
     : this(name, modifiers)
 {
     this.default_value = defaultValue;
 }
Exemple #9
0
 public ParameterData(string name, Parameter.Modifier modifiers)
 {
     this.name      = name;
     this.modifiers = modifiers;
 }
Exemple #10
0
        public static void CreateIterator(IMethodData method, TypeContainer parent, int modifiers, CompilerContext ctx)
        {
            bool is_enumerable;
            Type iterator_type;

            Type ret = method.ReturnType;

            if (ret == null)
            {
                return;
            }

            if (!CheckType(ret, out iterator_type, out is_enumerable))
            {
                ctx.Report.Error(1624, method.Location,
                                 "The body of `{0}' cannot be an iterator block " +
                                 "because `{1}' is not an iterator interface type",
                                 method.GetSignatureForError(),
                                 TypeManager.CSharpName(ret));
                return;
            }

            ParametersCompiled parameters = method.ParameterInfo;

            for (int i = 0; i < parameters.Count; i++)
            {
                Parameter          p   = parameters [i];
                Parameter.Modifier mod = p.ModFlags;
                if ((mod & Parameter.Modifier.ISBYREF) != 0)
                {
                    ctx.Report.Error(1623, p.Location,
                                     "Iterators cannot have ref or out parameters");
                    return;
                }

                if (p is ArglistParameter)
                {
                    ctx.Report.Error(1636, method.Location,
                                     "__arglist is not allowed in parameter list of iterators");
                    return;
                }

                if (parameters.Types [i].IsPointer)
                {
                    ctx.Report.Error(1637, p.Location,
                                     "Iterators cannot have unsafe parameters or " +
                                     "yield types");
                    return;
                }
            }

            if ((modifiers & Modifiers.UNSAFE) != 0)
            {
                ctx.Report.Error(1629, method.Location, "Unsafe code may not appear in iterators");
                return;
            }

            Iterator iter = new Iterator(ctx, method, parent, iterator_type, is_enumerable);

            iter.Storey.DefineType();
        }
Exemple #11
0
 public ParameterData(string name, Parameter.Modifier modifiers)
 {
     _name      = name;
     _modifiers = modifiers;
 }