예제 #1
0
        internal static HashSet <Symbol> Analyze(
            CSharpCompilation compilation,
            Symbol member,
            BoundNode node,
            bool convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = false
            )
        {
            var walker = new UnassignedVariablesWalker(compilation, member, node);

            if (convertInsufficientExecutionStackExceptionToCancelledByStackGuardException)
            {
                walker._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException =
                    true;
            }

            try
            {
                bool badRegion = false;
                var  result    = walker.Analyze(ref badRegion);
                return(badRegion ? new HashSet <Symbol>() : result);
            }
            finally
            {
                walker.Free();
            }
        }
        public static MultiDictionary <Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node)
        {
            var emptyStructs = new CaptureWalkerEmptyStructTypeCache();
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructs);

            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, emptyStructs, initiallyAssignedVariables);

            bool badRegion = false;

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

            var result = walker.variablesCaptured;


            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.
                result.Add(method.ThisParameter, node.Syntax);
            }

            foreach (var variable in result.Keys.ToArray()) // take a snapshot, as we are modifying the underlying multidictionary
            {
                var local = variable as LocalSymbol;
                if ((object)local != null && local.RefKind != RefKind.None)
                {
                    walker.AddSpillsForRef(walker.refLocalInitializers[local], result[local]);
                }
            }

            walker.Free();
            return(result);
        }
예제 #3
0
        // 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 : ((ParameterSymbol)variable).Type;

                    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);
                    }
                }
            }

            if (compilation.Options.OptimizationLevel != OptimizationLevel.Release)
            {
                Debug.Assert(variablesToHoist.Count == 0);

                // In debug build we hoist all locals and parameters:
                foreach (var v in allVariables)
                {
                    var symbol = v.Symbol;
                    if ((object)symbol != null && HoistInDebugBuild(symbol))
                    {
                        variablesToHoist.Add(symbol);
                    }
                }
            }

            return(variablesToHoist);
        }
 internal static HashSet<Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, EmptyStructTypeCache emptyStructCache = null)
 {
     var walker = new UnassignedVariablesWalker(compilation, member, node, emptyStructCache);
     try
     {
         bool badRegion = false;
         var result = walker.Analyze(ref badRegion);
         return badRegion ? new HashSet<Symbol>() : result;
     }
     finally
     {
         walker.Free();
     }
 }
예제 #5
0
        internal static HashSet <Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node, EmptyStructTypeCache emptyStructCache = null)
        {
            var walker = new UnassignedVariablesWalker(compilation, member, node, emptyStructCache);

            try
            {
                bool badRegion = false;
                var  result    = walker.Analyze(ref badRegion);
                return(badRegion ? new HashSet <Symbol>() : result);
            }
            finally
            {
                walker.Free();
            }
        }
        // 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, 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 : ((ParameterSymbol)variable).Type;

                    if (variable is SynthesizedLocal local && local.SynthesizedKind == SynthesizedLocalKind.Spill)
                    {
                        Debug.Assert(local.TypeWithAnnotations.IsRestrictedType());
                        diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, local.Locations[0], local.TypeWithAnnotations);
                    }
                    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);
                        }
                    }
                }
        internal static HashSet<Symbol> Analyze(CSharpCompilation compilation, Symbol member, BoundNode node,
                                                bool convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = false)
        {
            var walker = new UnassignedVariablesWalker(compilation, member, node);

            if (convertInsufficientExecutionStackExceptionToCancelledByStackGuardException)
            {
                walker._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true;
            }

            try
            {
                bool badRegion = false;
                var result = walker.Analyze(ref badRegion);
                return badRegion ? new HashSet<Symbol>() : result;
            }
            finally
            {
                walker.Free();
            }
        }
        public static MultiDictionary <Symbol, CSharpSyntaxNode> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node)
        {
            var  initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node);
            var  walker    = new IteratorAndAsyncCaptureWalker(compilation, method, node, new NeverEmptyStructTypeCache(), initiallyAssignedVariables);
            bool badRegion = false;

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

            var result = walker.variablesCaptured;

            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.
                result.Add(method.ThisParameter, node.Syntax);
            }

            walker.Free();
            return(result);
        }
 private IteratorAndAsyncCaptureWalker(CSharpCompilation compilation, MethodSymbol method, BoundNode node, CaptureWalkerEmptyStructTypeCache emptyStructCache)
     : base(compilation, method, node, emptyStructCache, trackUnassignments: true, initiallyAssignedVariables: UnassignedVariablesWalker.Analyze(compilation, method, node, emptyStructCache))
 {
 }