Example #1
0
        // basesBeingResolved is only used to break circular references.
        internal NamespaceOrTypeSymbol GetAliasTarget(ConsList <TypeSymbol>?basesBeingResolved)
        {
            if (!_state.HasComplete(CompletionPart.AliasTarget))
            {
                // the target is not yet bound. If it is an ordinary alias, bind the target
                // symbol. If it is an extern alias then find the target in the list of metadata references.
                var newDiagnostics = BindingDiagnosticBag.GetInstance();

                NamespaceOrTypeSymbol symbol = this.IsExtern ?
                                               ResolveExternAliasTarget(newDiagnostics) :
                                               ResolveAliasTarget(_aliasTargetName, newDiagnostics, basesBeingResolved);

                if ((object?)Interlocked.CompareExchange(ref _aliasTarget, symbol, null) == null)
                {
                    // Note: It's important that we don't call newDiagnosticsToReadOnlyAndFree here. That call
                    // can force the prompt evaluation of lazy initialized diagnostics.  That in turn can
                    // call back into GetAliasTarget on the same thread resulting in a dead lock scenario.
                    bool won = Interlocked.Exchange(ref _aliasTargetDiagnostics, newDiagnostics) == null;
                    Debug.Assert(won, "Only one thread can win the alias target CompareExchange");

                    _state.NotePartComplete(CompletionPart.AliasTarget);
                    // we do not clear this.aliasTargetName, as another thread might be about to use it for ResolveAliasTarget(...)
                }
                else
                {
                    newDiagnostics.Free();
                    // Wait for diagnostics to have been reported if another thread resolves the alias
                    _state.SpinWaitComplete(CompletionPart.AliasTarget, default(CancellationToken));
                }
            }

            return(_aliasTarget !);
        }
        internal sealed override ImmutableArray <NamedTypeSymbol> InterfacesNoUseSiteDiagnostics(
            ConsList <TypeSymbol> basesBeingResolved
            )
        {
            if (_lazyInterfaces.IsDefault)
            {
                if (
                    basesBeingResolved != null &&
                    basesBeingResolved.ContainsReference(this.OriginalDefinition)
                    )
                {
                    return(ImmutableArray <NamedTypeSymbol> .Empty);
                }

                var diagnostics       = BindingDiagnosticBag.GetInstance();
                var acyclicInterfaces = MakeAcyclicInterfaces(basesBeingResolved, diagnostics);
                if (
                    ImmutableInterlocked.InterlockedCompareExchange(
                        ref _lazyInterfaces,
                        acyclicInterfaces,
                        default(ImmutableArray <NamedTypeSymbol>)
                        ).IsDefault
                    )
                {
                    AddDeclarationDiagnostics(diagnostics);
                }
                diagnostics.Free();
            }

            return(_lazyInterfaces);
        }
Example #3
0
        internal void ComputeReturnType()
        {
            if (_lazyReturnType is object)
            {
                return;
            }

            var                 diagnostics      = BindingDiagnosticBag.GetInstance(_declarationDiagnostics);
            TypeSyntax          returnTypeSyntax = Syntax.ReturnType;
            TypeWithAnnotations returnType       = _binder.BindType(returnTypeSyntax.SkipRef(), diagnostics);

            var compilation = DeclaringCompilation;

            // Skip some diagnostics when the local function is not associated with a compilation
            // (specifically, local functions nested in expressions in the EE).
            if (compilation is object)
            {
                var location = returnTypeSyntax.Location;
                if (_refKind == RefKind.RefReadOnly)
                {
                    compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: false);
                }

                if (returnType.Type.ContainsNativeInteger())
                {
                    compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: false);
                }

                if (compilation.ShouldEmitNullableAttributes(this) &&
                    returnType.NeedsNullableAttribute())
                {
                    compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: false);
                    // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already
                }
            }

            // span-like types are returnable in general
            if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true))
            {
                // The return type of a method, delegate, or function pointer cannot be '{0}'
                diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type);
            }

            Debug.Assert(_refKind == RefKind.None ||
                         !returnType.IsVoidType() ||
                         returnTypeSyntax.HasErrors);

            lock (_declarationDiagnostics)
            {
                if (_lazyReturnType is object)
                {
                    diagnostics.Free();
                    return;
                }

                _declarationDiagnostics.AddRangeAndFree(diagnostics);
                Interlocked.CompareExchange(ref _lazyReturnType, new TypeWithAnnotations.Boxed(returnType), null);
            }
        }
Example #4
0
        internal override TypeWithAnnotations GetFieldType(ConsList <FieldSymbol> fieldsBeingBound)
        {
            Debug.Assert(fieldsBeingBound != null);

            if (_lazyType != null)
            {
                return(_lazyType.Value);
            }

            var typeSyntax = TypeSyntax;

            var compilation = this.DeclaringCompilation;

            var diagnostics = BindingDiagnosticBag.GetInstance();
            TypeWithAnnotations type;
            bool isVar;

            var binderFactory = compilation.GetBinderFactory(SyntaxTree);
            var binder        = binderFactory.GetBinder(typeSyntax ?? SyntaxNode);

            if (typeSyntax != null)
            {
                type = binder.BindTypeOrVarKeyword(typeSyntax, diagnostics, out isVar);
            }
            else
            {
                // Recursive patterns may omit the type syntax
                isVar = true;
                type  = default;
            }

            Debug.Assert(type.HasType || isVar);

            if (isVar && !fieldsBeingBound.ContainsReference(this))
            {
                InferFieldType(fieldsBeingBound, binder);
                Debug.Assert(_lazyType != null);
            }
            else
            {
                if (isVar)
                {
                    diagnostics.Add(
                        ErrorCode.ERR_RecursivelyTypedVariable,
                        this.ErrorLocation,
                        this
                        );
                    type = TypeWithAnnotations.Create(binder.CreateErrorType("var"));
                }

                SetType(compilation, diagnostics, type);
            }

            diagnostics.Free();
            return(_lazyType.Value);
        }
        protected void LazyMethodChecks()
        {
            if (!state.HasComplete(CompletionPart.FinishMethodChecks))
            {
                // TODO: if this lock ever encloses a potential call to Debugger.NotifyOfCrossThreadDependency,
                // then we should call DebuggerUtilities.CallBeforeAcquiringLock() (see method comment for more
                // details).

                object lockObject = MethodChecksLockObject;
                Debug.Assert(lockObject != null);
                lock (lockObject)
                {
                    if (state.NotePartComplete(CompletionPart.StartMethodChecks))
                    {
                        // By setting StartMethodChecks, we've committed to doing the checks and setting
                        // FinishMethodChecks.  So there is no cancellation supported between one and the other.
                        var diagnostics = BindingDiagnosticBag.GetInstance();
                        try
                        {
                            MethodChecks(diagnostics);
                            AddDeclarationDiagnostics(diagnostics);
                        }
                        finally
                        {
                            state.NotePartComplete(CompletionPart.FinishMethodChecks);
                            diagnostics.Free();
                        }
                    }
                    else
                    {
                        // Either (1) this thread is in the process of completing the method,
                        // or (2) some other thread has beat us to the punch and completed the method.
                        // We can distinguish the two cases here by checking for the FinishMethodChecks
                        // part to be complete, which would only occur if another thread completed this
                        // method.
                        //
                        // The other case, in which this thread is in the process of completing the method,
                        // requires that we return here even though the checks are not complete.  That's because
                        // methods are processed by first populating the return type and parameters by binding
                        // the syntax from source.  Those values are visible to the same thread for the purpose
                        // of computing which methods are implemented and overridden.  But then those values
                        // may be rewritten (by the same thread) to copy down custom modifiers.  In order to
                        // allow the same thread to see the return type and parameters from the syntax (though
                        // they do not yet take on their final values), we return here.

                        // Due to the fact that LazyMethodChecks is potentially reentrant, we must use a
                        // reentrant lock to avoid deadlock and cannot assert that at this point method checks
                        // have completed (state.HasComplete(CompletionPart.FinishMethodChecks)).
                    }
                }
            }
        }
Example #6
0
        private void ComputeParameters()
        {
            if (_lazyParameters != null)
            {
                return;
            }

            SyntaxToken arglistToken;
            var         diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics);

            var parameters = ParameterHelpers.MakeParameters(
                _binder,
                this,
                this.Syntax.ParameterList,
                arglistToken: out arglistToken,
                allowRefOrOut: true,
                allowThis: true,
                addRefReadOnlyModifier: false,
                diagnostics: diagnostics);

            var compilation = DeclaringCompilation;

            ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false);
            ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, parameters, diagnostics, modifyCompilation: false);
            ParameterHelpers.EnsureNullableAttributeExists(compilation, this, parameters, diagnostics, modifyCompilation: false);
            foreach (var parameter in parameters)
            {
                ParameterHelpers.ReportParameterNullCheckingErrors(diagnostics.DiagnosticBag, parameter);
            }
            // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already

            var isVararg = arglistToken.Kind() == SyntaxKind.ArgListKeyword;

            if (isVararg)
            {
                diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, arglistToken.GetLocation());
            }

            lock (_declarationDiagnostics)
            {
                if (_lazyParameters != null)
                {
                    diagnostics.Free();
                    return;
                }

                _declarationDiagnostics.AddRangeAndFree(diagnostics);
                _lazyIsVarArg   = isVararg;
                _lazyParameters = parameters;
            }
        }
        internal Tuple <NamedTypeSymbol, ImmutableArray <NamedTypeSymbol> > GetDeclaredBases(ConsList <TypeSymbol> basesBeingResolved)
        {
            if (ReferenceEquals(_lazyDeclaredBases, null))
            {
                var diagnostics = BindingDiagnosticBag.GetInstance();
                if (Interlocked.CompareExchange(ref _lazyDeclaredBases, MakeDeclaredBases(basesBeingResolved, diagnostics), null) == null)
                {
                    AddDeclarationDiagnostics(diagnostics);
                }
                diagnostics.Free();
            }

            return(_lazyDeclaredBases);
        }
Example #8
0
            private void MakeConstantTuple(LocalSymbol inProgress, BoundExpression boundInitValue)
            {
                if (this.IsConst && _constantTuple == null)
                {
                    var      value = Microsoft.CodeAnalysis.ConstantValue.Bad;
                    Location initValueNodeLocation = _initializer.Value.Location;
                    var      diagnostics           = BindingDiagnosticBag.GetInstance();
                    Debug.Assert(inProgress != this);
                    var type = this.Type;
                    if (boundInitValue == null)
                    {
                        var inProgressBinder = new LocalInProgressBinder(this, this._initializerBinder);
                        boundInitValue = inProgressBinder.BindVariableOrAutoPropInitializerValue(_initializer, this.RefKind, type, diagnostics);
                    }

                    value = ConstantValueUtils.GetAndValidateConstantValue(boundInitValue, this, type, initValueNodeLocation, diagnostics);
                    Interlocked.CompareExchange(ref _constantTuple, new EvaluatedConstant(value, diagnostics.ToReadOnlyAndFree()), null);
                }
            }
Example #9
0
        internal void GetDeclarationDiagnostics(BindingDiagnosticBag addTo)
        {
            // Force complete type parameters
            foreach (var typeParam in _typeParameters)
            {
                typeParam.ForceComplete(null, default(CancellationToken));
            }

            // force lazy init
            ComputeParameters();

            foreach (var p in _lazyParameters)
            {
                // Force complete parameters to retrieve all diagnostics
                p.ForceComplete(null, default(CancellationToken));
            }

            ComputeReturnType();

            GetAttributes();
            GetReturnTypeAttributes();

            AsyncMethodChecks(_declarationDiagnostics);

            addTo.AddRange(_declarationDiagnostics, allowMismatchInDependencyAccumulation: true);

            var diagnostics = BindingDiagnosticBag.GetInstance(
                withDiagnostics: false,
                withDependencies: addTo.AccumulatesDependencies
                );

            if (
                IsEntryPointCandidate &&
                !IsGenericMethod &&
                ContainingSymbol is SynthesizedSimpleProgramEntryPointSymbol &&
                DeclaringCompilation.HasEntryPointSignature(this, diagnostics).IsCandidate
                )
            {
                addTo.Add(ErrorCode.WRN_MainIgnored, Syntax.Identifier.GetLocation(), this);
            }

            addTo.AddRangeAndFree(diagnostics);
        }
Example #10
0
        protected sealed override void LazyAsyncMethodChecks(CancellationToken cancellationToken)
        {
            Debug.Assert(this.IsPartial == state.HasComplete(CompletionPart.FinishMethodChecks),
                         "Partial methods complete method checks during construction.  " +
                         "Other methods can't complete method checks before executing this method.");

            if (!this.IsAsync)
            {
                CompleteAsyncMethodChecks(diagnosticsOpt: null, cancellationToken: cancellationToken);
                return;
            }

            var diagnostics = BindingDiagnosticBag.GetInstance();

            AsyncMethodChecks(diagnostics);

            CompleteAsyncMethodChecks(diagnostics, cancellationToken);
            diagnostics.Free();
        }
Example #11
0
        internal ImmutableArray <Diagnostic> FlowDiagnostics(CSharpCompilation compilation)
        {
            var flowDiagnostics = BindingDiagnosticBag.GetInstance();

            foreach (var method in AllMethods(compilation.SourceModule.GlobalNamespace))
            {
                var sourceSymbol = method as SourceMemberMethodSymbol;
                if (sourceSymbol == null)
                {
                    continue;
                }

                var compilationState = new TypeCompilationState(sourceSymbol.ContainingType, compilation, null);
                var boundBody        = MethodCompiler.BindMethodBody(sourceSymbol, compilationState, new BindingDiagnosticBag(new DiagnosticBag()));
                if (boundBody != null)
                {
                    FlowAnalysisPass.Rewrite(sourceSymbol, boundBody, compilationState, flowDiagnostics, hasTrailingExpression: false, originalBodyNested: false);
                }
            }

            return(flowDiagnostics.ToReadOnlyAndFree().Diagnostics);
        }
Example #12
0
        private TypeParameterBounds GetBounds(ConsList <TypeParameterSymbol> inProgress)
        {
            Debug.Assert(!inProgress.ContainsReference(this));
            Debug.Assert(!inProgress.Any() || ReferenceEquals(inProgress.Head.ContainingSymbol, this.ContainingSymbol));

            if (!_lazyBounds.IsSet())
            {
                var diagnostics = BindingDiagnosticBag.GetInstance();
                var bounds      = this.ResolveBounds(inProgress, diagnostics);

                if (ReferenceEquals(Interlocked.CompareExchange(ref _lazyBounds, bounds, TypeParameterBounds.Unset), TypeParameterBounds.Unset))
                {
                    this.CheckConstraintTypeConstraints(diagnostics);
                    this.CheckUnmanagedConstraint(diagnostics);
                    this.EnsureAttributesFromConstraints(diagnostics);
                    this.AddDeclarationDiagnostics(diagnostics);
                    _state.NotePartComplete(CompletionPart.TypeParameterConstraints);
                }

                diagnostics.Free();
            }

            return(_lazyBounds);
        }
Example #13
0
        internal override void ForceComplete(SourceLocation locationOpt, CancellationToken cancellationToken)
        {
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();
                var incompletePart = _state.NextIncompletePart;
                switch (incompletePart)
                {
                case CompletionPart.Attributes:
                    GetAttributes();
                    break;

                case CompletionPart.StartValidatingReferencedAssemblies:
                {
                    BindingDiagnosticBag diagnostics = null;

                    if (AnyReferencedAssembliesAreLinked)
                    {
                        diagnostics = BindingDiagnosticBag.GetInstance();
                        ValidateLinkedAssemblies(diagnostics, cancellationToken);
                    }

                    if (_state.NotePartComplete(CompletionPart.StartValidatingReferencedAssemblies))
                    {
                        if (diagnostics != null)
                        {
                            _assemblySymbol.AddDeclarationDiagnostics(diagnostics);
                        }

                        _state.NotePartComplete(CompletionPart.FinishValidatingReferencedAssemblies);
                    }

                    if (diagnostics != null)
                    {
                        diagnostics.Free();
                    }
                }
                break;

                case CompletionPart.FinishValidatingReferencedAssemblies:
                    // some other thread has started validating references (otherwise we would be in the case above) so
                    // we just wait for it to both finish and report the diagnostics.
                    Debug.Assert(_state.HasComplete(CompletionPart.StartValidatingReferencedAssemblies));
                    _state.SpinWaitComplete(CompletionPart.FinishValidatingReferencedAssemblies, cancellationToken);
                    break;

                case CompletionPart.MembersCompleted:
                    this.GlobalNamespace.ForceComplete(locationOpt, cancellationToken);

                    if (this.GlobalNamespace.HasComplete(CompletionPart.MembersCompleted))
                    {
                        _state.NotePartComplete(CompletionPart.MembersCompleted);
                    }
                    else
                    {
                        Debug.Assert(locationOpt != null, "If no location was specified, then the namespace members should be completed");
                        return;
                    }

                    break;

                case CompletionPart.None:
                    return;

                default:
                    // any other values are completion parts intended for other kinds of symbols
                    _state.NotePartComplete(incompletePart);
                    break;
                }

                _state.SpinWaitComplete(incompletePart, cancellationToken);
            }
        }
Example #14
0
        internal SourceFieldLikeEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, BindingDiagnosticBag diagnostics)
            : base(containingType, declaratorSyntax, modifiers, isFieldLike: true, interfaceSpecifierSyntaxOpt: null,
                   nameTokenSyntax: declaratorSyntax.Identifier, diagnostics: diagnostics)
        {
            Debug.Assert(declaratorSyntax.Parent is object);

            _name = declaratorSyntax.Identifier.ValueText;

            var declaratorDiagnostics = BindingDiagnosticBag.GetInstance();
            var declarationSyntax     = (VariableDeclarationSyntax)declaratorSyntax.Parent;

            _type = BindEventType(binder, declarationSyntax.Type, declaratorDiagnostics);

            // The runtime will not treat the accessors of this event as overrides or implementations
            // of those of another event unless both the signatures and the custom modifiers match.
            // Hence, in the case of overrides and *explicit* implementations (not possible for field-like
            // events), we need to copy the custom modifiers that are in the signatures of the
            // overridden/implemented event accessors. (From source, we know that there can only be one
            // overridden/implemented event, so there are no conflicts.)  This is unnecessary for implicit
            // implementations because, if the custom modifiers don't match, we'll insert bridge methods
            // for the accessors (explicit implementations that delegate to the implicit implementations)
            // with the correct custom modifiers (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation).

            // If this event is an override, we may need to copy custom modifiers from
            // the overridden event (so that the runtime will recognize it as an override).
            // We check for this case here, while we can still modify the parameters and
            // return type without losing the appearance of immutability.
            if (this.IsOverride)
            {
                EventSymbol?overriddenEvent = this.OverriddenEvent;
                if ((object?)overriddenEvent != null)
                {
                    CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly);
                }
            }

            bool hasInitializer  = declaratorSyntax.Initializer != null;
            bool inInterfaceType = containingType.IsInterfaceType();

            if (hasInitializer)
            {
                if (inInterfaceType && !this.IsStatic)
                {
                    diagnostics.Add(ErrorCode.ERR_InterfaceEventInitializer, this.Locations[0], this);
                }
                else if (this.IsAbstract)
                {
                    diagnostics.Add(ErrorCode.ERR_AbstractEventInitializer, this.Locations[0], this);
                }
                else if (this.IsExtern)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternEventInitializer, this.Locations[0], this);
                }
            }

            // NOTE: if there's an initializer in source, we'd better create a backing field, regardless of
            // whether or not the initializer is legal.
            if (hasInitializer || !(this.IsExtern || this.IsAbstract))
            {
                AssociatedEventField = MakeAssociatedField(declaratorSyntax);
                // Don't initialize this.type - we'll just use the type of the field (which is lazy and handles var)
            }

            if (!IsStatic && ContainingType.IsReadOnly)
            {
                diagnostics.Add(ErrorCode.ERR_FieldlikeEventsInRoStruct, this.Locations[0]);
            }

            if (inInterfaceType)
            {
                if ((IsAbstract || IsVirtual) && IsStatic)
                {
                    if (!ContainingAssembly.RuntimeSupportsStaticAbstractMembersInInterfaces)
                    {
                        diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, this.Locations[0]);
                    }
                }
                else if (this.IsExtern || this.IsStatic)
                {
                    if (!ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation)
                    {
                        diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, this.Locations[0]);
                    }
                }
                else if (!this.IsAbstract)
                {
                    diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this);
                }
            }

            // Accessors will assume that Type is available.
            _addMethod    = new SynthesizedEventAccessorSymbol(this, isAdder: true);
            _removeMethod = new SynthesizedEventAccessorSymbol(this, isAdder: false);

            if (declarationSyntax.Variables[0] == declaratorSyntax)
            {
                // Don't report these diagnostics for every declarator in this declaration.
                diagnostics.AddRange(declaratorDiagnostics);
            }

            declaratorDiagnostics.Free();
        }