| File: FlowAnalysis\UnassignedAddressTakenVariablesWalker.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. #nullable disable using System.Collections.Generic; using System.Diagnostics; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.CodeAnalysis.CSharp { /// <summary> /// An analysis that computes all cases where the address is taken of a variable that has not yet been assigned /// </summary> internal class UnassignedAddressTakenVariablesWalker : DefiniteAssignmentPass { private UnassignedAddressTakenVariablesWalker(CSharpCompilation compilation, Symbol member, BoundNode node) : base(compilation, member, node, strictAnalysis: true) { } 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 readonly HashSet<PrefixUnaryExpressionSyntax> _result = new HashSet<PrefixUnaryExpressionSyntax>(); private HashSet<PrefixUnaryExpressionSyntax> Analyze(ref bool badRegion) { // It might seem necessary to clear this.result after each Scan performed by base.Analyze, however, // finding new execution paths (via new backwards branches) can only make variables "less" definitely // assigned, not more. That is, if there was formerly a path on which the variable was not definitely // assigned, then adding another path will not make the variable definitely assigned. Therefore, // subsequent scans can only re-add elements to this.result, and the HashSet will naturally de-dup. base.Analyze(ref badRegion, null); return _result; } protected override void ReportUnassigned(Symbol symbol, SyntaxNode node, int slot, bool skipIfUseBeforeDeclaration) { if (node.Parent.Kind() == SyntaxKind.AddressOfExpression) { _result.Add((PrefixUnaryExpressionSyntax)node.Parent); } } public override BoundNode VisitAddressOfOperator(BoundAddressOfOperator node) { // Pretend address-of is a pure read (i.e. no write) - would we see an // unassigned diagnostic? VisitRvalue(node.Operand); return null; } } }