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(); } }
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) { }
internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node) : base(compilation, member, node) { }
private void Fail(BoundNode node) { Debug.Assert(false, $"Bound nodes of kind {node.Kind} should not survive past local rewriting"); }
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)); }
private EntryPointsWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion) : base(compilation, member, node, firstInRegion, lastInRegion) { }
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(); } }
/// <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; } } }
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(); } }
/// <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(); }
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); }
private RegionReachableWalker(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion) : base(compilation, member, node, firstInRegion, lastInRegion) { }
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); }
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(); } }
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>(); }
/// <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); } } }
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)); }
public CancelledByStackGuardException(Exception inner, BoundNode node) : base(inner.Message, inner) { Node = node; }
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; } }
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) { }
internal ControlFlowPass(CSharpCompilation compilation, Symbol member, BoundNode node, BoundNode firstInRegion, BoundNode lastInRegion) : base(compilation, member, node, firstInRegion, lastInRegion) { }
private void Error(ErrorCode code, BoundNode node, params object[] args) { _diagnostics.Add(code, node.Syntax.Location, args); }