예제 #1
0
        private IEnumerable <Instruction> Sinks(BasicBlock <Instruction> block, Instruction instruction, CFG cdfg)
        {
            switch (instruction.Operation.OperationCode)
            {
            case OperationCode.Call:
            case OperationCode.Callvirt:
            {
                var methodRef = instruction.Operation.Value as IMethodReference;
                if (methodRef != null)
                {
                    if (IsDisposeMethod(methodRef))
                    {
                        var constraint = block.CallConstraint(instruction);
                        if (methodRef.ContainingType.IsValueType || constraint != null && (constraint.IsValueType || constraint is IGenericParameter))
                        {
                            // passing the address, figure out what local
                            var loc       = cdfg.LocalOrParameter(instruction.Operand1);
                            var toDispose = instruction[loc];
                            yield return(toDispose);
                        }
                        else
                        {
                            yield return(instruction.Operand1);        // consumes the "this" parameter
                        }
                    }

                    var args = instruction.Operand2 as Instruction[];
                    if (args != null)
                    {
                        foreach (var p in methodRef.Parameters)
                        {
                            if (p.IsByReference && IsDisposableType(p.Type) && p.Index < args.Length || PassingObligationTo(methodRef, p))
                            {
                                var arg = args[p.Index];
                                if (arg != null)
                                {
                                    yield return(arg);
                                }
                            }
                        }
                    }
                }
                break;
            }

            case OperationCode.Stfld:
                // consider fields escaping
                yield return(instruction.Operand2 as Instruction);

                break;

            case OperationCode.Stsfld:
                // consider fields escaping
                yield return(instruction.Operand1);

                break;

            case OperationCode.Ret:
                if (instruction.Operand1 != null && IsDisposableType(this.currentMethod.Type))
                {
                    yield return(instruction.Operand1);    // consumes the returned value
                }
                // by ref parameters are also sinks
                foreach (var p in this.currentMethod.Parameters)
                {
                    Instruction finalParameterValue;
                    if ((p.IsByReference || p.IsOut) && IsDisposableType(p.Type) && instruction.PostParamDefs != null && instruction.PostParamDefs.TryGetValue(p, out finalParameterValue))
                    {
                        yield return(finalParameterValue);
                    }
                }
                break;
            }
        }