Ejemplo n.º 1
0
        internal override InvalidInfo CheckValid(ValidityContext vctxt, MessageContext ctxt, RootEnvironment rootEnv)
        {
            var v = base.CheckValid(vctxt, ctxt, rootEnv);

            if (v != null)
            {
                return(v);
            }
            var typeEnv   = DefiningType.Enter(rootEnv);
            var methodDef = typeEnv.Type.ResolveMethod(signature);

            if (methodDef == null)
            {
                vctxt.Log(new InvalidMemberRef(ctxt, this, "No such method in defining type"));
                return(new InvalidInfo(MessageContextBuilders.Member(vctxt.Global, this)));
            }
            var methEnv = typeEnv.AddMethod(methodDef).AddSelfMethodBoundArguments();

            v = signature.CheckValid(vctxt, ctxt, methEnv);
            if (v != null)
            {
                return(v);
            }

            return(vctxt.ImplementableMemberRef(ctxt, rootEnv, this));
        }
Ejemplo n.º 2
0
        internal override void AccumUsedTypeAndMemberDefs(ValidityContext vctxt, AssemblyDef assemblyDef, TypeDef typeDef)
        {
            base.AccumUsedTypeAndMemberDefs(vctxt, assemblyDef, typeDef);
            var ctxt = MessageContextBuilders.Member(vctxt.Global, assemblyDef, typeDef, this);

            Invalid = FieldType.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
        }
Ejemplo n.º 3
0
        //
        // Validity
        //

        internal virtual InvalidInfo AccumUsedTypeDefs(ValidityContext vctxt, MessageContext ctxt, Set <QualifiedTypeName> usedTypes)
        {
            var v = DefiningType.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);

            if (v != null)
            {
                return(v);
            }
            v = Signature.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
            if (v != null)
            {
                return(v);
            }
            var assemblyDef = default(AssemblyDef);
            var typeDef     = default(TypeDef);

            if (DefiningType.PrimTryResolve(vctxt.Global, out assemblyDef, out typeDef))
            {
                if (!typeDef.HasMember(Signature))
                {
                    vctxt.Log
                        (new InvalidMemberRef
                            (ctxt, this, "Defining type does not contain definition for matching member"));
                    return(new InvalidInfo(MessageContextBuilders.Member(vctxt.Global, this)));
                }
            }
            return(null);
        }
Ejemplo n.º 4
0
        internal void PropogateInvalidity(Global global, AssemblyDef assemblyDef, TypeDef typeDef)
        {
            if (Invalid == null)
            {
                return;
            }

            if (usedByMembers != null)
            {
                var self = PrimReference(global, assemblyDef, typeDef, null);
                foreach (var r in usedByMembers)
                {
                    var usedByAssemblyDef = default(AssemblyDef);
                    var usedByTypeDef     = default(TypeDef);
                    var usedByMemberDef   = default(MemberDef);
                    if (r.PrimTryResolve(global, out usedByAssemblyDef, out usedByTypeDef, out usedByMemberDef))
                    {
                        if (usedByMemberDef.Invalid == null)
                        {
                            usedByMemberDef.Invalid = new InvalidInfo(MessageContextBuilders.Member(global, self), Invalid);
                        }
                    }
                }
            }
        }
Ejemplo n.º 5
0
        internal override void CheckValid(ValidityContext vctxt, TypeEnvironment typeEnv)
        {
            if (Invalid != null || typeEnv.Type.Invalid != null)
            {
                return;
            }
            var ctxt = MessageContextBuilders.Member(vctxt.Global, typeEnv.Assembly, typeEnv.Type, this);

            if (Get != null)
            {
                Invalid = Get.CheckValid(vctxt, ctxt, typeEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Set != null)
            {
                Invalid = Set.CheckValid(vctxt, ctxt, typeEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            Invalid = FieldType.CheckValid(vctxt, ctxt, typeEnv);
            if (Invalid != null)
            {
                vctxt.ImplementableMemberDef(typeEnv.Assembly, typeEnv.Type, this);
            }
        }
Ejemplo n.º 6
0
        internal override void CheckValid(ValidityContext vctxt, TypeEnvironment typeEnv)
        {
            if (Invalid != null || typeEnv.Type.Invalid != null)
            {
                return;
            }
            var ctxt = MessageContextBuilders.Member(vctxt.Global, typeEnv.Assembly, typeEnv.Type, this);

            if (Add != null)
            {
                Invalid = Add.CheckValid(vctxt, ctxt, typeEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Remove != null)
            {
                Invalid = Remove.CheckValid(vctxt, ctxt, typeEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            Invalid = HandlerType.CheckValid(vctxt, ctxt, typeEnv);
            if (Invalid != null)
            {
                return;
            }

            vctxt.ImplementableMemberDef(typeEnv.Assembly, typeEnv.Type, this);
        }
Ejemplo n.º 7
0
        internal override void AccumUsedTypeAndMemberDefs(ValidityContext vctxt, AssemblyDef assemblyDef, TypeDef typeDef)
        {
            base.AccumUsedTypeAndMemberDefs(vctxt, assemblyDef, typeDef);
            var ctxt = MessageContextBuilders.Member(vctxt.Global, assemblyDef, typeDef, this);

            for (var i = 0; i < TypeParameters.Count; i++)
            {
                var p = TypeParameters[i];
                p.AccumUsedTypeDefs(vctxt, assemblyDef, false);
                if (p.Invalid != null)
                {
                    Invalid = new InvalidInfo(MessageContextBuilders.TypeArg(ParameterFlavor.Method, i), p.Invalid);
                    return;
                }
            }
            foreach (var p in ValueParameters)
            {
                Invalid = p.Type.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Result != null)
            {
                Invalid = Result.Type.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }

            if (vctxt.IgnoreMethodDefBody(assemblyDef, typeDef, this))
            {
                return;
            }

            foreach (var l in Locals)
            {
                Invalid = l.Type.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            var instructions = Instructions(vctxt.Global);

            if (instructions != null)
            {
                foreach (var i in instructions.Body)
                {
                    Invalid = i.AccumUsedTypeAndMemberDefs(vctxt, ctxt, usedTypes, usedMembers);
                    if (Invalid != null)
                    {
                        return;
                    }
                }
            }
        }
Ejemplo n.º 8
0
        internal override InvalidInfo CheckValid(ValidityContext vctxt, MessageContext ctxt, RootEnvironment rootEnv)
        {
            var v = base.CheckValid(vctxt, ctxt, rootEnv);

            if (v != null)
            {
                return(v);
            }
            if (MethodTypeArguments.Count != MethodTypeArity)
            {
                vctxt.Log
                    (new InvalidMemberRef
                        (ctxt,
                        this,
                        String.Format
                            ("Polymorphic method has {0} type parameters but is applied to {1} type arguments",
                            MethodTypeArity,
                            MethodTypeArguments.Count)));
                return(new InvalidInfo(MessageContextBuilders.Member(vctxt.Global, this)));
            }

            v = MethodTypeArguments.Select(t => t.CheckValid(vctxt, ctxt, rootEnv)).FirstOrDefault(v2 => v2 != null);
            if (v != null)
            {
                return(v);
            }
            var groundMethodTypeArguments = rootEnv.SubstituteTypes(MethodTypeArguments);
            var typeEnv   = DefiningType.Enter(rootEnv);
            var methodDef = typeEnv.Type.ResolveMethod(signature);

            if (methodDef == null)
            {
                throw new InvalidOperationException("unable to resolve method");
            }
            var methEnv = typeEnv.AddMethod(methodDef).AddMethodBoundArguments(groundMethodTypeArguments);

            return(signature.CheckValid(vctxt, ctxt, methEnv));
        }
Ejemplo n.º 9
0
        internal override void AccumUsedTypeAndMemberDefs(ValidityContext vctxt, AssemblyDef assemblyDef, TypeDef typeDef)
        {
            base.AccumUsedTypeAndMemberDefs(vctxt, assemblyDef, typeDef);
            var ctxt = MessageContextBuilders.Member(vctxt.Global, assemblyDef, typeDef, this);

            if (Get != null)
            {
                Invalid = Get.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Set != null)
            {
                Invalid = Set.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            Invalid = FieldType.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
        }
Ejemplo n.º 10
0
        internal override void AccumUsedTypeAndMemberDefs(ValidityContext vctxt, AssemblyDef assemblyDef, TypeDef typeDef)
        {
            base.AccumUsedTypeAndMemberDefs(vctxt, assemblyDef, typeDef);
            var ctxt = MessageContextBuilders.Member(vctxt.Global, assemblyDef, typeDef, this);

            if (Add != null)
            {
                Invalid = Add.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Remove != null)
            {
                Invalid = Remove.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
                if (Invalid != null)
                {
                    return;
                }
            }
            Invalid = HandlerType.AccumUsedTypeDefs(vctxt, ctxt, usedTypes);
        }
Ejemplo n.º 11
0
        public void Check()
        {
            if (tracer != null)
            {
                tracer.AppendLine("Check {");
                tracer.Indent();
            }

            try
            {
                Stats("initial");

                // Phase 1:
                //  - Discover used root types and methods
                //  - Fixup assembly entry points
                //  - Lazily check names are valid, build the 'uses' and 'used-by' graph, and fixup some
                //    value-vs-ref type issues deferred by the loader.
                //  - Propogate initial usedness (will be refined later).
                var rootMembers = new Seq <QualifiedMemberName>();
                var rootTypes   = new Seq <QualifiedTypeName>();
                foreach (var assemblyDef in Global.Assemblies)
                {
                    var entryPoint = default(MethodRef);
                    foreach (var typeDef in assemblyDef.Types)
                    {
                        if (TypeAlwaysUsed(assemblyDef, typeDef))
                        {
                            rootTypes.Add(typeDef.QualifiedTypeName(Global, assemblyDef));
                            typeDef.MarkAsUsed(this, assemblyDef);
                        }
                        foreach (var memberDef in typeDef.Members)
                        {
                            var alwaysUsed = default(bool);
                            switch (memberDef.Flavor)
                            {
                            case MemberDefFlavor.Field:
                            {
                                var fieldDef = (FieldDef)memberDef;
                                alwaysUsed = FieldAlwaysUsed(assemblyDef, typeDef, fieldDef);
                                break;
                            }

                            case MemberDefFlavor.Method:
                            {
                                var methodDef = (MethodDef)memberDef;
                                if (IsAlternateEntryPoint(assemblyDef, typeDef, methodDef))
                                {
                                    var methodRef = methodDef.PrimMethodReference
                                                        (Global, assemblyDef, typeDef, null, null);
                                    if (entryPoint != null)
                                    {
                                        Log(new DuplicateEntryPointMessage(entryPoint, methodRef));
                                        throw new ExitException();
                                    }
                                    entryPoint = methodRef;
                                    // Will mark below
                                }
                                else
                                {
                                    alwaysUsed = MethodAlwaysUsed(assemblyDef, typeDef, methodDef);
                                }
                                break;
                            }

                            case MemberDefFlavor.Event:
                            {
                                var eventDef = (EventDef)memberDef;
                                alwaysUsed = EventAlwaysUsed(assemblyDef, typeDef, eventDef);
                                break;
                            }

                            case MemberDefFlavor.Property:
                            {
                                var propDef = (PropertyDef)memberDef;
                                alwaysUsed = PropertyAlwaysUsed(assemblyDef, typeDef, propDef);
                                break;
                            }

                            default:
                                throw new ArgumentOutOfRangeException();
                            }

                            if (alwaysUsed)
                            {
                                rootMembers.Add(memberDef.QualifiedMemberName(Global, assemblyDef, typeDef));
                                memberDef.MarkAsUsed(this, assemblyDef, typeDef);
                            }
                        }
                    }
                    if (entryPoint == null)
                    {
                        entryPoint = assemblyDef.EntryPoint;
                    }
                    else
                    {
                        assemblyDef.EntryPoint = entryPoint;
                    }

                    if (entryPoint != null)
                    {
                        // Entry points are implicity used
                        var entryAssemblyDef = default(AssemblyDef);
                        var entryTypeDef     = default(TypeDef);
                        var entryMemberDef   = default(MemberDef);
                        if (entryPoint.PrimTryResolve
                                (Global, out entryAssemblyDef, out entryTypeDef, out entryMemberDef))
                        {
                            rootMembers.Add
                                (entryMemberDef.QualifiedMemberName(Global, entryAssemblyDef, entryTypeDef));
                            entryMemberDef.MarkAsUsed(this, entryAssemblyDef, entryTypeDef);
                        }
                    }
                }

                var anyMarkedAsUsed = default(bool);
                var iter            = 0;
                do
                {
                    anyMarkedAsUsed = false;

                    // Phase 2: Construct topological sort of used types and members
                    //          (later only depends on earlier unless in a scc)
                    var visitedTypeDefs   = new Set <QualifiedTypeName>();
                    var sortedTypeDefs    = new Seq <QualifiedTypeName>();
                    var visitedMemberDefs = new Set <QualifiedMemberName>();
                    var sortedMemberDefs  = new Seq <QualifiedMemberName>();
                    foreach (var assemblyDef in Global.Assemblies)
                    {
                        foreach (var typeDef in assemblyDef.Types)
                        {
                            typeDef.TopologicalAllDeps(Global, assemblyDef, visitedTypeDefs, sortedTypeDefs);
                            foreach (var memberDef in typeDef.Members)
                            {
                                memberDef.TopologicalAllDeps
                                    (Global, assemblyDef, typeDef, visitedMemberDefs, sortedMemberDefs);
                            }
                        }
                    }

                    // Phase 3: Construct strongly connected components of types and members
                    visitedTypeDefs = new Set <QualifiedTypeName>();
                    var typeScc  = new Seq <QualifiedTypeName>();
                    var typeSccs = new Seq <Seq <QualifiedTypeName> >();
                    for (var i = sortedTypeDefs.Count - 1; i >= 0; i--)
                    {
                        var r           = sortedTypeDefs[i];
                        var assemblyDef = default(AssemblyDef);
                        var typeDef     = default(TypeDef);
                        if (r.PrimTryResolve(Global, out assemblyDef, out typeDef))
                        {
                            typeDef.UsedByTypesClosure(Global, assemblyDef, visitedTypeDefs, typeScc);
                            if (typeScc.Count > 0)
                            {
                                typeSccs.Add(typeScc);
                                typeScc = new Seq <QualifiedTypeName>();
                            }
                        }
                    }

                    visitedMemberDefs = new Set <QualifiedMemberName>();
                    var memberScc  = new Seq <QualifiedMemberName>();
                    var memberSccs = new Seq <Seq <QualifiedMemberName> >();
                    for (var i = sortedMemberDefs.Count - 1; i >= 0; i--)
                    {
                        var r           = sortedMemberDefs[i];
                        var assemblyDef = default(AssemblyDef);
                        var typeDef     = default(TypeDef);
                        var memberDef   = default(MemberDef);
                        if (r.PrimTryResolve(Global, out assemblyDef, out typeDef, out memberDef))
                        {
                            memberDef.UsedByMembersClosure(Global, assemblyDef, typeDef, visitedMemberDefs, memberScc);
                            if (memberScc.Count > 0)
                            {
                                memberSccs.Add(memberScc);
                                memberScc = new Seq <QualifiedMemberName>();
                            }
                        }
                    }

                    // Phase 4: Propogate failures known so far
                    //          (next step is expensive so good to avoid invalid definitions asap)
                    PropogateInvalidity(typeSccs, memberSccs);

                    Stats("iter " + iter + ", after first propogation");

                    // Phase 5:
                    //  - Check validity of types and members
                    //  - Fill-in the slot implementations for types
                    //  - Construct the slot-to-implementations graph.
                    var rootEnv = Global.Environment();
                    foreach (var assemblyDef in Global.Assemblies)
                    {
                        var assmEnv = rootEnv.AddAssembly(assemblyDef);
                        foreach (var typeDef in assemblyDef.Types.Where(t => t.Invalid == null && t.IsUsed))
                        {
                            var typeEnv = assmEnv.AddType(typeDef).AddSelfTypeBoundArguments();
                            typeDef.CheckValid(this, typeEnv);
                            foreach (var memberDef in typeDef.Members.Where(m => m.Invalid == null && m.IsUsed))
                            {
                                memberDef.CheckValid(this, typeEnv);
                            }
                        }
                    }

                    // Phase 6: Propogate any new failures discovered by above
                    PropogateInvalidity(typeSccs, memberSccs);

                    Stats("iter " + iter + ", after second propogation");

                    // Phase 7: Look for additional definitions to mark as used
                    //          (couldn't do so earlier since types weren't yet initialized)
                    foreach (var assemblyDef in Global.Assemblies)
                    {
                        foreach (var typeDef in assemblyDef.Types.Where(t => t.IsUsed && t.Invalid == null))
                        {
                            if (PropogateExtraUsedFromType(assemblyDef, typeDef))
                            {
                                anyMarkedAsUsed = true;
                            }
                            foreach (var memberDef in typeDef.Members.Where(m => m.IsUsed && m.Invalid == null))
                            {
                                if (PropogateExtraUsedFromMember(assemblyDef, typeDef, memberDef))
                                {
                                    anyMarkedAsUsed = true;
                                }
                            }
                        }
                    }

                    // Phase 8: Complete according to:
                    //  - used virtual/iface method and used implementing type => used override/impl methods of that type
                    //  - invalid overrifde/impl method => invalid virtual/iface method
                    //  - virtual/iface method must have a def and used implementing type => used override/impl methods of that type must have a def
                    foreach (var assemblyDef in Global.Assemblies)
                    {
                        foreach (var typeDef in assemblyDef.Types)
                        {
                            foreach (var methodDef in
                                     typeDef.Members.OfType <MethodDef>().Where(d => d.IsUsed && d.Implementors != null))
                            {
                                var slot             = methodDef.QualifiedMemberName(Global, assemblyDef, typeDef);
                                var forceDefinitions = IsMustHaveADefinition(slot);
                                foreach (var impl in methodDef.Implementors)
                                {
                                    var implAssemblyDef = default(AssemblyDef);
                                    var implTypeDef     = default(TypeDef);
                                    var implMemberDef   = default(MemberDef);
                                    if (impl.PrimTryResolve
                                            (Global, out implAssemblyDef, out implTypeDef, out implMemberDef))
                                    {
                                        if (implTypeDef.IsUsed)
                                        {
                                            if (forceDefinitions)
                                            {
                                                mustHaveADefinitionCache.Add(impl);
                                            }
                                            if (implMemberDef.MarkAsUsed(this, assemblyDef, typeDef))
                                            {
                                                anyMarkedAsUsed = true;
                                            }
                                            if (implMemberDef.Invalid != null && methodDef.Invalid == null)
                                            {
                                                methodDef.Invalid = new CST.InvalidInfo
                                                                        (MessageContextBuilders.Member
                                                                            (Global, implAssemblyDef, implTypeDef, implMemberDef),
                                                                        implMemberDef.Invalid);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // Phase 9: Propogate any new failures discovered by above
                    PropogateInvalidity(typeSccs, memberSccs);

                    Stats("iter " + iter + ", after third propogation");

                    iter++;
                }while (anyMarkedAsUsed);

                // Phase 10: Check roots are valid
                foreach (var typeName in rootTypes)
                {
                    var assemblyDef = default(AssemblyDef);
                    var typeDef     = default(TypeDef);
                    if (typeName.PrimTryResolve(Global, out assemblyDef, out typeDef))
                    {
                        if (typeDef.Invalid != null)
                        {
                            Log
                                (new UnimplementableUsedTypeMessage
                                    (MessageContextBuilders.Type(Global, assemblyDef, typeDef), typeDef.Invalid));
                            throw new ExitException();
                        }
                    }
                }
                foreach (var methodName in rootMembers)
                {
                    var assemblyDef = default(AssemblyDef);
                    var typeDef     = default(TypeDef);
                    var memberDef   = default(MemberDef);
                    if (methodName.PrimTryResolve(Global, out assemblyDef, out typeDef, out memberDef))
                    {
                        if (memberDef.Invalid != null)
                        {
                            Log
                                (new UnimplementableRootMethodMessage
                                    (MessageContextBuilders.Member(Global, assemblyDef, typeDef, memberDef),
                                    memberDef.Invalid));
                            throw new ExitException();
                        }
                    }
                }

                // Phase 11: Construct topological sort of type's according to their .cctor 'used' graph
                typeInitializationOrder = new Seq <QualifiedTypeName>();
                var visitedTypeDefs2 = new Set <QualifiedTypeName>();
                foreach (var assemblyDef in Global.Assemblies)
                {
                    foreach (var typeDef in assemblyDef.Types)
                    {
                        typeDef.TopologicalTypeInit(Global, assemblyDef, visitedTypeDefs2, typeInitializationOrder);
                    }
                }
            }
            finally
            {
                if (tracer != null)
                {
                    tracer.Outdent();
                    tracer.AppendLine("}");
                }
            }
        }
Ejemplo n.º 12
0
        private void PropogateInvalidity(Seq <Seq <QualifiedTypeName> > typeSccs, Seq <Seq <QualifiedMemberName> > memberSccs)
        {
            for (var i = typeSccs.Count - 1; i >= 0; i--)
            {
                var typeScc = typeSccs[i];
                if (typeScc.Count == 1)
                {
                    var sccAssemblyDef = default(AssemblyDef);
                    var sccTypeDef     = default(TypeDef);
                    if (typeScc[0].PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef))
                    {
                        sccTypeDef.PropogateInvalidity(Global, sccAssemblyDef);
                    }
                }
                else
                {
                    // Check if entire scc is valid
                    var invalid = default(InvalidInfo);
                    foreach (var r in typeScc)
                    {
                        var sccAssemblyDef = default(AssemblyDef);
                        var sccTypeDef     = default(TypeDef);
                        if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef))
                        {
                            if (sccTypeDef.Invalid != null)
                            {
                                invalid = new InvalidInfo
                                              (MessageContextBuilders.Type(Global, sccAssemblyDef, sccTypeDef),
                                              sccTypeDef.Invalid);
                                break;
                            }
                        }
                    }
                    if (invalid != null)
                    {
                        // Fail entire scc
                        foreach (var r in typeScc)
                        {
                            var sccAssemblyDef = default(AssemblyDef);
                            var sccTypeDef     = default(TypeDef);
                            if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef))
                            {
                                if (sccTypeDef.Invalid == null)
                                {
                                    sccTypeDef.Invalid = invalid;
                                }
                            }
                        }
                        // Propogate failure
                        foreach (var r in typeScc)
                        {
                            var sccAssemblyDef = default(AssemblyDef);
                            var sccTypeDef     = default(TypeDef);
                            if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef))
                            {
                                sccTypeDef.PropogateInvalidity(Global, sccAssemblyDef);
                            }
                        }
                    }
                }
            }

            for (var i = memberSccs.Count - 1; i >= 0; i--)
            {
                var memberScc = memberSccs[i];
                if (memberScc.Count == 1)
                {
                    var sccAssemblyDef = default(AssemblyDef);
                    var sccTypeDef     = default(TypeDef);
                    var sccMemberDef   = default(MemberDef);
                    if (memberScc[0].PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef, out sccMemberDef))
                    {
                        sccMemberDef.PropogateInvalidity(Global, sccAssemblyDef, sccTypeDef);
                        var sccMethodDef = sccMemberDef as CST.MethodDef;
                        if (sccMethodDef != null)
                        {
                            // Check if method is recursive
                            if (sccMethodDef.UsedMembers.Contains(memberScc[0]))
                            {
                                sccMethodDef.IsRecursive = true;
                            }
                        }
                    }
                }
                else if (memberScc.Count > 1)
                {
                    // Check if entire scc is valid, and mark methods as recursive
                    var invalid = default(InvalidInfo);
                    foreach (var r in memberScc)
                    {
                        var sccAssemblyDef = default(AssemblyDef);
                        var sccTypeDef     = default(TypeDef);
                        var sccMemberDef   = default(MemberDef);
                        if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef, out sccMemberDef))
                        {
                            if (sccMemberDef.Invalid != null && invalid == null)
                            {
                                invalid = new InvalidInfo
                                              (MessageContextBuilders.Member(Global, sccAssemblyDef, sccTypeDef, sccMemberDef),
                                              sccMemberDef.Invalid);
                            }
                            var sccMethodDef = sccMemberDef as CST.MethodDef;
                            if (sccMethodDef != null)
                            {
                                sccMethodDef.IsRecursive = true;
                            }
                        }
                    }
                    if (invalid != null)
                    {
                        // Fail entire scc
                        foreach (var r in memberScc)
                        {
                            var sccAssemblyDef = default(AssemblyDef);
                            var sccTypeDef     = default(TypeDef);
                            var sccMemberDef   = default(MemberDef);
                            if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef, out sccMemberDef))
                            {
                                if (sccMemberDef.Invalid == null)
                                {
                                    sccMemberDef.Invalid = invalid;
                                }
                            }
                        }
                        // Propogate failure
                        foreach (var r in memberScc)
                        {
                            var sccAssemblyDef = default(AssemblyDef);
                            var sccTypeDef     = default(TypeDef);
                            var sccMemberDef   = default(MemberDef);
                            if (r.PrimTryResolve(Global, out sccAssemblyDef, out sccTypeDef, out sccMemberDef))
                            {
                                sccMemberDef.PropogateInvalidity(Global, sccAssemblyDef, sccTypeDef);
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 13
0
        internal override void CheckValid(ValidityContext vctxt, TypeEnvironment typeEnv)
        {
            if (Invalid != null || typeEnv.Type.Invalid != null)
            {
                return;
            }

            var methEnv = typeEnv.AddMethod(this).AddSelfMethodBoundArguments();

            for (var i = 0; i < TypeParameters.Count; i++)
            {
                TypeParameters[i].CheckValid(vctxt, methEnv);
                if (TypeParameters[i].Invalid != null)
                {
                    Invalid = new InvalidInfo
                                  (MessageContextBuilders.TypeArg(ParameterFlavor.Method, i), TypeParameters[i].Invalid);
                    return;
                }
            }
            var ctxt = MessageContextBuilders.Member(vctxt.Global, typeEnv.Assembly, typeEnv.Type, this);

            foreach (var p in ValueParameters)
            {
                Invalid = p.Type.CheckValid(vctxt, ctxt, methEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            if (Result != null)
            {
                Invalid = Result.Type.CheckValid(vctxt, ctxt, methEnv);
                if (Invalid != null)
                {
                    return;
                }
            }

            if (vctxt.IgnoreMethodDefBody(typeEnv.Assembly, typeEnv.Type, this))
            {
                return;
            }

            foreach (var l in Locals)
            {
                Invalid = l.Type.CheckValid(vctxt, ctxt, methEnv);
                if (Invalid != null)
                {
                    return;
                }
            }
            var instructions = Instructions(vctxt.Global);

            if (instructions != null)
            {
                foreach (var i in instructions.Body)
                {
                    Invalid = i.CheckValid(vctxt, ctxt, methEnv);
                    if (Invalid != null)
                    {
                        return;
                    }
                    Invalid = vctxt.ImplementableInstruction(ctxt, methEnv.Assembly, methEnv.Type, this, i);
                    if (Invalid != null)
                    {
                        return;
                    }
                }
            }

            vctxt.ImplementableMemberDef(typeEnv.Assembly, typeEnv.Type, this);
        }