Example #1
0
 public void SetCustomAttribute(MethodSpec ctor, byte[] data)
 {
     FieldBuilder.SetCustomAttribute((ConstructorInfo)ctor.GetMetaInfo(), data);
 }
Example #2
0
 public void Emit(OpCode opcode, MethodSpec method, MetaType[] vargs)
 {
     // TODO MemberCache: This should mutate too
     ig.EmitCall(opcode, (MethodInfo)method.GetMetaInfo(), vargs);
 }
Example #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);
        }