Пример #1
0
        internal static void Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion,
                                     out bool startPointIsReachable, out bool endPointIsReachable)
        {
            var  walker      = new RegionReachableWalker(compilation, member, node, firstInRegion, lastInRegion);
            var  diagnostics = DiagnosticBag.GetInstance();
            bool badRegion   = false;

            try
            {
                walker.Analyze(ref badRegion, diagnostics);
                startPointIsReachable = badRegion || walker._regionStartPointIsReachable.GetValueOrDefault(true);
                endPointIsReachable   = badRegion || walker._regionEndPointIsReachable.GetValueOrDefault(walker.State.Alive);
            }
            finally
            {
                diagnostics.Free();
                walker.Free();
            }
        }
        internal static HashSet <PrefixUnaryExpressionSyntax> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node)
        {
            var walker = new UnassignedAddressTakenVariablesWalker(compilation, member, node);

            try
            {
                bool badRegion = false;
                var  result    = walker.Analyze(ref badRegion);
                Debug.Assert(!badRegion);
                return(result);
            }
            finally
            {
                walker.Free();
            }
        }
Пример #3
0
 private DataFlowsInWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion,
                           HashSet <Symbol> unassignedVariables, HashSet <PrefixUnaryExpressionSyntax> unassignedVariableAddressOfSyntaxes)
     : base(compilation, member, node, firstInRegion, lastInRegion, unassignedVariables, unassignedVariableAddressOfSyntaxes)
 {
 }
Пример #4
0
 internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node)
     : base(compilation, member, node)
 {
 }
Пример #5
0
 private void Fail(BoundNode node)
 {
     Debug.Assert(false, $"Bound nodes of kind {node.Kind} should not survive past local rewriting");
 }
Пример #6
0
        public virtual R Visit(BoundNode node, A arg)
        {
            if (node == null)
            {
                return(default(R));
            }

            // this switch contains fewer than 50 of the most common node kinds
            switch (node.Kind)
            {
            case BoundKind.TypeExpression:
                return(VisitTypeExpression(node as BoundTypeExpression, arg));

            case BoundKind.NamespaceExpression:
                return(VisitNamespaceExpression(node as BoundNamespaceExpression, arg));

            case BoundKind.UnaryOperator:
                return(VisitUnaryOperator(node as BoundUnaryOperator, arg));

            case BoundKind.IncrementOperator:
                return(VisitIncrementOperator(node as BoundIncrementOperator, arg));

            case BoundKind.BinaryOperator:
                return(VisitBinaryOperator(node as BoundBinaryOperator, arg));

            case BoundKind.CompoundAssignmentOperator:
                return(VisitCompoundAssignmentOperator(node as BoundCompoundAssignmentOperator, arg));

            case BoundKind.AssignmentOperator:
                return(VisitAssignmentOperator(node as BoundAssignmentOperator, arg));

            case BoundKind.NullCoalescingOperator:
                return(VisitNullCoalescingOperator(node as BoundNullCoalescingOperator, arg));

            case BoundKind.ConditionalOperator:
                return(VisitConditionalOperator(node as BoundConditionalOperator, arg));

            case BoundKind.ArrayAccess:
                return(VisitArrayAccess(node as BoundArrayAccess, arg));

            case BoundKind.TypeOfOperator:
                return(VisitTypeOfOperator(node as BoundTypeOfOperator, arg));

            case BoundKind.DefaultExpression:
                return(VisitDefaultExpression(node as BoundDefaultExpression, arg));

            case BoundKind.IsOperator:
                return(VisitIsOperator(node as BoundIsOperator, arg));

            case BoundKind.AsOperator:
                return(VisitAsOperator(node as BoundAsOperator, arg));

            case BoundKind.Conversion:
                return(VisitConversion(node as BoundConversion, arg));

            case BoundKind.SequencePointExpression:
                return(VisitSequencePointExpression(node as BoundSequencePointExpression, arg));

            case BoundKind.SequencePoint:
                return(VisitSequencePoint(node as BoundSequencePoint, arg));

            case BoundKind.SequencePointWithSpan:
                return(VisitSequencePointWithSpan(node as BoundSequencePointWithSpan, arg));

            case BoundKind.Block:
                return(VisitBlock(node as BoundBlock, arg));

            case BoundKind.LocalDeclaration:
                return(VisitLocalDeclaration(node as BoundLocalDeclaration, arg));

            case BoundKind.Sequence:
                return(VisitSequence(node as BoundSequence, arg));

            case BoundKind.NoOpStatement:
                return(VisitNoOpStatement(node as BoundNoOpStatement, arg));

            case BoundKind.ReturnStatement:
                return(VisitReturnStatement(node as BoundReturnStatement, arg));

            case BoundKind.ThrowStatement:
                return(VisitThrowStatement(node as BoundThrowStatement, arg));

            case BoundKind.ExpressionStatement:
                return(VisitExpressionStatement(node as BoundExpressionStatement, arg));

            case BoundKind.BreakStatement:
                return(VisitBreakStatement(node as BoundBreakStatement, arg));

            case BoundKind.ContinueStatement:
                return(VisitContinueStatement(node as BoundContinueStatement, arg));

            case BoundKind.IfStatement:
                return(VisitIfStatement(node as BoundIfStatement, arg));

            case BoundKind.ForEachStatement:
                return(VisitForEachStatement(node as BoundForEachStatement, arg));

            case BoundKind.TryStatement:
                return(VisitTryStatement(node as BoundTryStatement, arg));

            case BoundKind.Literal:
                return(VisitLiteral(node as BoundLiteral, arg));

            case BoundKind.ThisReference:
                return(VisitThisReference(node as BoundThisReference, arg));

            case BoundKind.Local:
                return(VisitLocal(node as BoundLocal, arg));

            case BoundKind.Parameter:
                return(VisitParameter(node as BoundParameter, arg));

            case BoundKind.LabelStatement:
                return(VisitLabelStatement(node as BoundLabelStatement, arg));

            case BoundKind.GotoStatement:
                return(VisitGotoStatement(node as BoundGotoStatement, arg));

            case BoundKind.LabeledStatement:
                return(VisitLabeledStatement(node as BoundLabeledStatement, arg));

            case BoundKind.StatementList:
                return(VisitStatementList(node as BoundStatementList, arg));

            case BoundKind.ConditionalGoto:
                return(VisitConditionalGoto(node as BoundConditionalGoto, arg));

            case BoundKind.Call:
                return(VisitCall(node as BoundCall, arg));

            case BoundKind.ObjectCreationExpression:
                return(VisitObjectCreationExpression(node as BoundObjectCreationExpression, arg));

            case BoundKind.DelegateCreationExpression:
                return(VisitDelegateCreationExpression(node as BoundDelegateCreationExpression, arg));

            case BoundKind.FieldAccess:
                return(VisitFieldAccess(node as BoundFieldAccess, arg));

            case BoundKind.PropertyAccess:
                return(VisitPropertyAccess(node as BoundPropertyAccess, arg));

            case BoundKind.Lambda:
                return(VisitLambda(node as BoundLambda, arg));

            case BoundKind.NameOfOperator:
                return(VisitNameOfOperator(node as BoundNameOfOperator, arg));

            case BoundKind.ConstTypeParameterExpression:
                return(VisitConstTypeParameterExpression(node as BoundConstTypeParameterExpression, arg));
            }

            return(VisitInternal(node, arg));
        }
Пример #7
0
 private EntryPointsWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
Пример #8
0
        internal static HashSet <Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, HashSet <Symbol> unassignedVariables, ImmutableArray <ISymbol> dataFlowsIn)
        {
            var walker = new DataFlowsOutWalker(compilation, member, node, firstInRegion, lastInRegion, unassignedVariables, dataFlowsIn);

            try
            {
                bool badRegion = false;
                var  result    = walker.Analyze(ref badRegion);
#if DEBUG
                // Assert that DataFlowsOut only contains variables that were assigned to inside the region
                Debug.Assert(badRegion || !result.Any((variable) => !walker._assignedInside.Contains(variable)));
#endif
                return(badRegion ? new HashSet <Symbol>() : result);
            }
            finally
            {
                walker.Free();
            }
        }
Пример #9
0
        /// <summary>
        /// Construct context
        /// </summary>
        public RegionAnalysisContext(CSharpCompilation compilation, Symbol member, BoundNode boundNode, BoundNode firstInRegion, BoundNode lastInRegion)
        {
            this.Compilation   = compilation;
            this.Member        = member;
            this.BoundNode     = boundNode;
            this.FirstInRegion = firstInRegion;
            this.LastInRegion  = lastInRegion;
            this.Failed        =
                boundNode == null ||
                firstInRegion == null ||
                lastInRegion == null ||
                firstInRegion.Syntax.SpanStart > lastInRegion.Syntax.Span.End;

            if (!this.Failed && ReferenceEquals(firstInRegion, lastInRegion))
            {
                switch (firstInRegion.Kind)
                {
                case BoundKind.NamespaceExpression:
                case BoundKind.TypeExpression:

                    // Some bound nodes are still considered to be invalid for flow analysis
                    this.Failed = true;
                    break;
                }
            }
        }
Пример #10
0
        internal static IEnumerable <LabeledStatementSyntax> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, out bool?succeeded)
        {
            var  walker    = new EntryPointsWalker(compilation, member, node, firstInRegion, lastInRegion);
            bool badRegion = false;

            try
            {
                walker.Analyze(ref badRegion);
                var result = walker._entryPoints;
                succeeded = !badRegion;
                return(badRegion ? SpecializedCollections.EmptyEnumerable <LabeledStatementSyntax>() : result);
            }
            finally
            {
                walker.Free();
            }
        }
Пример #11
0
            /// <summary>
            /// Walks the bound tree and adds all non compiler generated bound nodes whose syntax matches the given one
            /// to the cache.
            /// </summary>
            /// <param name="root">The root of the bound tree.</param>
            /// <param name="map">The cache.</param>
            /// <param name="node">The syntax node where to add bound nodes for.</param>
            public static void AddToMap(BoundNode root, Dictionary <SyntaxNode, ImmutableArray <BoundNode> > map, SyntaxNode node = null)
            {
                Debug.Assert(node == null || root == null || !(root.Syntax is StatementSyntax), "individually added nodes are not supposed to be statements.");

                if (root == null || map.ContainsKey(root.Syntax))
                {
                    // root node is already in the map, children must be in the map too.
                    return;
                }

                var additionMap = OrderPreservingMultiDictionary <SyntaxNode, BoundNode> .GetInstance();

                var builder = new NodeMapBuilder(additionMap, node);

                builder.Visit(root);

                foreach (CSharpSyntaxNode key in additionMap.Keys)
                {
                    if (map.ContainsKey(key))
                    {
#if DEBUG
                        // It's possible that AddToMap was previously called with a subtree of root.  If this is the case,
                        // then we'll see an entry in the map.  Since the incremental binder should also have seen the
                        // pre-existing map entry, the entry in addition map should be identical.
                        // Another, more unfortunate, possibility is that we've had to re-bind the syntax and the new bound
                        // nodes are equivalent, but not identical, to the existing ones.  In such cases, we prefer the
                        // existing nodes so that the cache will always return the same bound node for a given syntax node.

                        // EXAMPLE: Suppose we have the statement P.M(1);
                        // First, we ask for semantic info about "P".  We'll walk up to the statement level and bind that.
                        // We'll end up with map entries for "1", "P", "P.M(1)", and "P.M(1);".
                        // Next, we ask for semantic info about "P.M".  That isn't in our map, so we walk up to the statement
                        // level - again - and bind that - again.
                        // Once again, we'll end up with map entries for "1", "P", "P.M(1)", and "P.M(1);".  They will
                        // have the same structure as the original map entries, but will not be ReferenceEquals.

                        var existing = map[key];
                        var added    = additionMap[key];
                        Debug.Assert(existing.Length == added.Length, "existing.Length == added.Length");
                        for (int i = 0; i < existing.Length; i++)
                        {
                            // TODO: it would be great if we could check !ReferenceEquals(existing[i], added[i]) (DevDiv #11584).
                            // Known impediments include:
                            //   1) Field initializers aren't cached because they're not in statements.
                            //   2) Single local declarations (e.g. "int x = 1;" vs "int x = 1, y = 2;") aren't found in the cache
                            //      since nothing is cached for the statement syntax.
                            if (existing[i].Kind != added[i].Kind)
                            {
                                Debug.Assert(!(key is StatementSyntax), "!(key is StatementSyntax)");

                                // This also seems to be happening when we get equivalent BoundTypeExpression and BoundTypeOrValueExpression nodes.
                                if (existing[i].Kind == BoundKind.TypeExpression && added[i].Kind == BoundKind.TypeOrValueExpression)
                                {
                                    Debug.Assert(
                                        TypeSymbol.Equals(((BoundTypeExpression)existing[i]).Type, ((BoundTypeOrValueExpression)added[i]).Type, TypeCompareKind.ConsiderEverything2),
                                        string.Format(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "((BoundTypeExpression)existing[{0}]).Type == ((BoundTypeOrValueExpression)added[{0}]).Type", i));
                                }
                                else if (existing[i].Kind == BoundKind.TypeOrValueExpression && added[i].Kind == BoundKind.TypeExpression)
                                {
                                    Debug.Assert(
                                        TypeSymbol.Equals(((BoundTypeOrValueExpression)existing[i]).Type, ((BoundTypeExpression)added[i]).Type, TypeCompareKind.ConsiderEverything2),
                                        string.Format(
                                            System.Globalization.CultureInfo.InvariantCulture,
                                            "((BoundTypeOrValueExpression)existing[{0}]).Type == ((BoundTypeExpression)added[{0}]).Type", i));
                                }
                                else
                                {
                                    Debug.Assert(false, "New bound node does not match existing bound node");
                                }
                            }
                            else
                            {
                                Debug.Assert(
                                    (object)existing[i] == added[i] || !(key is StatementSyntax),
                                    string.Format(
                                        System.Globalization.CultureInfo.InvariantCulture,
                                        "(object)existing[{0}] == added[{0}] || !(key is StatementSyntax)", i));
                            }
                        }
#endif
                    }
                    else
                    {
                        map[key] = additionMap[key];
                    }
                }

                additionMap.Free();
            }
Пример #12
0
            public override BoundNode Visit(BoundNode node)
            {
                if (node == null)
                {
                    return(null);
                }

                BoundNode current = node;

                // It is possible that we will encounter a lambda in the bound tree that was never
                // turned into a bound lambda. For example, if you have something like:
                //
                // object x = (int y)=>M(y);
                //
                // then no conversion to a valid delegate type was performed and the "bound" tree
                // contains an "unbound" lambda with no body. Or, similarly, we could have something
                // like:
                //
                // M(x=>x.Blah());
                //
                // and overload resolution failed to infer a unique type for x; perhaps it
                // inferred two types and neither return type was better. Or perhaps
                // there was a semantic error inside the lambda.
                //
                // In any of these cases there will be no bound lambda in the bound tree.
                //
                // Ultimately what we probably want to do here is ensure that this never happens;
                // we could run a post-processing pass on the bound tree, look for unbound lambdas,
                // and replace them with bound lambdas. However at this time that is a fairly complex
                // change and it is not clear where the most efficient place to put the rewriter is
                // in the IDE scenario. Until we figure that out, I'm going to detect that situation
                // here, when building the map. If we encounter an unbound lambda in the tree,
                // we'll just bind it right now. The unbound lambda will cache the result, and we'll
                // keep on trucking just as though there had been a bound lambda here all along.
                if (node.Kind == BoundKind.UnboundLambda)
                {
                    current = ((UnboundLambda)node).BindForErrorRecovery();
                }

                // It is possible for there to be multiple bound nodes with the same syntax tree,
                // and that is by design. For example, in
                //
                // byte b = 3;
                //
                // there is a bound node for the implicit conversion to byte and a bound node for the
                // literal, an int. Sometimes we want the inner one (to state the type of the expression)
                // and sometimes we want the "parent's" view of things (for extract method, for instance.)
                //
                // We want to add all bound nodes associated with the same syntax node to the cache, so we first add the
                // bound node, then we dive deeper into the bound tree.
                if (ShouldAddNode(current))
                {
                    _map.Add(current.Syntax, current);
                }

                // In machine-generated code we frequently end up with binary operator trees that are deep on the left,
                // such as a + b + c + d ...
                // To avoid blowing the call stack, we build an explicit stack to handle the left-hand recursion.
                var binOp = current as BoundBinaryOperator;

                if (binOp != null)
                {
                    var stack = ArrayBuilder <BoundExpression> .GetInstance();

                    stack.Push(binOp.Right);
                    current = binOp.Left;
                    binOp   = current as BoundBinaryOperator;

                    while (binOp != null)
                    {
                        if (ShouldAddNode(binOp))
                        {
                            _map.Add(binOp.Syntax, binOp);
                        }

                        stack.Push(binOp.Right);
                        current = binOp.Left;
                        binOp   = current as BoundBinaryOperator;
                    }

                    Visit(current);

                    while (stack.Count > 0)
                    {
                        Visit(stack.Pop());
                    }

                    stack.Free();
                }
                else
                {
                    base.Visit(current);
                }

                return(null);
            }
Пример #13
0
 private RegionReachableWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
Пример #14
0
        private Symbol GetNodeSymbol(BoundNode node)
        {
            while (node != null)
            {
                switch (node.Kind)
                {
                case BoundKind.DeclarationPattern:
                {
                    return(((BoundDeclarationPattern)node).Variable as LocalSymbol);
                }

                case BoundKind.RecursivePattern:
                {
                    return(((BoundRecursivePattern)node).Variable as LocalSymbol);
                }

                case BoundKind.FieldAccess:
                {
                    var fieldAccess = (BoundFieldAccess)node;
                    if (MayRequireTracking(fieldAccess.ReceiverOpt, fieldAccess.FieldSymbol))
                    {
                        node = fieldAccess.ReceiverOpt;
                        continue;
                    }

                    return(null);
                }

                case BoundKind.LocalDeclaration:
                {
                    return(((BoundLocalDeclaration)node).LocalSymbol);
                }

                case BoundKind.ThisReference:
                {
                    return(MethodThisParameter);
                }

                case BoundKind.Local:
                {
                    return(((BoundLocal)node).LocalSymbol);
                }

                case BoundKind.Parameter:
                {
                    return(((BoundParameter)node).ParameterSymbol);
                }

                case BoundKind.CatchBlock:
                {
                    var local = ((BoundCatchBlock)node).Locals.FirstOrDefault();
                    return(local?.DeclarationKind == LocalDeclarationKind.CatchVariable ? local : null);
                }

                case BoundKind.RangeVariable:
                {
                    return(((BoundRangeVariable)node).RangeVariableSymbol);
                }

                case BoundKind.EventAccess:
                {
                    var         eventAccess     = (BoundEventAccess)node;
                    FieldSymbol associatedField = eventAccess.EventSymbol.AssociatedField;
                    if ((object)associatedField != null)
                    {
                        if (MayRequireTracking(eventAccess.ReceiverOpt, associatedField))
                        {
                            node = eventAccess.ReceiverOpt;
                            continue;
                        }
                    }
                    return(null);
                }

                case BoundKind.LocalFunctionStatement:
                {
                    return(((BoundLocalFunctionStatement)node).Symbol);
                }

                default:
                {
                    return(null);
                }
                }
            }

            return(null);
        }
Пример #15
0
        internal static void Analyze(
            CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, HashSet <PrefixUnaryExpressionSyntax> unassignedVariableAddressOfSyntaxes,
            out IEnumerable <Symbol> readInside,
            out IEnumerable <Symbol> writtenInside,
            out IEnumerable <Symbol> readOutside,
            out IEnumerable <Symbol> writtenOutside,
            out IEnumerable <Symbol> captured,
            out IEnumerable <Symbol> unsafeAddressTaken,
            out IEnumerable <Symbol> capturedInside,
            out IEnumerable <Symbol> capturedOutside)
        {
            var walker = new ReadWriteWalker(compilation, member, node, firstInRegion, lastInRegion, unassignedVariableAddressOfSyntaxes);

            try
            {
                bool badRegion = false;
                walker.Analyze(ref badRegion);
                if (badRegion)
                {
                    readInside = writtenInside = readOutside = writtenOutside = captured = unsafeAddressTaken = capturedInside = capturedOutside = Enumerable.Empty <Symbol>();
                }
                else
                {
                    readInside     = walker._readInside;
                    writtenInside  = walker._writtenInside;
                    readOutside    = walker._readOutside;
                    writtenOutside = walker._writtenOutside;

                    captured        = walker.GetCaptured();
                    capturedInside  = walker.GetCapturedInside();
                    capturedOutside = walker.GetCapturedOutside();

                    unsafeAddressTaken = walker.GetUnsafeAddressTaken();
                }
            }
            finally
            {
                walker.Free();
            }
        }
Пример #16
0
 private DataFlowsOutWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion, HashSet <Symbol> unassignedVariables, ImmutableArray <ISymbol> dataFlowsIn)
     : base(compilation, member, node, firstInRegion, lastInRegion, unassignedVariables, trackUnassignments: true)
 {
     _dataFlowsIn = dataFlowsIn;
 }
 private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, NeverEmptyStructTypeCache emptyStructCache, HashSet <Symbol> initiallyAssignedVariables)
     : base(compilation,
            method,
            node,
            emptyStructCache,
            trackUnassignments: true,
            initiallyAssignedVariables: initiallyAssignedVariables)
 {
     _variablesToHoist = new OrderedSet <Symbol>();
 }
Пример #18
0
            /// <summary>
            /// Find the parent <see cref="Scope"/> of the <see cref="Scope"/> corresponding to
            /// the given <see cref="BoundNode"/>.
            /// </summary>
            public static Scope GetScopeParent(Scope treeRoot, BoundNode scopeNode)
            {
                var correspondingScope = GetScopeWithMatchingBoundNode(treeRoot, scopeNode);

                return(correspondingScope.Parent);
            }
        // Returns deterministically ordered list of variables that ought to be hoisted.
        public static OrderedSet <Symbol> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node, DiagnosticBag diagnostics)
        {
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, convertInsufficientExecutionStackExceptionToCancelledByStackGuardException: true);
            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, new NeverEmptyStructTypeCache(), initiallyAssignedVariables);

            walker._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true;

            bool badRegion = false;

            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                walker.CaptureVariable(method.ThisParameter, node.Syntax);
            }

            var variablesToHoist       = walker._variablesToHoist;
            var lazyDisallowedCaptures = walker._lazyDisallowedCaptures;
            var allVariables           = walker.variableBySlot;

            walker.Free();

            if (lazyDisallowedCaptures != null)
            {
                foreach (var kvp in lazyDisallowedCaptures)
                {
                    var variable = kvp.Key;
                    var type     = (variable.Kind == SymbolKind.Local) ? ((LocalSymbol)variable).Type.TypeSymbol : ((ParameterSymbol)variable).Type.TypeSymbol;

                    if (variable is SynthesizedLocal local && local.SynthesizedKind == SynthesizedLocalKind.Spill)
                    {
                        Debug.Assert(local.Type.IsRestrictedType());
                        diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, local.Locations[0], local.Type);
                    }
                    else
                    {
                        foreach (CSharpSyntaxNode syntax in kvp.Value)
                        {
                            // CS4013: Instance of type '{0}' cannot be used inside an anonymous function, query expression, iterator block or async method
                            diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, type);
                        }
                    }
                }
Пример #20
0
 public virtual R DefaultVisit(BoundNode node, A arg)
 {
     return(default(R));
 }
 public override BoundNode Visit(BoundNode node)
 {
     // Stop visiting once we determine something might get assigned
     return(this._mightAssignSomething ? null : base.Visit(node));
 }
Пример #22
0
 public CancelledByStackGuardException(Exception inner, BoundNode node)
     : base(inner.Message, inner)
 {
     Node = node;
 }
Пример #23
0
        public static void GetExpressionSymbols(this BoundExpression node, ArrayBuilder <Symbol> symbols, BoundNode parent, Binder binder)
        {
            switch (node.Kind)
            {
            case BoundKind.MethodGroup:
                // Special case: if we are looking for info on "M" in "new Action(M)" in the context of a parent
                // then we want to get the symbol that overload resolution chose for M, not on the whole method group M.
                var delegateCreation = parent as BoundDelegateCreationExpression;
                if (delegateCreation != null && (object)delegateCreation.MethodOpt != null)
                {
                    symbols.Add(delegateCreation.MethodOpt);
                }
                else
                {
                    symbols.AddRange(CSharpSemanticModel.GetReducedAndFilteredMethodGroupSymbols(binder, (BoundMethodGroup)node));
                }
                break;

            case BoundKind.BadExpression:
                symbols.AddRange(((BoundBadExpression)node).Symbols);
                break;

            case BoundKind.DelegateCreationExpression:
                var expr = (BoundDelegateCreationExpression)node;
                var ctor = expr.Type.GetMembers(WellKnownMemberNames.InstanceConstructorName).FirstOrDefault();
                if ((object)ctor != null)
                {
                    symbols.Add(ctor);
                }
                break;

            case BoundKind.Call:
                // Either overload resolution succeeded for this call or it did not. If it did not
                // succeed then we've stashed the original method symbols from the method group,
                // and we should use those as the symbols displayed for the call. If it did succeed
                // then we did not stash any symbols; just fall through to the default case.

                var originalMethods = ((BoundCall)node).OriginalMethodsOpt;
                if (originalMethods.IsDefault)
                {
                    goto default;
                }
                symbols.AddRange(originalMethods);
                break;

            case BoundKind.IndexerAccess:
                // Same behavior as for a BoundCall: if overload resolution failed, pull out stashed candidates;
                // otherwise use the default behavior.

                var originalIndexers = ((BoundIndexerAccess)node).OriginalIndexersOpt;
                if (originalIndexers.IsDefault)
                {
                    goto default;
                }
                symbols.AddRange(originalIndexers);
                break;

            default:
                var symbol = node.ExpressionSymbol;
                if ((object)symbol != null)
                {
                    symbols.Add(symbol);
                }
                break;
            }
        }
Пример #24
0
        internal static HashSet <Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion,
                                                 HashSet <Symbol> unassignedVariables, HashSet <PrefixUnaryExpressionSyntax> unassignedVariableAddressOfSyntaxes, out bool?succeeded)
        {
            var walker = new DataFlowsInWalker(compilation, member, node, firstInRegion, lastInRegion, unassignedVariables, unassignedVariableAddressOfSyntaxes);

            try
            {
                bool badRegion = false;
                var  result    = walker.Analyze(ref badRegion);
                succeeded = !badRegion;
                return(badRegion ? new HashSet <Symbol>() : result);
            }
            finally
            {
                walker.Free();
            }
        }
 private UnassignedAddressTakenVariablesWalker(CSharpCompilation compilation, Symbol member, BoundNode node)
     : base(compilation, member, node)
 {
 }
Пример #26
0
 internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion)
     : base(compilation, member, node, firstInRegion, lastInRegion)
 {
 }
Пример #27
0
 private void Error(ErrorCode code, BoundNode node, params object[] args)
 {
     _diagnostics.Add(code, node.Syntax.Location, args);
 }