Example #1
0
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            // Strip off ExecutableCodeBinder (see ctor).
            Binder binder = this.RootBinder;

            do
            {
                if (binder is ExecutableCodeBinder)
                {
                    binder = binder.Next;
                    break;
                }

                binder = binder.Next;
            }while (binder != null);

            Debug.Assert(binder != null);

            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder);
            var blockBinder      = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags());

            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position);
            return(true);
        }
        public static void IssueDiagnostics(
            CSharpCompilation compilation,
            BoundNode node,
            BindingDiagnosticBag diagnostics,
            MethodSymbol containingSymbol
            )
        {
            Debug.Assert(node != null);
            Debug.Assert((object)containingSymbol != null);

            ExecutableCodeBinder.ValidateIteratorMethod(compilation, containingSymbol, diagnostics);

            try
            {
                var diagnosticPass = new DiagnosticsPass(
                    compilation,
                    diagnostics,
                    containingSymbol
                    );
                diagnosticPass.Visit(node);
            }
            catch (CancelledByStackGuardException ex)
            {
                ex.AddAnError(diagnostics);
            }
        }
Example #3
0
        internal override bool TryGetSpeculativeSemanticModelCore(
            SyntaxTreeSemanticModel parentModel,
            int position,
            EqualsValueClauseSyntax initializer,
            out SemanticModel speculativeModel
            )
        {
            var binder = this.GetEnclosingBinder(position);

            if (binder == null)
            {
                speculativeModel = null;
                return(false);
            }

            binder           = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder);
            speculativeModel = CreateSpeculative(
                parentModel,
                this.MemberSymbol,
                initializer,
                binder,
                GetRemappedSymbols(),
                position
                );
            return(true);
        }
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            // Strip off ExecutableCodeBinder (see ctor).
            Binder binder = this.RootBinder;

            do
            {
                if (binder is ExecutableCodeBinder)
                {
                    binder = binder.Next;
                    break;
                }

                binder = binder.Next;
            }while (binder != null);

            Debug.Assert(binder != null);

            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder);
            var blockBinder      = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags());

            // We don't pass the snapshot manager along here, because we're speculating about an entirely new body and it should not
            // be influenced by any existing code in the body.
            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, snapshotManagerOpt: null, position);
            return(true);
        }
Example #5
0
        private static BoundFieldEqualsValue BindFieldInitializer(Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax equalsValueClauseNode,
                                                                  DiagnosticBag diagnostics)
        {
            Debug.Assert(!fieldSymbol.IsMetadataConstant);

            var fieldsBeingBound = binder.FieldsBeingBound;

            var  sourceField            = fieldSymbol as SourceMemberFieldSymbolFromDeclarator;
            bool isImplicitlyTypedField = (object)sourceField != null && sourceField.FieldTypeInferred(fieldsBeingBound);

            // If the type is implicitly typed, the initializer diagnostics have already been reported, so ignore them here:
            // CONSIDER (tomat): reusing the bound field initializers for implicitly typed fields.
            DiagnosticBag initializerDiagnostics;

            if (isImplicitlyTypedField)
            {
                initializerDiagnostics = DiagnosticBag.GetInstance();
            }
            else
            {
                initializerDiagnostics = diagnostics;
            }

            binder = new ExecutableCodeBinder(equalsValueClauseNode, fieldSymbol, new LocalScopeBinder(binder));
            BoundFieldEqualsValue boundInitValue = binder.BindFieldInitializer(fieldSymbol, equalsValueClauseNode, initializerDiagnostics);

            if (isImplicitlyTypedField)
            {
                initializerDiagnostics.Free();
            }

            return(boundInitValue);
        }
        /// <summary>
        /// Creates a SemanticModel for an ArrowExpressionClause, which includes
        /// an ExecutableCodeBinder and a ScopedExpressionBinder.
        /// </summary>
        internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, ArrowExpressionClauseSyntax syntax)
        {
            Binder binder = new ExecutableCodeBinder(syntax, owner, rootBinder);

            binder = new ScopedExpressionBinder(binder, syntax.Expression);
            return(new MethodBodySemanticModel(compilation, owner, binder, syntax));
        }
        internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var binder = this.GetEnclosingBinder(position);

            if (binder == null)
            {
                speculativeModel = null;
                return(false);
            }

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            binder = new ExecutableCodeBinder(statement, methodSymbol, binder);

            // local declaration statements need to be wrapped in a block so the local gets seen
            if (!statement.IsKind(SyntaxKind.Block))
            {
                binder = new BlockBinder(binder, new SyntaxList <StatementSyntax>(statement));
            }

            speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, binder, position);
            return(true);
        }
Example #8
0
        private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType, ImmutableArray <TypeSymbol> parameterTypes, ImmutableArray <RefKind> parameterRefKinds)
        {
            var diagnostics  = DiagnosticBag.GetInstance();
            var lambdaSymbol = new LambdaSymbol(
                binder.Compilation,
                binder.ContainingMemberOrLambda,
                _unboundLambda,
                parameterTypes,
                parameterRefKinds,
                refKind: CodeAnalysis.RefKind.None,
                returnType: null,
                diagnostics: diagnostics);
            Binder lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            var    block            = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: true)
            {
                WasCompilerGenerated = _unboundLambda.WasCompilerGenerated
            };

            HashSet <DiagnosticInfo> useSiteDiagnostics = null; // TODO: figure out if this should be somehow merged into BoundLambda.Diagnostics.
            TypeSymbol returnType = result.InferredReturnType(ref useSiteDiagnostics) ?? LambdaSymbol.InferenceFailureReturnType;

            lambdaSymbol.SetInferredReturnType(result.RefKind, returnType);

            return(result);
        }
        private bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CSharpSyntaxNode initializer, out SemanticModel speculativeModel)
        {
            Debug.Assert(initializer is EqualsValueClauseSyntax || initializer is ConstructorInitializerSyntax);

            var binder = this.GetEnclosingBinder(position);

            if (binder == null)
            {
                speculativeModel = null;
                return(false);
            }

            switch (initializer.Kind())
            {
            case SyntaxKind.EqualsValueClause:
                binder = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder);
                break;

            case SyntaxKind.ThisConstructorInitializer:
            case SyntaxKind.BaseConstructorInitializer:
                ArgumentListSyntax argList = ((ConstructorInitializerSyntax)initializer).ArgumentList;
                if (argList != null)
                {
                    binder = new ExecutableCodeBinder(argList, binder.ContainingMemberOrLambda, binder);
                }
                break;
            }

            speculativeModel = CreateSpeculative(parentModel, this.MemberSymbol, initializer, binder, position);
            return(true);
        }
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol = (MethodSymbol)this.MemberSymbol;
            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, this.rootBinder.Next); // Strip off ExecutableCodeBinder (see ctor).
            var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(BinderFlags.SemanticModel);
            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position);
            return true;
        }
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol     = (MethodSymbol)this.MemberSymbol;
            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, this.rootBinder.Next); // Strip off ExecutableCodeBinder (see ctor).
            var blockBinder      = executablebinder.GetBinder(body).WithAdditionalFlags(BinderFlags.SemanticModel);

            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position);
            return(true);
        }
Example #12
0
 protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics)
 {
     if (this.IsExpressionLambda)
     {
         return(lambdaBodyBinder.BindExpressionLambdaBody((ExpressionSyntax)this.Body, diagnostics));
     }
     else
     {
         return(lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics));
     }
 }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            ExecutableCodeBinder.ValidateIteratorMethod(_compilation, node.Symbol, _diagnostics);

            var outerLocalFunction = _staticLocalFunction;

            if (node.Symbol.IsStatic)
            {
                _staticLocalFunction = node.Symbol;
            }
            var result = base.VisitLocalFunctionStatement(node);

            _staticLocalFunction = outerLocalFunction;
            return(result);
        }
Example #14
0
        internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ConstructorInitializerSyntax constructorInitializer, out SemanticModel speculativeModel)
        {
            if ((MemberSymbol as MethodSymbol)?.MethodKind == MethodKind.Constructor)
            {
                var binder = this.GetEnclosingBinder(position);
                if (binder != null)
                {
                    var methodSymbol = (MethodSymbol)this.MemberSymbol;
                    binder           = new ExecutableCodeBinder(constructorInitializer, methodSymbol, binder);
                    speculativeModel = CreateSpeculative(parentModel, methodSymbol, constructorInitializer, binder, position);
                    return(true);
                }
            }

            speculativeModel = null;
            return(false);
        }
Example #15
0
        internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var binder = this.GetEnclosingBinder(position);

            if (binder == null)
            {
                speculativeModel = null;
                return(false);
            }

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            binder           = new ExecutableCodeBinder(statement, methodSymbol, binder);
            speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, binder, position);
            return(true);
        }
Example #16
0
        private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType)
        {
            var    diagnostics      = DiagnosticBag.GetInstance();
            var    parameters       = DelegateParameters(delegateType);
            var    lambdaSymbol     = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, this.unboundLambda, parameters, returnType: null);
            Binder lambdaBodyBinder = new ExecutableCodeBinder(this.unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            var    block            = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics);

            var result = new BoundLambda(this.unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType)
            {
                WasCompilerGenerated = this.unboundLambda.WasCompilerGenerated
            };

            HashSet <DiagnosticInfo> useSiteDiagnostics = null; // TODO: figure out if this should be somehow merged into BoundLambda.Diagnostics.

            lambdaSymbol.SetInferredReturnType(result.InferredReturnType(ref useSiteDiagnostics) ??
                                               new ExtendedErrorTypeSymbol(binder.Compilation, string.Empty, 0, null));

            return(result);
        }
        internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, StatementSyntax statement, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var binder = this.GetEnclosingBinder(position);
            if (binder == null)
            {
                speculativeModel = null;
                return false;
            }

            var methodSymbol = (MethodSymbol)this.MemberSymbol;
            binder = new ExecutableCodeBinder(statement, methodSymbol, binder);

            // local declaration statements need to be wrapped in a block so the local gets seen 
            if (!statement.IsKind(SyntaxKind.Block))
            {
                binder = new BlockBinder(methodSymbol, binder, new SyntaxList<StatementSyntax>(statement));
            }

            speculativeModel = CreateSpeculative(parentModel, methodSymbol, statement, binder, position);
            return true;
        }
Example #18
0
        private static BoundFieldInitializer BindFieldInitializer(Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax equalsValueClauseNode,
                                                                  DiagnosticBag diagnostics)
        {
            Debug.Assert(!fieldSymbol.IsMetadataConstant);

            var fieldsBeingBound = binder.FieldsBeingBound;

            var  sourceField            = fieldSymbol as SourceMemberFieldSymbol;
            bool isImplicitlyTypedField = (object)sourceField != null && sourceField.FieldTypeInferred(fieldsBeingBound);

            // If the type is implicitly typed, the initializer diagnostics have already been reported, so ignore them here:
            // CONSIDER (tomat): reusing the bound field initializers for implicitly typed fields.
            DiagnosticBag initializerDiagnostics;

            if (isImplicitlyTypedField)
            {
                initializerDiagnostics = DiagnosticBag.GetInstance();
            }
            else
            {
                initializerDiagnostics = diagnostics;
            }

            binder = new ExecutableCodeBinder(equalsValueClauseNode, fieldSymbol, new LocalScopeBinder(binder));
            var boundInitValue = binder.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);

            if (isImplicitlyTypedField)
            {
                initializerDiagnostics.Free();
            }

            return(new BoundFieldInitializer(
                       equalsValueClauseNode.Value, //we want the attached sequence point to indicate the value node
                       fieldSymbol,
                       boundInitValue));
        }
Example #19
0
        // NOTE: can return null if the method has no body.
        internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList<Imports> debugImports)
        {
            debugImports = null;

            BoundStatement constructorInitializer = null;
            BoundBlock body;

            var compilation = method.DeclaringCompilation;

            var sourceMethod = method as SourceMethodSymbol;
            if ((object)sourceMethod != null)
            {
                if (sourceMethod.IsExtern)
                {
                    if (sourceMethod.BlockSyntax == null)
                    {
                        // Generate warnings only if we are not generating ERR_ExternHasBody error
                        GenerateExternalMethodWarnings(sourceMethod, diagnostics);
                    }
                    return null;
                }
                else if (sourceMethod.IsParameterlessValueTypeConstructor(requireSynthesized: true))
                {
                    // No body for default struct constructor.
                    return null;
                }

                var blockSyntax = sourceMethod.BlockSyntax;
                if (blockSyntax != null)
                {
                var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree);
                var inMethodBinder = factory.GetBinder(blockSyntax);
                var binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
                body = binder.BindBlock(blockSyntax, diagnostics);
                if (generateDebugInfo)
                {
                    debugImports = binder.ImportsList;
                }
                if (inMethodBinder.IsDirectlyInIterator)
                {
                    foreach (var parameter in method.Parameters)
                    {
                        if (parameter.RefKind != RefKind.None)
                        {
                            diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]);
                        }
                        else if (parameter.Type.IsUnsafe())
                        {
                            diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]);
                        }
                    }

                    if (sourceMethod.IsUnsafe && compilation.Options.AllowUnsafe) // Don't cascade
                    {
                        diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, sourceMethod.Locations[0]);
                    }

                    if (sourceMethod.IsVararg)
                    {
                        // error CS1636: __arglist is not allowed in the parameter list of iterators
                        diagnostics.Add(ErrorCode.ERR_VarargsIterator, sourceMethod.Locations[0]);
                    }
                    }
                }
                else // for [if (blockSyntax != null)]
                {
                    var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol;
                    if ((object)property != null && property.IsAutoProperty)
                    {
                        return MethodBodySynthesizer.ConstructAutoPropertyAccessorBody(sourceMethod);
                }

                    if (sourceMethod.IsPrimaryCtor)
                    {
                        body = null;
            }
            else
            {
                        return null;
                    }
                }
            }
            else
            {
                //  synthesized methods should return their bound bodies 
                body = null;
            }

            // delegates have constructors but not constructor initializers
            if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType())
            {
                var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation);

                if (initializerInvocation != null)
                {
                    constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation) { WasCompilerGenerated = true };
                    Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
                }
            }

            var statements = ArrayBuilder<BoundStatement>.GetInstance();

            if (constructorInitializer != null)
            {
                statements.Add(constructorInitializer);
            }

            if ((object)sourceMethod != null && sourceMethod.IsPrimaryCtor && (object)((SourceMemberContainerTypeSymbol)sourceMethod.ContainingType).PrimaryCtor == (object)sourceMethod)
            {
                Debug.Assert(method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType());
                Debug.Assert(body == null);

                if (sourceMethod.ParameterCount > 0)
                {
                    var factory = new SyntheticBoundNodeFactory(sourceMethod, sourceMethod.SyntaxNode, compilationState, diagnostics);
                    factory.CurrentMethod = sourceMethod; 

                    foreach (var parameter in sourceMethod.Parameters)
                    {
                        FieldSymbol field = parameter.PrimaryConstructorParameterBackingField;

                        if ((object)field != null)
                        {
                            statements.Add(factory.Assignment(factory.Field(factory.This(), field),
                                                                   factory.Parameter(parameter)));
                        }
                    }
                }
            }

            if (body != null)
            {
                statements.Add(body);
            }

            CSharpSyntaxNode syntax = body != null ? body.Syntax : method.GetNonNullSyntaxNode();

            BoundBlock block;
            if (statements.Count == 1 && statements[0].Kind == ((body == null) ? BoundKind.Block : body.Kind))
            {
                // most common case - we just have a single block for the body.
                block = (BoundBlock)statements[0];
                statements.Free();
            }
            else
            {
                block = new BoundBlock(syntax, default(ImmutableArray<LocalSymbol>), statements.ToImmutableAndFree()) { WasCompilerGenerated = true };
            }

            return method.MethodKind == MethodKind.Destructor ? MethodBodySynthesizer.ConstructDestructorBody(syntax, method, block) : block;
        }
Example #20
0
        /// <summary>
        /// Performs the same function as GetEnclosingBinder, but is known to take place within a
        /// specified lambda.  Walks up the syntax hierarchy until a node with an associated binder
        /// is found.
        /// </summary>
        /// <remarks>
        /// CONSIDER: can this share code with MemberSemanticModel.GetEnclosingBinder?
        /// 
        /// Returned binder doesn't need to have <see cref="BinderFlags.SemanticModel"/> set - the caller will add it.
        /// </remarks>
        private static Binder GetLambdaEnclosingBinder(int position, CSharpSyntaxNode startingNode, CSharpSyntaxNode containingLambda, ExecutableCodeBinder lambdaBinder)
        {
            Debug.Assert(containingLambda.IsAnonymousFunction());
            Debug.Assert(LookupPosition.IsInAnonymousFunctionOrQuery(position, containingLambda));

            var current = startingNode;
            while (current != containingLambda)
            {
                Debug.Assert(current != null);

                StatementSyntax stmt = current as StatementSyntax;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchBlockScope(position, (CatchClauseSyntax)current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.CatchFilterClause)
                {
                    if (LookupPosition.IsInCatchFilterScope(position, (CatchFilterClauseSyntax)current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        Binder binder = lambdaBinder.GetBinder(current);
                        if (binder != null)
                        {
                            return binder;
                        }
                    }
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                current = current.ParentOrStructuredTriviaParent;
            }

            return lambdaBinder;
        }
Example #21
0
        private static BoundFieldInitializer BindFieldInitializer(Binder binder, FieldSymbol fieldSymbol, EqualsValueClauseSyntax equalsValueClauseNode,
            DiagnosticBag diagnostics)
        {
            Debug.Assert(!fieldSymbol.IsMetadataConstant);

            var fieldsBeingBound = binder.FieldsBeingBound;

            var sourceField = fieldSymbol as SourceMemberFieldSymbolFromDeclarator;
            bool isImplicitlyTypedField = (object)sourceField != null && sourceField.FieldTypeInferred(fieldsBeingBound);

            // If the type is implicitly typed, the initializer diagnostics have already been reported, so ignore them here:
            // CONSIDER (tomat): reusing the bound field initializers for implicitly typed fields.
            DiagnosticBag initializerDiagnostics;
            if (isImplicitlyTypedField)
            {
                initializerDiagnostics = DiagnosticBag.GetInstance();
            }
            else
            {
                initializerDiagnostics = diagnostics;
            }

            binder = new ExecutableCodeBinder(equalsValueClauseNode, fieldSymbol, new LocalScopeBinder(binder));
            var boundInitValue = binder.BindVariableOrAutoPropInitializer(equalsValueClauseNode, RefKind.None, fieldSymbol.GetFieldType(fieldsBeingBound), initializerDiagnostics);

            if (isImplicitlyTypedField)
            {
                initializerDiagnostics.Free();
            }

            return new BoundFieldInitializer(
                equalsValueClauseNode.Value, //we want the attached sequence point to indicate the value node
                fieldSymbol,
                boundInitValue);
        }
Example #22
0
        private static Binder GetEnclosingBinder(SyntaxNode node, int position, Binder rootBinder, SyntaxNode root)
        {
            if (node == root)
            {
                return rootBinder.GetBinder(node) ?? rootBinder;
            }

            Debug.Assert(root.Contains(node));

            ExpressionSyntax typeOfArgument = null;
            SyntaxNode unexpectedAnonymousFunction = null;

            // Keep track of which fix-up should be applied first.  If we see a typeof expression inside an unexpected
            // anonymous function, that the typeof binder should be innermost (i.e. should have the unexpected
            // anonymous function binder as its Next).
            // NOTE: only meaningful if typeOfArgument is non-null;
            bool typeOfEncounteredBeforeUnexpectedAnonymousFunction = false;

            Binder binder = null;
            for (var current = node; binder == null; current = current.ParentOrStructuredTriviaParent)
            {
                Debug.Assert(current != null); // Why were we asked for an enclosing binder for a node outside our root?
                StatementSyntax stmt = current as StatementSyntax;
                TypeOfExpressionSyntax typeOfExpression;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        binder = rootBinder.GetBinder(current);

                        if (binder != null)
                        {
                            binder = AdjustBinderForPositionWithinStatement(position, binder, stmt);
                        }
                    }
                }
                else if (current.Kind() == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchBlockScope(position, (CatchClauseSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.CatchFilterClause)
                {
                    if (LookupPosition.IsInCatchFilterScope(position, (CatchFilterClauseSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        binder = rootBinder.GetBinder(current);

                        // This should only happen in error scenarios.  For example, C# does not allow array rank
                        // specifiers in types, (e.g. int[1] x;), but the syntax model does.  In order to construct
                        // an appropriate binder chain for the anonymous method body, we need to construct an
                        // ExecutableCodeBinder.
                        if (binder == null && unexpectedAnonymousFunction == null && current != root)
                        {
                            unexpectedAnonymousFunction = current;
                        }
                    }
                }
                else if (current.Kind() == SyntaxKind.TypeOfExpression &&
                    typeOfArgument == null &&
                    LookupPosition.IsBetweenTokens(
                        position,
                        (typeOfExpression = (TypeOfExpressionSyntax)current).OpenParenToken,
                        typeOfExpression.CloseParenToken))
                {
                    typeOfArgument = typeOfExpression.Type;
                    typeOfEncounteredBeforeUnexpectedAnonymousFunction = unexpectedAnonymousFunction == null;
                }
                else if (current.Kind() == SyntaxKind.SwitchSection)
                {
                    if (LookupPosition.IsInSwitchSectionScope(position, (SwitchSectionSyntax)current))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.ArgumentList)
                {
                    var argList = (ArgumentListSyntax)current;

                    if (LookupPosition.IsBetweenTokens(position, argList.OpenParenToken, argList.CloseParenToken))
                    {
                        binder = rootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind() == SyntaxKind.EqualsValueClause)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current.Kind() == SyntaxKind.Attribute)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current.Kind() == SyntaxKind.ArrowExpressionClause)
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current is ExpressionSyntax && 
                            ((current.Parent as LambdaExpressionSyntax)?.Body == current ||
                             (current.Parent as SwitchStatementSyntax)?.Expression == current ||
                             (current.Parent as CommonForEachStatementSyntax)?.Expression == current))
                {
                    binder = rootBinder.GetBinder(current);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent as ForEachComponentStatementSyntax)?.VariableComponent == current)
                {
                    binder = rootBinder.GetBinder(current.Parent);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent is VariableComponentAssignmentSyntax) &&
                             (current.Parent.Parent as ForStatementSyntax)?.Deconstruction == current)
                {
                    binder = rootBinder.GetBinder(current.Parent.Parent);
                }
                else if (current is VariableComponentSyntax &&
                             (current.Parent is VariableComponentAssignmentSyntax) &&
                             (current.Parent.Parent as DeconstructionDeclarationStatementSyntax)?.Assignment.VariableComponent == current)
                {
                    binder = rootBinder.GetBinder(current.Parent.Parent);
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                if (current == root)
                {
                    break;
                }
            }

            binder = binder ?? rootBinder.GetBinder(root) ?? rootBinder;
            Debug.Assert(binder != null);

            if (typeOfArgument != null && !typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            if (unexpectedAnonymousFunction != null)
            {
                binder = new ExecutableCodeBinder(unexpectedAnonymousFunction,
                                                  new LambdaSymbol(binder.ContainingMemberOrLambda,
                                                                   ImmutableArray<ParameterSymbol>.Empty,
                                                                   RefKind.None,
                                                                   ErrorTypeSymbol.UnknownResultType,
                                                                   unexpectedAnonymousFunction.Kind() == SyntaxKind.AnonymousMethodExpression ? MessageID.IDS_AnonMethod : MessageID.IDS_Lambda,
                                                                   unexpectedAnonymousFunction,
                                                                   isSynthesized: false),
                                                  binder);
            }

            if (typeOfArgument != null && typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            return binder;
        }
Example #23
0
        /// <summary>
        /// Bind the constructor initializer in the context of the specified location and get semantic information
        /// such as type, symbols and diagnostics. This method is used to get semantic information about a constructor
        /// initializer that did not actually appear in the source code.
        /// 
        /// NOTE: This will only work in locations where there is already a constructor initializer.
        /// </summary>
        /// <param name="position">A character position used to identify a declaration scope and accessibility. This
        /// character position must be within the FullSpan of the Root syntax node in this SemanticModel.
        /// Furthermore, it must be within the span of an existing constructor initializer.
        /// </param>
        /// <param name="constructorInitializer">A syntax node that represents a parsed constructor initializer. This syntax node
        /// need not and typically does not appear in the source code referred to SemanticModel instance.</param>
        /// <returns>The semantic information for the topmost node of the constructor initializer.</returns>
        public SymbolInfo GetSpeculativeSymbolInfo(int position, ConstructorInitializerSyntax constructorInitializer)
        {
            Debug.Assert(CanGetSemanticInfo(constructorInitializer, isSpeculative: true));

            position = CheckAndAdjustPosition(position);

            if (constructorInitializer == null)
            {
                throw new ArgumentNullException(nameof(constructorInitializer));
            }

            // NOTE: since we're going to be depending on a MemberModel to do the binding for us,
            // we need to find a constructor initializer in the tree of this semantic model.
            // NOTE: This approach will not allow speculative binding of a constructor initializer
            // on a constructor that didn't formerly have one.
            // TODO: Should we support positions that are not in existing constructor initializers?
            // If so, we will need to build up the context that would otherwise be built up by
            // InitializerMemberModel.
            var existingConstructorInitializer = this.Root.FindToken(position).Parent.AncestorsAndSelf().OfType<ConstructorInitializerSyntax>().FirstOrDefault();

            if (existingConstructorInitializer == null)
            {
                return SymbolInfo.None;
            }

            MemberSemanticModel memberModel = GetMemberModel(existingConstructorInitializer);

            if (memberModel == null)
            {
                return SymbolInfo.None;
            }

            var binder = this.GetEnclosingBinder(position);
            if (binder != null)
            {
                var diagnostics = DiagnosticBag.GetInstance();

                if (constructorInitializer.ArgumentList != null)
                {
                    binder = new ExecutableCodeBinder(constructorInitializer.ArgumentList, binder.ContainingMemberOrLambda, binder);
                }

                var bnode = memberModel.Bind(binder, constructorInitializer, diagnostics);
                var binfo = memberModel.GetSymbolInfoForNode(SymbolInfoOptions.DefaultOptions, bnode, bnode, boundNodeForSyntacticParent: null, binderOpt: binder);
                diagnostics.Free();
                return binfo;
            }
            else
            {
                return SymbolInfo.None;
            }
        }
Example #24
0
        /// <summary>
        /// Creates a SemanticModel for the method.
        /// </summary>
        internal static MethodBodySemanticModel Create(SyntaxTreeSemanticModel containingSemanticModel, MethodSymbol owner, ExecutableCodeBinder executableCodeBinder,
                                                       CSharpSyntaxNode syntax, BoundNode boundNode = null)
        {
            Debug.Assert(containingSemanticModel != null);
            var result = new MethodBodySemanticModel(owner, executableCodeBinder, syntax, containingSemanticModel);

            if (boundNode != null)
            {
                result.UnguardedAddBoundTreeForStandaloneSyntax(syntax, boundNode);
            }

            return(result);
        }
Example #25
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
                                                        ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers, ArrayBuilder <BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
                                                        out ImportChain firstDebugImports)
        {
            Debug.Assert((object)scriptCtor != null);

            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray <FieldOrPropertyInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.FieldOpt;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    Debug.Assert(syntaxRef.SyntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportChain;
                    }

                    Binder parentBinder = new ExecutableCodeBinder((CSharpSyntaxNode)syntaxRef.SyntaxTree.GetRoot(), scriptCtor, scriptClassBinder);

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);
                    }
                    else if (initializerNode.Kind() == SyntaxKind.LabeledStatement)
                    {
                        // TODO: labels in interactive
                        var boundStatement = new BoundBadStatement(initializerNode, ImmutableArray <BoundNode> .Empty, true);
                        boundInitializer = new BoundGlobalStatementInitializer(initializerNode, boundStatement);
                    }
                    else
                    {
                        var collisionDetector = new LocalScopeBinder(parentBinder);
                        boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
                                                               isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
Example #26
0
 /// <summary>
 /// Creates an AttributeSemanticModel that allows asking semantic questions about an attribute node.
 /// </summary>
 public static AttributeSemanticModel Create(CSharpCompilation compilation, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder)
 {
     var executableBinder = new ExecutableCodeBinder(syntax, attributeType, rootBinder);
     return new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new LocalScopeBinder(executableBinder));
 }
Example #27
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var     invokeMethod = DelegateInvokeMethod(delegateType);
            RefKind refKind;
            var     returnType = DelegateReturnType(invokeMethod, out refKind);

            LambdaSymbol lambdaSymbol;
            Binder       lambdaBodyBinder;
            BoundBlock   block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for
            // return type inference.
            var cacheKey = ReturnInferenceCacheKey.Create(delegateType, IsAsync);

            BoundLambda returnInferenceLambda;

            if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType)
            {
                lambdaSymbol = returnInferenceLambda.Symbol;
                if ((object)LambdaSymbol.InferenceFailureReturnType != lambdaSymbol.ReturnType &&
                    lambdaSymbol.ReturnType == returnType && lambdaSymbol.RefKind == refKind)
                {
                    lambdaBodyBinder = returnInferenceLambda.Binder;
                    block            = returnInferenceLambda.Body;
                    diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                    goto haveLambdaBodyAndBinders;
                }
            }

            lambdaSymbol = new LambdaSymbol(
                binder.Compilation,
                binder.ContainingMemberOrLambda,
                _unboundLambda,
                cacheKey.ParameterTypes,
                cacheKey.ParameterRefKinds,
                refKind,
                returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block            = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);

            ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics);
            ValidateUnsafeParameters(diagnostics, cacheKey.ParameterTypes);

haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);

            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(invokeMethod))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.DiagnosticLocation, this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    !returnType.IsNonGenericTaskType(binder.Compilation) &&
                    !returnType.IsGenericTaskType(binder.Compilation))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.DiagnosticLocation, lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.DiagnosticLocation);
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            {
                WasCompilerGenerated = _unboundLambda.WasCompilerGenerated
            };

            return(result);
        }
Example #28
0
 public BoundLambda(CSharpSyntaxNode syntax, BoundBlock body, ImmutableArray <Diagnostic> diagnostics, ExecutableCodeBinder binder, TypeSymbol type)
     : this(syntax, (LambdaSymbol)binder.MemberSymbol, body, diagnostics, binder, type)
 {
 }
Example #29
0
        // NOTE: can return null if the method has no body.
        internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo, out ConsList <Imports> debugImports)
        {
            debugImports = null;

            BoundStatement constructorInitializer = null;
            BoundBlock     body;

            var compilation = method.DeclaringCompilation;

            var sourceMethod = method as SourceMethodSymbol;

            if ((object)sourceMethod != null)
            {
                if (sourceMethod.IsExtern)
                {
                    if (sourceMethod.BlockSyntax == null)
                    {
                        // Generate warnings only if we are not generating ERR_ExternHasBody error
                        GenerateExternalMethodWarnings(sourceMethod, diagnostics);
                    }
                    return(null);
                }
                else if (sourceMethod.IsParameterlessValueTypeConstructor(requireSynthesized: true))
                {
                    // No body for default struct constructor.
                    return(null);
                }

                var blockSyntax = sourceMethod.BlockSyntax;
                if (blockSyntax != null)
                {
                    var factory        = compilation.GetBinderFactory(sourceMethod.SyntaxTree);
                    var inMethodBinder = factory.GetBinder(blockSyntax);
                    var binder         = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
                    body = binder.BindBlock(blockSyntax, diagnostics);
                    if (generateDebugInfo)
                    {
                        debugImports = binder.ImportsList;
                    }
                    if (inMethodBinder.IsDirectlyInIterator)
                    {
                        foreach (var parameter in method.Parameters)
                        {
                            if (parameter.RefKind != RefKind.None)
                            {
                                diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]);
                            }
                            else if (parameter.Type.IsUnsafe())
                            {
                                diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]);
                            }
                        }

                        if (sourceMethod.IsUnsafe && compilation.Options.AllowUnsafe) // Don't cascade
                        {
                            diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, sourceMethod.Locations[0]);
                        }

                        if (sourceMethod.IsVararg)
                        {
                            // error CS1636: __arglist is not allowed in the parameter list of iterators
                            diagnostics.Add(ErrorCode.ERR_VarargsIterator, sourceMethod.Locations[0]);
                        }
                    }
                }
                else // for [if (blockSyntax != null)]
                {
                    var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol;
                    if ((object)property != null && property.IsAutoProperty)
                    {
                        return(MethodBodySynthesizer.ConstructAutoPropertyAccessorBody(sourceMethod));
                    }

                    if (sourceMethod.IsPrimaryCtor)
                    {
                        body = null;
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            else
            {
                //  synthesized methods should return their bound bodies
                body = null;
            }

            // delegates have constructors but not constructor initializers
            if (method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType())
            {
                var initializerInvocation = BindConstructorInitializer(method, diagnostics, compilation);

                if (initializerInvocation != null)
                {
                    constructorInitializer = new BoundExpressionStatement(initializerInvocation.Syntax, initializerInvocation)
                    {
                        WasCompilerGenerated = true
                    };
                    Debug.Assert(initializerInvocation.HasAnyErrors || constructorInitializer.IsConstructorInitializer(), "Please keep this bound node in sync with BoundNodeExtensions.IsConstructorInitializer.");
                }
            }

            var statements = ArrayBuilder <BoundStatement> .GetInstance();

            if (constructorInitializer != null)
            {
                statements.Add(constructorInitializer);
            }

            if ((object)sourceMethod != null && sourceMethod.IsPrimaryCtor && (object)((SourceMemberContainerTypeSymbol)sourceMethod.ContainingType).PrimaryCtor == (object)sourceMethod)
            {
                Debug.Assert(method.MethodKind == MethodKind.Constructor && !method.ContainingType.IsDelegateType());
                Debug.Assert(body == null);

                if (sourceMethod.ParameterCount > 0)
                {
                    var factory = new SyntheticBoundNodeFactory(sourceMethod, sourceMethod.SyntaxNode, compilationState, diagnostics);
                    factory.CurrentMethod = sourceMethod;

                    foreach (var parameter in sourceMethod.Parameters)
                    {
                        FieldSymbol field = parameter.PrimaryConstructorParameterBackingField;

                        if ((object)field != null)
                        {
                            statements.Add(factory.Assignment(factory.Field(factory.This(), field),
                                                              factory.Parameter(parameter)));
                        }
                    }
                }
            }

            if (body != null)
            {
                statements.Add(body);
            }

            CSharpSyntaxNode syntax = body != null ? body.Syntax : method.GetNonNullSyntaxNode();

            BoundBlock block;

            if (statements.Count == 1 && statements[0].Kind == ((body == null) ? BoundKind.Block : body.Kind))
            {
                // most common case - we just have a single block for the body.
                block = (BoundBlock)statements[0];
                statements.Free();
            }
            else
            {
                block = new BoundBlock(syntax, default(ImmutableArray <LocalSymbol>), statements.ToImmutableAndFree())
                {
                    WasCompilerGenerated = true
                };
            }

            return(method.MethodKind == MethodKind.Destructor ? MethodBodySynthesizer.ConstructDestructorBody(syntax, method, block) : block);
        }
Example #30
0
 protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics)
 {
     return(bodyResolver(lambdaSymbol, lambdaBodyBinder, diagnostics));
 }
Example #31
0
 public BoundLambda(CSharpSyntaxNode syntax, BoundBlock body, ImmutableArray<Diagnostic> diagnostics, ExecutableCodeBinder binder, TypeSymbol type)
     : this(syntax, (LambdaSymbol)binder.MemberSymbol, body, diagnostics, binder, type)
 {
 }
 /// <summary>
 /// Creates a SemanticModel for an ArrowExpressionClause, which includes
 /// an ExecutableCodeBinder and a ScopedExpressionBinder.
 /// </summary>
 internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, ArrowExpressionClauseSyntax syntax)
 {
     Binder binder = new ExecutableCodeBinder(syntax, owner, rootBinder);
     return new MethodBodySemanticModel(compilation, owner, binder, syntax);
 }
Example #33
0
 protected abstract BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder binder, DiagnosticBag diagnostics);
 protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics)
 {
     return bodyResolver(lambdaSymbol, lambdaBodyBinder, diagnostics);
 }
Example #35
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var invokeMethod = DelegateInvokeMethod(delegateType);
            RefKind refKind;
            var returnType = DelegateReturnType(invokeMethod, out refKind);

            LambdaSymbol lambdaSymbol;
            Binder lambdaBodyBinder;
            BoundBlock block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for 
            // return type inference.
            MethodSymbol cacheKey = GetCacheKey(delegateType);

            BoundLambda returnInferenceLambda;
            if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType && returnInferenceLambda.Symbol.ReturnType == returnType)
            {
                lambdaSymbol = returnInferenceLambda.Symbol;
                Debug.Assert(lambdaSymbol.RefKind == refKind);

                lambdaBodyBinder = returnInferenceLambda.Binder;
                block = returnInferenceLambda.Body;
                diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                goto haveLambdaBodyAndBinders;
            }

            var parameters = DelegateParameters(invokeMethod);

            lambdaSymbol = new LambdaSymbol(
                binder.Compilation,
                binder.ContainingMemberOrLambda,
                _unboundLambda,
                parameters,
                refKind,
                returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);

            ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics);
            ValidateUnsafeParameters(diagnostics, parameters);

        haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);
            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(invokeMethod))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    !returnType.IsNonGenericTaskType(binder.Compilation) &&
                    !returnType.IsGenericTaskType(binder.Compilation))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.Locations[0]);
            }

            // This is an attempt to get a repro for https://devdiv.visualstudio.com/DevDiv/_workitems?id=278481
            if ((object)returnType != null && returnType.SpecialType != SpecialType.System_Void &&
                !block.HasErrors && !diagnostics.HasAnyResolvedErrors() && block.Statements.Length > 0)
            {
                BoundStatement first = block.Statements[0];
                if (first.Kind == BoundKind.ReturnStatement)
                {
                    var returnStmt = (BoundReturnStatement)first;
                    if (returnStmt.ExpressionOpt != null && (object)returnStmt.ExpressionOpt.Type == null)
                    {
                        throw ExceptionUtilities.Unreachable;
                    }
                }
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated };

            return result;
        }
Example #36
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var returnType = DelegateReturnType(delegateType);

            LambdaSymbol lambdaSymbol;
            Binder lambdaBodyBinder;
            BoundBlock block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for 
            // return type inference.
            MethodSymbol cacheKey = GetCacheKey(delegateType);

            BoundLambda returnInferenceLambda;
            if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType)
            {
                var lambdaSym = returnInferenceLambda.Symbol;
                var lambdaRetType = lambdaSym.ReturnType;
                if (lambdaRetType == returnType)
                {
                    lambdaSymbol = lambdaSym;
                    lambdaBodyBinder = returnInferenceLambda.Binder;
                    block = returnInferenceLambda.Body;
                    diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                    goto haveLambdaBodyAndBinders;
                }
            }

            var parameters = DelegateParameters(delegateType);
            lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics);
            ValidateUnsafeParameters(diagnostics, parameters);

        haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);
            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(delegateType))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol, _unboundLambda.Syntax);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    returnType != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) &&
                    returnType.OriginalDefinition != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol, diagnostics, lambdaSymbol.Locations[0]);
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated };

            return result;
        }
Example #37
0
        /// <summary>
        /// Bind the given attribute speculatively at the given position, and return back
        /// the resulting bound node. May return null in some error cases.
        /// </summary>
        private BoundAttribute GetSpeculativelyBoundAttribute(int position, AttributeSyntax attribute, out Binder binder)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException(nameof(attribute));
            }

            binder = this.GetSpeculativeBinderForAttribute(position);
            if (binder == null)
            {
                return null;
            }

            var diagnostics = DiagnosticBag.GetInstance();
            AliasSymbol aliasOpt; // not needed.
            NamedTypeSymbol attributeType = (NamedTypeSymbol)binder.BindType(attribute.Name, diagnostics, out aliasOpt);
            var boundNode = new ExecutableCodeBinder(attribute, binder.ContainingMemberOrLambda, binder).BindAttribute(attribute, attributeType, diagnostics);
            diagnostics.Free();

            return boundNode;
        }
Example #38
0
        /// <summary>
        /// Creates a SemanticModel for the method.
        /// </summary>
        internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, ExecutableCodeBinder executableCodeBinder,
                                                       CSharpSyntaxNode syntax, BoundNode boundNode = null)
        {
            var result = new MethodBodySemanticModel(compilation, owner, executableCodeBinder, syntax);

            if (boundNode != null)
            {
                result.UnguardedAddBoundTreeForStandaloneSyntax(syntax, boundNode);
            }

            return(result);
        }
        /// <summary>
        /// This overload exists for callers who
        ///   a) Already have a node in hand and don't want to search through the tree
        ///   b) May want to search from an indirect container (e.g. node containing node
        ///      containing position).
        /// </summary>
        private Binder GetEnclosingBinder(CSharpSyntaxNode node, int position)
        {
            AssertPositionAdjusted(position);

            if (node == this.root)
            {
                return RootBinder;
            }

            ExpressionSyntax typeOfArgument = null;
            CSharpSyntaxNode unexpectedAnonymousFunction = null;

            // Keep track of which fix-up should be applied first.  If we see a typeof expression inside an unexpected
            // anonymous function, that the typeof binder should be innermost (i.e. should have the unexpected
            // anonymous function binder as its Next).
            // NOTE: only meaningful if typeOfArgument is non-null;
            bool typeOfEncounteredBeforeUnexpectedAnonymousFunction = false;

            Binder binder = null;
            for (var current = node; binder == null; current = current.ParentOrStructuredTriviaParent)
            {
                Debug.Assert(current != null); // Why were we asked for an enclosing binder for a node outside our root?

                StatementSyntax stmt = current as StatementSyntax;
                if (stmt != null)
                {
                    if (LookupPosition.IsInStatementScope(position, stmt))
                    {
                        binder = RootBinder.GetBinder(current);

                        if (binder != null)
                        {
                            binder = AdjustBinderForPositionWithinStatement(position, binder, stmt);
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.CatchClause)
                {
                    if (LookupPosition.IsInCatchBlockScope(position, (CatchClauseSyntax)current))
                    {
                        binder = RootBinder.GetBinder(current);
                    }
                }
                else if (current.Kind == SyntaxKind.CatchFilterClause)
                {
                    if (LookupPosition.IsInCatchFilterScope(position, (CatchFilterClauseSyntax)current))
                    {
                        binder = RootBinder.GetBinder(current);
                    }
                }
                else if (current.IsAnonymousFunction())
                {
                    if (LookupPosition.IsInAnonymousFunctionOrQuery(position, current))
                    {
                        binder = RootBinder.GetBinder(current);

                        // This should only happen in error scenarios.  For example, C# does not allow array rank
                        // specifiers in types, (e.g. int[1] x;), but the syntax model does.  In order to construct
                        // an appropriate binder chain for the anonymous method body, we need to construct an
                        // ExecutableCodeBinder.
                        if (binder == null && unexpectedAnonymousFunction == null)
                        {
                            unexpectedAnonymousFunction = current;
                        }
                    }
                }
                else if (current.Kind == SyntaxKind.TypeOfExpression && typeOfArgument == null)
                {
                    typeOfArgument = ((TypeOfExpressionSyntax)current).Type;
                    typeOfEncounteredBeforeUnexpectedAnonymousFunction = unexpectedAnonymousFunction == null;
                }
                else
                {
                    // If this ever breaks, make sure that all callers of
                    // CanHaveAssociatedLocalBinder are in sync.
                    Debug.Assert(!current.CanHaveAssociatedLocalBinder());
                }

                if (current == this.root)
                {
                    break;
                }
            }

            binder = binder ?? RootBinder;
            Debug.Assert(binder != null);

            if (typeOfArgument != null && !typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            if (unexpectedAnonymousFunction != null)
            {
                binder = new ExecutableCodeBinder(unexpectedAnonymousFunction, ErrorMethodSymbol.UnknownMethod, binder);
            }

            if (typeOfArgument != null && typeOfEncounteredBeforeUnexpectedAnonymousFunction)
            {
                binder = new TypeofBinder(typeOfArgument, binder);
            }

            return binder.WithAdditionalFlags(BinderFlags.SemanticModel);
        }
        private bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, CSharpSyntaxNode initializer, out SemanticModel speculativeModel)
        {
            Debug.Assert(initializer is EqualsValueClauseSyntax || initializer is ConstructorInitializerSyntax);

            var binder = this.GetEnclosingBinder(position);
            if (binder == null)
            {
                speculativeModel = null;
                return false;
            }

            switch (initializer.Kind())
            {
                case SyntaxKind.EqualsValueClause:
                    binder = new ExecutableCodeBinder(initializer, binder.ContainingMemberOrLambda, binder);
                    break;

                case SyntaxKind.ThisConstructorInitializer:
                case SyntaxKind.BaseConstructorInitializer:
                    ArgumentListSyntax argList = ((ConstructorInitializerSyntax)initializer).ArgumentList;
                    if (argList != null)
                    {
                        binder = new ExecutableCodeBinder(argList, binder.ContainingMemberOrLambda, binder);
                    }
                    break;
            }

            speculativeModel = CreateSpeculative(parentModel, this.MemberSymbol, initializer, binder, position);
            return true;
        }
Example #41
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
            ArrayBuilder<BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            out ImportChain firstDebugImports)
        {
            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray<FieldOrPropertyInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder 
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;
                // Label instances must be shared across all global statements.
                ScriptLocalScopeBinder.Labels labels = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.FieldOpt;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    var syntaxTree = syntaxRef.SyntaxTree;
                    Debug.Assert(syntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var syntax = (CSharpSyntaxNode)syntaxRef.GetSyntax();
                    var syntaxRoot = syntaxTree.GetCompilationUnitRoot();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxTree);
                        labels = new ScriptLocalScopeBinder.Labels(scriptInitializer, syntaxRoot);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(syntax);
                    Debug.Assert(((NamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportChain;
                    }

                    Binder parentBinder = new ExecutableCodeBinder(
                        syntaxRoot,
                        scriptInitializer,
                        new ScriptLocalScopeBinder(labels, scriptClassBinder));

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            parentBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)syntax,
                            diagnostics);
                    }
                    else
                    {
                        boundInitializer = BindGlobalStatement(
                            parentBinder,
                            scriptInitializer,
                            (StatementSyntax)syntax,
                            diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
        private Binder GetFieldOrPropertyInitializerBinder(FieldSymbol symbol, Binder outer, EqualsValueClauseSyntax initializer)
        {
            BinderFlags flags = BinderFlags.None;

            // NOTE: checking for a containing script class is sufficient, but the regular C# test is quick and easy.
            if (this.IsRegularCSharp || !symbol.ContainingType.IsScriptClass)
            {
                flags |= BinderFlags.FieldInitializer;
            }

            outer = new LocalScopeBinder(outer).WithAdditionalFlagsAndContainingMemberOrLambda(flags, symbol);

            if (initializer != null)
            {
                outer = new ExecutableCodeBinder(initializer, symbol, outer);
            }

            return outer;
        }
Example #43
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var returnType = DelegateReturnType(delegateType);

            LambdaSymbol lambdaSymbol;
            Binder       lambdaBodyBinder;
            BoundBlock   block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for
            // return type inference.
            MethodSymbol cacheKey = GetCacheKey(delegateType);

            BoundLambda returnInferenceLambda;

            if (returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType)
            {
                var lambdaSym     = returnInferenceLambda.Symbol;
                var lambdaRetType = lambdaSym.ReturnType;
                if (lambdaRetType == returnType)
                {
                    lambdaSymbol     = lambdaSym;
                    lambdaBodyBinder = returnInferenceLambda.Binder;
                    block            = returnInferenceLambda.Body;
                    diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                    goto haveLambdaBodyAndBinders;
                }
            }

            var parameters = DelegateParameters(delegateType);

            lambdaSymbol     = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, this.unboundLambda, parameters, returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(this.unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block            = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics);
            ValidateUnsafeParameters(diagnostics, parameters);

haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);

            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(delegateType))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol, this.unboundLambda.Syntax);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    returnType != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) &&
                    returnType.OriginalDefinition != binder.Compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task_T))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol, diagnostics, lambdaSymbol.Locations[0]);
            }

            var result = new BoundLambda(this.unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType)
            {
                WasCompilerGenerated = this.unboundLambda.WasCompilerGenerated
            };

            return(result);
        }
        // Create a member model for the given declaration syntax. In certain very malformed
        // syntax trees, there may not be a symbol that can have a member model associated with it
        // (although we try to minimize such cases). In such cases, null is returned.
        private MemberSemanticModel CreateMemberModel(CSharpSyntaxNode node)
        {
            var outer = _binderFactory.GetBinder(node);

            if (this.IgnoresAccessibility)
            {
                outer = outer.WithAdditionalFlags(BinderFlags.IgnoreAccessibility);
            }

            switch (node.Kind())
            {
                case SyntaxKind.Block:

                    MemberDeclarationSyntax memberDecl;
                    AccessorDeclarationSyntax accessorDecl;
                    if ((memberDecl = node.Parent as MemberDeclarationSyntax) != null)
                    {
                        var symbol = (SourceMethodSymbol)GetDeclaredSymbol(memberDecl);
                        if ((object)symbol == null)
                            return null;

                        return MethodBodySemanticModel.Create(this.Compilation, symbol, outer, memberDecl);
                    }
                    else if ((accessorDecl = node.Parent as AccessorDeclarationSyntax) != null)
                    {
                        var symbol = (SourceMethodSymbol)GetDeclaredSymbol(accessorDecl);
                        if ((object)symbol == null)
                            return null;

                        return MethodBodySemanticModel.Create(this.Compilation, symbol, outer, accessorDecl);
                    }
                    else
                    {
                        Debug.Assert(false, "Unexpected node: " + node.Parent);
                        return null;
                    }

                case SyntaxKind.EqualsValueClause:
                    switch (node.Parent.Kind())
                    {
                        case SyntaxKind.VariableDeclarator:
                            {
                                var variableDecl = (VariableDeclaratorSyntax)node.Parent;
                                SourceMemberFieldSymbol fieldSymbol = GetDeclaredFieldSymbol(variableDecl);

                                return InitializerSemanticModel.Create(
                                    this.Compilation,
                                    variableDecl,   //pass in the entire field initializer to permit region analysis. 
                                    fieldSymbol,
                                    //if we're in regular C#, then insert an extra binder to perform field initialization checks
                                    GetFieldOrPropertyInitializerBinder(fieldSymbol, outer, variableDecl.Initializer));
                            }

                        case SyntaxKind.PropertyDeclaration:
                            {
                                var propertyDecl = (PropertyDeclarationSyntax)node.Parent;
                                var propertySymbol = (SourcePropertySymbol)GetDeclaredSymbol(propertyDecl);
                                return InitializerSemanticModel.Create(
                                    this.Compilation,
                                    propertyDecl,
                                    propertySymbol,
                                    GetFieldOrPropertyInitializerBinder(propertySymbol.BackingField, outer, propertyDecl.Initializer));
                            }

                        case SyntaxKind.Parameter:
                            {
                                // NOTE: we don't need to create a member model for lambda parameter default value
                                // (which is bad code anyway) because lambdas only appear in code with associated
                                // member models.
                                ParameterSyntax parameterDecl = (ParameterSyntax)node.Parent;
                                ParameterSymbol parameterSymbol = GetDeclaredNonLambdaParameterSymbol(parameterDecl);
                                if ((object)parameterSymbol == null)
                                    return null;

                                return InitializerSemanticModel.Create(
                                    this.Compilation,
                                    parameterDecl,
                                    parameterSymbol,
                                    outer.CreateBinderForParameterDefaultValue(parameterSymbol, (EqualsValueClauseSyntax)node));
                            }

                        case SyntaxKind.EnumMemberDeclaration:
                            {
                                var enumDecl = (EnumMemberDeclarationSyntax)node.Parent;
                                var enumSymbol = (FieldSymbol)GetDeclaredSymbol(enumDecl);
                                if ((object)enumSymbol == null)
                                    return null;

                                return InitializerSemanticModel.Create(
                                    this.Compilation,
                                    enumDecl,
                                    enumSymbol,
                                    GetFieldOrPropertyInitializerBinder(enumSymbol, outer, enumDecl.EqualsValue));
                            }
                        default:
                            throw ExceptionUtilities.UnexpectedValue(node.Parent.Kind());
                    }

                case SyntaxKind.ArrowExpressionClause:
                    {
                        SourceMethodSymbol symbol = null;
                        MemberDeclarationSyntax memberSyntax;
                        var exprDecl = (ArrowExpressionClauseSyntax)node;

                        if (node.Parent is BasePropertyDeclarationSyntax)
                        {
                            symbol = (SourceMethodSymbol)GetDeclaredSymbol(exprDecl);
                        }
                        else if ((memberSyntax = node.Parent as MemberDeclarationSyntax) != null)
                        {
                            symbol = (SourceMethodSymbol)GetDeclaredSymbol(node.Parent as MemberDeclarationSyntax);
                        }
                        else
                        {
                            // Don't throw, just use for the assert
                            ExceptionUtilities.UnexpectedValue(node.Parent);
                        }

                        if ((object)symbol == null)
                            return null;
                        return MethodBodySemanticModel.Create(
                            _compilation, symbol, outer.WithContainingMemberOrLambda(symbol), exprDecl);
                    }

                case SyntaxKind.GlobalStatement:
                    {
                        Debug.Assert(!this.IsRegularCSharp);
                        var parent = node.Parent;
                        // TODO (tomat): handle misplaced global statements
                        if (parent.Kind() == SyntaxKind.CompilationUnit)
                        {
                            var scriptInitializer = _compilation.ScriptClass.GetScriptInitializer();
                            Debug.Assert((object)scriptInitializer != null);
                            if ((object)scriptInitializer == null)
                            {
                                return null;
                            }

                            // Share labels across all global statements.
                            if (_globalStatementLabels == null)
                            {
                                Interlocked.CompareExchange(ref _globalStatementLabels, new ScriptLocalScopeBinder.Labels(scriptInitializer, (CompilationUnitSyntax)parent), null);
                            }

                            return MethodBodySemanticModel.Create(
                                this.Compilation,
                                scriptInitializer,
                                new ScriptLocalScopeBinder(_globalStatementLabels, outer),
                                node);
                        }
                    }
                    break;

                case SyntaxKind.BaseConstructorInitializer:
                case SyntaxKind.ThisConstructorInitializer:
                    {
                        var constructorDecl = (ConstructorDeclarationSyntax)node.Parent;
                        var constructorSymbol = (SourceMethodSymbol)GetDeclaredSymbol(constructorDecl);
                        if ((object)constructorSymbol == null)
                            return null;

                        // insert an extra binder to perform constructor initialization checks
                        // Handle scoping for possible pattern variables declared in the initializer
                        Binder initializerBinder = outer.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.ConstructorInitializer, constructorSymbol);
                        ArgumentListSyntax argumentList = ((ConstructorInitializerSyntax)node).ArgumentList;

                        if (argumentList != null)
                        {
                            initializerBinder = new ExecutableCodeBinder(argumentList, constructorSymbol, initializerBinder);
                        }

                        return InitializerSemanticModel.Create(
                            this.Compilation,
                            (ConstructorInitializerSyntax)node,
                            constructorSymbol,
                            initializerBinder);
                    }

                case SyntaxKind.Attribute:
                    {
                        var attribute = (AttributeSyntax)node;
                        AliasSymbol aliasOpt;
                        DiagnosticBag discarded = DiagnosticBag.GetInstance();
                        var attributeType = (NamedTypeSymbol)outer.BindType(attribute.Name, discarded, out aliasOpt);
                        discarded.Free();

                        return AttributeSemanticModel.Create(
                            _compilation,
                            attribute,
                            attributeType,
                            aliasOpt,
                            outer.WithAdditionalFlags(BinderFlags.AttributeArgument));
                    }
            }

            return null;
        }
Example #45
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
            ImmutableArray<ImmutableArray<FieldInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
            bool generateDebugInfo, out ConsList<Imports> firstDebugImports)
        {
            Debug.Assert((object)scriptCtor != null);

            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray<FieldInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder 
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.Field;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef = initializer.Syntax;
                    Debug.Assert(syntaxRef.SyntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var initializerNode = (CSharpSyntaxNode)syntaxRef.GetSyntax();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxRef.SyntaxTree);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
                    Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (generateDebugInfo && firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportsList;
                    }

                    Binder parentBinder = new ExecutableCodeBinder((CSharpSyntaxNode)syntaxRef.SyntaxTree.GetRoot(), scriptCtor, scriptClassBinder);

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            new LocalScopeBinder(parentBinder).WithAdditionalFlagsAndContainingMemberOrLambda(parentBinder.Flags | BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)initializerNode,
                            diagnostics);
                    }
                    else if (initializerNode.Kind == SyntaxKind.LabeledStatement)
                    {
                        // TODO: labels in interactive
                        var boundStatement = new BoundBadStatement(initializerNode, ImmutableArray<BoundNode>.Empty, true);
                        boundInitializer = new BoundGlobalStatementInitializer(initializerNode, boundStatement);
                    }
                    else
                    {
                        var collisionDetector = new LocalScopeBinder(parentBinder);
                        boundInitializer = BindGlobalStatement(collisionDetector, (StatementSyntax)initializerNode, diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
Example #46
0
        internal override bool TryGetSpeculativeSemanticModelCore(SyntaxTreeSemanticModel parentModel, int position, ArrowExpressionClauseSyntax expressionBody, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var binder = this.GetEnclosingBinder(position);
            if (binder == null)
            {
                speculativeModel = null;
                return false;
            }

            var methodSymbol = (MethodSymbol)this.MemberSymbol;
            binder = new ExecutableCodeBinder(expressionBody, methodSymbol, binder);

            speculativeModel = CreateSpeculative(parentModel, methodSymbol, expressionBody, binder, position);
            return true;
        }
        /// <summary>
        /// Creates a SemanticModel that creates and owns the ExecutableCodeBinder for the method of which it is a model.
        /// </summary>
        internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax)
        {
            var executableCodeBinder = new ExecutableCodeBinder(syntax, owner, rootBinder);

            return(new MethodBodySemanticModel(compilation, owner, executableCodeBinder, syntax));
        }
Example #48
0
        private bool GetSpeculativeSemanticModelForMethodBody(SyntaxTreeSemanticModel parentModel, int position, BlockSyntax body, out SemanticModel speculativeModel)
        {
            position = CheckAndAdjustPosition(position);

            var methodSymbol = (MethodSymbol)this.MemberSymbol;

            // Strip off ExecutableCodeBinder (see ctor).
            Binder binder = this.RootBinder;

            do
            {
                if (binder is ExecutableCodeBinder)
                {
                    binder = binder.Next;
                    break;
                }

                binder = binder.Next;
            }
            while (binder != null);

            Debug.Assert(binder != null);

            var executablebinder = new ExecutableCodeBinder(body, methodSymbol, binder ?? this.RootBinder);
            var blockBinder = executablebinder.GetBinder(body).WithAdditionalFlags(GetSemanticModelBinderFlags());
            speculativeModel = CreateSpeculative(parentModel, methodSymbol, body, blockBinder, position);
            return true;
        }
Example #49
0
 protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder lambdaBodyBinder, DiagnosticBag diagnostics)
 {
     return this.IsExpressionLambda ?
         lambdaBodyBinder.BindExpressionLambdaBody((ExpressionSyntax)this.Body, diagnostics) :
         lambdaBodyBinder.BindBlock((BlockSyntax)this.Body, diagnostics);
 }
        /// <summary>
        /// Creates an AttributeSemanticModel that allows asking semantic questions about an attribute node.
        /// </summary>
        public static AttributeSemanticModel Create(CSharpCompilation compilation, AttributeSyntax syntax, NamedTypeSymbol attributeType, AliasSymbol aliasOpt, Binder rootBinder)
        {
            var executableBinder = new ExecutableCodeBinder(syntax, attributeType, rootBinder);

            return(new AttributeSemanticModel(compilation, syntax, attributeType, aliasOpt, new LocalScopeBinder(executableBinder)));
        }
Example #51
0
        internal CSharpAttributeData GetAttribute(AttributeSyntax node, NamedTypeSymbol boundAttributeType, DiagnosticBag diagnostics)
        {
            var boundAttribute = new ExecutableCodeBinder(node, this.ContainingMemberOrLambda, this).BindAttribute(node, boundAttributeType, diagnostics);

            return GetAttribute(boundAttribute, diagnostics);
        }
Example #52
0
        /// <summary>
        /// In script C#, some field initializers are assignments to fields and others are global
        /// statements.  There are no restrictions on accessing instance members.
        /// </summary>
        private static void BindScriptFieldInitializers(
            CSharpCompilation compilation,
            SynthesizedInteractiveInitializerMethod scriptInitializer,
            ImmutableArray <ImmutableArray <FieldOrPropertyInitializer> > initializers,
            ArrayBuilder <BoundInitializer> boundInitializers,
            DiagnosticBag diagnostics,
            out ImportChain firstDebugImports)
        {
            firstDebugImports = null;

            for (int i = 0; i < initializers.Length; i++)
            {
                ImmutableArray <FieldOrPropertyInitializer> siblingInitializers = initializers[i];

                // All sibling initializers share the same parent node and tree so we can reuse the binder
                // factory across siblings.  Unfortunately, we cannot reuse the binder itself, because
                // individual fields might have their own binders (e.g. because of being declared unsafe).
                BinderFactory binderFactory = null;
                // Label instances must be shared across all global statements.
                ScriptLocalScopeBinder.Labels labels = null;

                for (int j = 0; j < siblingInitializers.Length; j++)
                {
                    var initializer = siblingInitializers[j];
                    var fieldSymbol = initializer.FieldOpt;

                    if ((object)fieldSymbol != null && fieldSymbol.IsConst)
                    {
                        // Constants do not need field initializers.
                        continue;
                    }

                    var syntaxRef  = initializer.Syntax;
                    var syntaxTree = syntaxRef.SyntaxTree;
                    Debug.Assert(syntaxTree.Options.Kind != SourceCodeKind.Regular);

                    var syntax     = (CSharpSyntaxNode)syntaxRef.GetSyntax();
                    var syntaxRoot = syntaxTree.GetCompilationUnitRoot();

                    if (binderFactory == null)
                    {
                        binderFactory = compilation.GetBinderFactory(syntaxTree);
                        labels        = new ScriptLocalScopeBinder.Labels(scriptInitializer, syntaxRoot);
                    }

                    Binder scriptClassBinder = binderFactory.GetBinder(syntax);
                    Debug.Assert(((NamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);

                    if (firstDebugImports == null)
                    {
                        firstDebugImports = scriptClassBinder.ImportChain;
                    }

                    Binder parentBinder = new ExecutableCodeBinder(
                        syntaxRoot,
                        scriptInitializer,
                        new ScriptLocalScopeBinder(labels, scriptClassBinder));

                    BoundInitializer boundInitializer;
                    if ((object)fieldSymbol != null)
                    {
                        boundInitializer = BindFieldInitializer(
                            parentBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.FieldInitializer, fieldSymbol),
                            fieldSymbol,
                            (EqualsValueClauseSyntax)syntax,
                            diagnostics);
                    }
                    else
                    {
                        boundInitializer = BindGlobalStatement(
                            parentBinder,
                            scriptInitializer,
                            (StatementSyntax)syntax,
                            diagnostics,
                            isLast: i == initializers.Length - 1 && j == siblingInitializers.Length - 1);
                    }

                    boundInitializers.Add(boundInitializer);
                }
            }
        }
 /// <summary>
 /// Creates a SemanticModel that creates and owns the ExecutableCodeBinder for the method of which it is a model.
 /// </summary>
 internal static MethodBodySemanticModel Create(CSharpCompilation compilation, MethodSymbol owner, Binder rootBinder, CSharpSyntaxNode syntax)
 {
     var executableCodeBinder = new ExecutableCodeBinder(syntax, owner, rootBinder);
     return new MethodBodySemanticModel(compilation, owner, executableCodeBinder, syntax);
 }
Example #54
0
        private BoundLambda ReallyBind(NamedTypeSymbol delegateType)
        {
            var     invokeMethod = DelegateInvokeMethod(delegateType);
            RefKind refKind;
            var     returnType = DelegateReturnType(invokeMethod, out refKind);

            LambdaSymbol lambdaSymbol;
            Binder       lambdaBodyBinder;
            BoundBlock   block;

            var diagnostics = DiagnosticBag.GetInstance();

            // when binding for real (not for return inference), there is still
            // a good chance that we could reuse a body of a lambda previously bound for
            // return type inference.
            MethodSymbol cacheKey = GetCacheKey(delegateType);

            BoundLambda returnInferenceLambda;

            if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType && returnInferenceLambda.Symbol.ReturnType == returnType)
            {
                lambdaSymbol = returnInferenceLambda.Symbol;
                Debug.Assert(lambdaSymbol.RefKind == refKind);

                lambdaBodyBinder = returnInferenceLambda.Binder;
                block            = returnInferenceLambda.Body;
                diagnostics.AddRange(returnInferenceLambda.Diagnostics);

                goto haveLambdaBodyAndBinders;
            }

            var parameters = DelegateParameters(invokeMethod);

            lambdaSymbol = new LambdaSymbol(
                binder.Compilation,
                binder.ContainingMemberOrLambda,
                _unboundLambda,
                parameters,
                refKind,
                returnType);
            lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            block            = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics);

            ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics);
            ValidateUnsafeParameters(diagnostics, parameters);

haveLambdaBodyAndBinders:

            bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics);

            if (reachableEndpoint)
            {
                if (DelegateNeedsReturn(invokeMethod))
                {
                    // Not all code paths return a value in {0} of type '{1}'
                    diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.Locations[0], this.MessageID.Localize(), delegateType);
                }
                else
                {
                    block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol);
                }
            }

            if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics))
            {
                if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type.
                    returnType.SpecialType != SpecialType.System_Void &&
                    !returnType.IsNonGenericTaskType(binder.Compilation) &&
                    !returnType.IsGenericTaskType(binder.Compilation))
                {
                    // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task&lt;T&gt;, none of which are convertible to '{1}'.
                    diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.Locations[0], lambdaSymbol.MessageID.Localize(), delegateType);
                }
            }

            if (IsAsync)
            {
                Debug.Assert(lambdaSymbol.IsAsync);
                SourceMemberMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.Locations[0]);
            }

            // This is an attempt to get a repro for https://devdiv.visualstudio.com/DevDiv/_workitems?id=278481
            if ((object)returnType != null && returnType.SpecialType != SpecialType.System_Void &&
                !block.HasErrors && !diagnostics.HasAnyResolvedErrors() && block.Statements.Length > 0)
            {
                BoundStatement first = block.Statements[0];
                if (first.Kind == BoundKind.ReturnStatement)
                {
                    var returnStmt = (BoundReturnStatement)first;
                    if (returnStmt.ExpressionOpt != null && (object)returnStmt.ExpressionOpt.Type == null)
                    {
                        throw ExceptionUtilities.Unreachable;
                    }
                }
            }

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false)
            {
                WasCompilerGenerated = _unboundLambda.WasCompilerGenerated
            };

            return(result);
        }
Example #55
0
        private BoundLambda ReallyInferReturnType(NamedTypeSymbol delegateType)
        {
            var diagnostics = DiagnosticBag.GetInstance();
            var parameters = DelegateParameters(delegateType);
            var lambdaSymbol = new LambdaSymbol(binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, parameters, returnType: null);
            Binder lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder));
            var block = BindLambdaBody(lambdaSymbol, ref lambdaBodyBinder, diagnostics);

            var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: true)
            { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated };

            HashSet<DiagnosticInfo> useSiteDiagnostics = null; // TODO: figure out if this should be somehow merged into BoundLambda.Diagnostics.
            lambdaSymbol.SetInferredReturnType(result.InferredReturnType(ref useSiteDiagnostics) ??
                                                new ExtendedErrorTypeSymbol(binder.Compilation, string.Empty, 0, null));

            return result;
        }
Example #56
0
 protected abstract BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, ExecutableCodeBinder binder, DiagnosticBag diagnostics);