private static ImmutableHashSet <CaptureId> CreateLValueFlowCaptures(ControlFlowGraph cfg)
        {
            var lvalueFlowCaptureIdBuilder = PooledHashSet <CaptureId> .GetInstance();

#if DEBUG
            var rvalueFlowCaptureIds = new Dictionary <CaptureId, HashSet <IFlowCaptureReferenceOperation> >();
#endif
            foreach (var flowCaptureReference in cfg.DescendantOperations <IFlowCaptureReferenceOperation>(OperationKind.FlowCaptureReference))
            {
                if (flowCaptureReference.IsLValueFlowCaptureReference())
                {
                    lvalueFlowCaptureIdBuilder.Add(flowCaptureReference.Id);
                }
#if DEBUG
                else
                {
                    if (!rvalueFlowCaptureIds.TryGetValue(flowCaptureReference.Id, out var operations))
                    {
                        operations = new HashSet <IFlowCaptureReferenceOperation>();
                        rvalueFlowCaptureIds[flowCaptureReference.Id] = operations;
                    }

                    operations.Add(flowCaptureReference);
                }
#endif
            }

#if DEBUG
            if (lvalueFlowCaptureIdBuilder.Count > 0)
            {
                foreach (var captureId in lvalueFlowCaptureIdBuilder)
                {
                    if (rvalueFlowCaptureIds.ContainsKey(captureId))
                    {
                        // Flow capture reference is used on left side as well as right side for
                        // CFG generated for coalesce assignment operation ('??=')
                        // Do not fire an assert for this known anomaly.
                        var operations = rvalueFlowCaptureIds[captureId];
                        if (operations.Count == 1 &&
                            operations.Single().Parent?.Kind == OperationKind.FlowCapture)
                        {
                            continue;
                        }

                        Debug.Fail("Flow capture used as both an r-value and an l-value?");
                    }
                }
            }
#endif

            return(lvalueFlowCaptureIdBuilder.ToImmutableAndFree());
        }
示例#2
0
        private static ImmutableHashSet <CaptureId> CreateLValueFlowCaptures(ControlFlowGraph cfg)
        {
            var lvalueFlowCaptureIdBuilder = PooledHashSet <CaptureId> .GetInstance();

#if DEBUG
            var rvalueFlowCaptureIds = new HashSet <CaptureId>();
#endif
            foreach (var flowCaptureReference in cfg.DescendantOperations <IFlowCaptureReferenceOperation>(OperationKind.FlowCaptureReference))
            {
                if (flowCaptureReference.Parent is IAssignmentOperation assignment &&
                    assignment.Target == flowCaptureReference)
                {
                    lvalueFlowCaptureIdBuilder.Add(flowCaptureReference.Id);
                }
示例#3
0
        public static ImmutableDictionary <CaptureId, FlowCaptureKind> CreateLValueFlowCaptures(ControlFlowGraph cfg)
        {
            // This method identifies flow capture reference operations that are target of an assignment
            // and marks them as lvalue flow captures.
            // Control flow graph can also contain flow captures
            // that are r-value captures at some point and l-values captures at other point in
            // the flow graph. Specifically, for an ICoalesceOperation a flow capture acts
            // as both an r-value and l-value flow capture.

            ImmutableDictionary <CaptureId, FlowCaptureKind> .Builder lvalueFlowCaptureIdBuilder = null;
            var rvalueFlowCaptureIds = new HashSet <CaptureId> ();

            foreach (var flowCaptureReference in cfg.DescendantOperations <IFlowCaptureReferenceOperation> (OperationKind.FlowCaptureReference))
            {
                if (flowCaptureReference.Parent is IAssignmentOperation assignment &&
                    assignment.Target == flowCaptureReference ||
                    flowCaptureReference.IsInLeftOfDeconstructionAssignment(out _))
                {
                    lvalueFlowCaptureIdBuilder ??= ImmutableDictionary.CreateBuilder <CaptureId, FlowCaptureKind> ();
                    var captureKind = flowCaptureReference.Parent.IsAnyCompoundAssignment() || rvalueFlowCaptureIds.Contains(flowCaptureReference.Id)
                                                ? FlowCaptureKind.LValueAndRValueCapture
                                                : FlowCaptureKind.LValueCapture;
                    lvalueFlowCaptureIdBuilder.Add(flowCaptureReference.Id, captureKind);
                }
示例#4
0
 public static IEnumerable <T> DescendantOperations <T> (this ControlFlowGraph cfg, OperationKind operationKind)
     where T : IOperation
 => cfg.DescendantOperations().Where(d => d?.Kind == operationKind).Cast <T> ();