Beispiel #1
0
        /// <summary>
        /// Bind and return a single type parameter constraint clause along with syntax nodes corresponding to type constraints.
        /// </summary>
        private (TypeParameterConstraintClause, ArrayBuilder <TypeConstraintSyntax>?) BindTypeParameterConstraints(TypeParameterSyntax typeParameterSyntax, TypeParameterConstraintClauseSyntax constraintClauseSyntax, bool isForOverride, BindingDiagnosticBag diagnostics)
        {
            var constraints = TypeParameterConstraintKind.None;
            ArrayBuilder <TypeWithAnnotations>? constraintTypes = null;
            ArrayBuilder <TypeConstraintSyntax>?syntaxBuilder   = null;
            SeparatedSyntaxList <TypeParameterConstraintSyntax> constraintsSyntax = constraintClauseSyntax.Constraints;

            Debug.Assert(!InExecutableBinder); // Cannot eagerly report diagnostics handled by LazyMissingNonNullTypesContextDiagnosticInfo
            bool hasTypeLikeConstraint           = false;
            bool reportedOverrideWithConstraints = false;

            for (int i = 0, n = constraintsSyntax.Count; i < n; i++)
            {
                var syntax = constraintsSyntax[i];
                switch (syntax.Kind())
                {
                case SyntaxKind.ClassConstraint:
                    hasTypeLikeConstraint = true;

                    if (i != 0)
                    {
                        if (!reportedOverrideWithConstraints)
                        {
                            reportTypeConstraintsMustBeUniqueAndFirst(syntax, diagnostics);
                        }

                        if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0)
                        {
                            continue;
                        }
                    }

                    var         constraintSyntax = (ClassOrStructConstraintSyntax)syntax;
                    SyntaxToken questionToken    = constraintSyntax.QuestionToken;
                    if (questionToken.IsKind(SyntaxKind.QuestionToken))
                    {
                        constraints |= TypeParameterConstraintKind.NullableReferenceType;

                        if (isForOverride)
                        {
                            reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics);
                        }
                        else if (diagnostics.DiagnosticBag is DiagnosticBag diagnosticBag)
                        {
                            LazyMissingNonNullTypesContextDiagnosticInfo.ReportNullableReferenceTypesIfNeeded(
                                AreNullableAnnotationsEnabled(questionToken),
                                IsGeneratedCode(questionToken),
                                questionToken.GetLocation(),
                                diagnosticBag);
                        }
                    }
                    else if (isForOverride || AreNullableAnnotationsEnabled(constraintSyntax.ClassOrStructKeyword))
                    {
                        constraints |= TypeParameterConstraintKind.NotNullableReferenceType;
                    }
                    else
                    {
                        constraints |= TypeParameterConstraintKind.ReferenceType;
                    }

                    continue;

                case SyntaxKind.StructConstraint:
                    hasTypeLikeConstraint = true;

                    if (i != 0)
                    {
                        if (!reportedOverrideWithConstraints)
                        {
                            reportTypeConstraintsMustBeUniqueAndFirst(syntax, diagnostics);
                        }

                        if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0)
                        {
                            continue;
                        }
                    }

                    constraints |= TypeParameterConstraintKind.ValueType;
                    continue;

                case SyntaxKind.ConstructorConstraint:
                    if (isForOverride)
                    {
                        reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics);
                        continue;
                    }

                    if ((constraints & TypeParameterConstraintKind.ValueType) != 0)
                    {
                        diagnostics.Add(ErrorCode.ERR_NewBoundWithVal, syntax.GetFirstToken().GetLocation());
                    }
                    if ((constraints & TypeParameterConstraintKind.Unmanaged) != 0)
                    {
                        diagnostics.Add(ErrorCode.ERR_NewBoundWithUnmanaged, syntax.GetFirstToken().GetLocation());
                    }

                    if (i != n - 1)
                    {
                        diagnostics.Add(ErrorCode.ERR_NewBoundMustBeLast, syntax.GetFirstToken().GetLocation());
                    }

                    constraints |= TypeParameterConstraintKind.Constructor;
                    continue;

                case SyntaxKind.DefaultConstraint:
                    if (!isForOverride)
                    {
                        diagnostics.Add(ErrorCode.ERR_DefaultConstraintOverrideOnly, syntax.GetLocation());
                    }

                    if (i != 0)
                    {
                        if (!reportedOverrideWithConstraints)
                        {
                            reportTypeConstraintsMustBeUniqueAndFirst(syntax, diagnostics);
                        }

                        if (isForOverride && (constraints & (TypeParameterConstraintKind.ValueType | TypeParameterConstraintKind.ReferenceType)) != 0)
                        {
                            continue;
                        }
                    }

                    constraints |= TypeParameterConstraintKind.Default;
                    continue;

                case SyntaxKind.TypeConstraint:
                    if (isForOverride)
                    {
                        reportOverrideWithConstraints(ref reportedOverrideWithConstraints, syntax, diagnostics);
                    }
                    else
                    {
                        hasTypeLikeConstraint = true;

                        if (constraintTypes == null)
                        {
                            constraintTypes = ArrayBuilder <TypeWithAnnotations> .GetInstance();

                            syntaxBuilder = ArrayBuilder <TypeConstraintSyntax> .GetInstance();
                        }

                        var typeConstraintSyntax = (TypeConstraintSyntax)syntax;
                        var typeSyntax           = typeConstraintSyntax.Type;

                        var type = BindTypeOrConstraintKeyword(typeSyntax, diagnostics, out ConstraintContextualKeyword keyword);

                        switch (keyword)
                        {
                        case ConstraintContextualKeyword.Unmanaged:
                            if (i != 0)
                            {
                                reportTypeConstraintsMustBeUniqueAndFirst(typeSyntax, diagnostics);
                                continue;
                            }

                            // This should produce diagnostics if the types are missing
                            GetWellKnownType(WellKnownType.System_Runtime_InteropServices_UnmanagedType, diagnostics, typeSyntax);
                            GetSpecialType(SpecialType.System_ValueType, diagnostics, typeSyntax);

                            constraints |= TypeParameterConstraintKind.Unmanaged;
                            continue;

                        case ConstraintContextualKeyword.NotNull:
                            if (i != 0)
                            {
                                reportTypeConstraintsMustBeUniqueAndFirst(typeSyntax, diagnostics);
                            }

                            constraints |= TypeParameterConstraintKind.NotNull;
                            continue;

                        case ConstraintContextualKeyword.None:
                            break;

                        default:
                            throw ExceptionUtilities.UnexpectedValue(keyword);
                        }

                        constraintTypes.Add(type);
                        syntaxBuilder !.Add(typeConstraintSyntax);
                    }
                    continue;

                default:
                    throw ExceptionUtilities.UnexpectedValue(syntax.Kind());
                }
            }

            if (!isForOverride && !hasTypeLikeConstraint && !AreNullableAnnotationsEnabled(typeParameterSyntax.Identifier))
            {
                constraints |= TypeParameterConstraintKind.ObliviousNullabilityIfReferenceType;
            }

            Debug.Assert(!isForOverride ||
                         (constraints & (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType)) != (TypeParameterConstraintKind.ReferenceType | TypeParameterConstraintKind.ValueType));

            return(TypeParameterConstraintClause.Create(constraints, constraintTypes?.ToImmutableAndFree() ?? ImmutableArray <TypeWithAnnotations> .Empty), syntaxBuilder);
Beispiel #2
0
        private ImmutableArray <Symbol> BindQualifiedCref(QualifiedCrefSyntax syntax, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            // NOTE: we won't check whether container is an error type - we'll just let BindMemberCref fail
            // and report a blanket diagnostic.
            NamespaceOrTypeSymbol container = BindNamespaceOrTypeSymbolInCref(syntax.Container);

            return(BindMemberCref(syntax.Member, container, out ambiguityWinner, diagnostics));
        }
Beispiel #3
0
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, BindingDiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;

            Debug.Assert((object)accessor != null);

            FieldSymbol field = eventSymbol.AssociatedField;

            Debug.Assert((object)field != null);

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;

            Debug.Assert(fieldType.Name == "EventRegistrationTokenTable");

            MethodSymbol getOrCreateMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable,
                diagnostics,
                syntax: syntax);

            if ((object)getOrCreateMethod == null)
            {
                Debug.Assert(diagnostics.DiagnosticBag is null || diagnostics.HasAnyErrors());
                return(null);
            }

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

            WellKnownMember processHandlerMember = isAddMethod
                ? WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler
                : WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler;

            MethodSymbol processHandlerMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                processHandlerMember,
                diagnostics,
                syntax: syntax);

            if ((object)processHandlerMethod == null)
            {
                Debug.Assert(diagnostics.DiagnosticBag is null || diagnostics.HasAnyErrors());
                return(null);
            }

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

            // _tokenTable
            BoundFieldAccess fieldAccess = new BoundFieldAccess(
                syntax,
                field.IsStatic ? null : new BoundThisReference(syntax, accessor.ThisParameter.Type),
                field,
                constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
            BoundCall getOrCreateCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: getOrCreateMethod,
                arg0: fieldAccess);

            // value
            BoundParameter parameterAccess = new BoundParameter(
                syntax,
                accessor.Parameters[0]);

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value) // or RemoveHandler
            BoundCall processHandlerCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: getOrCreateCall,
                method: processHandlerMethod,
                arg0: parameterAccess);

            if (isAddMethod)
            {
                // {
                //     return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
                // }
                BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, RefKind.None, processHandlerCall);
                return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement));
            }
            else
            {
                // {
                //     EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
                //     return;
                // }
                BoundStatement callStatement   = new BoundExpressionStatement(syntax, processHandlerCall);
                BoundStatement returnStatement = new BoundReturnStatement(syntax, RefKind.None, expressionOpt: null);
                return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement));
            }
        }
Beispiel #4
0
        private ImmutableArray <Symbol> BindCrefInternal(CrefSyntax syntax, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            switch (syntax.Kind())
            {
            case SyntaxKind.TypeCref:
                return(BindTypeCref((TypeCrefSyntax)syntax, out ambiguityWinner, diagnostics));

            case SyntaxKind.QualifiedCref:
                return(BindQualifiedCref((QualifiedCrefSyntax)syntax, out ambiguityWinner, diagnostics));

            case SyntaxKind.NameMemberCref:
            case SyntaxKind.IndexerMemberCref:
            case SyntaxKind.OperatorMemberCref:
            case SyntaxKind.ConversionOperatorMemberCref:
                return(BindMemberCref((MemberCrefSyntax)syntax, containerOpt: null, ambiguityWinner: out ambiguityWinner, diagnostics: diagnostics));

            default:
                throw ExceptionUtilities.UnexpectedValue(syntax.Kind());
            }
        }
Beispiel #5
0
        /// <summary>
        /// Perform lookup (optionally, in a specified container).  If nothing is found and the member name matches the containing type
        /// name, then use the instance constructors of the type instead.  The resulting symbols are sorted since tie-breaking is based
        /// on order and we want cref binding to be repeatable.
        /// </summary>
        /// <remarks>
        /// Never returns null.
        /// </remarks>
        private ImmutableArray <Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol?containerOpt, string memberName, string memberNameText, int arity, bool hasParameterList, BindingDiagnosticBag diagnostics)
        {
            CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
            var result = ComputeSortedCrefMembers(containerOpt, memberName, memberNameText, arity, hasParameterList, syntax, diagnostics, ref useSiteInfo);

            diagnostics.Add(syntax, useSiteInfo);
            return(result);
        }
Beispiel #6
0
        private ImmutableArray <Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            SimpleNameSyntax?nameSyntax = syntax.Name as SimpleNameSyntax;

            int    arity;
            string memberName;
            string memberNameText;

            if (nameSyntax != null)
            {
                arity          = nameSyntax.Arity;
                memberName     = nameSyntax.Identifier.ValueText;
                memberNameText = nameSyntax.Identifier.Text;
            }
            else
            {
                // If the name isn't a SimpleNameSyntax, then we must have a type name followed by a parameter list.
                // Thus, we're looking for a constructor.
                Debug.Assert((object?)containerOpt == null);

                // Could be an error type, but we'll just lookup fail below.
                containerOpt = BindNamespaceOrTypeSymbolInCref(syntax.Name);

                arity      = 0;
                memberName = memberNameText = WellKnownMemberNames.InstanceConstructorName;
            }

            if (string.IsNullOrEmpty(memberName))
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            ImmutableArray <Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText, arity, syntax.Parameters != null, diagnostics);

            if (sortedSymbols.IsEmpty)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            return(ProcessCrefMemberLookupResults(
                       sortedSymbols,
                       arity,
                       syntax,
                       typeArgumentListSyntax: arity == 0 ? null : ((GenericNameSyntax)nameSyntax !).TypeArgumentList,
                       parameterListSyntax: syntax.Parameters,
                       ambiguityWinner: out ambiguityWinner,
                       diagnostics: diagnostics));
        }
Beispiel #7
0
        private ImmutableArray <Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            const int arity = 0;

            ImmutableArray <Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, WellKnownMemberNames.Indexer, memberNameText: WellKnownMemberNames.Indexer, arity, syntax.Parameters != null, diagnostics);

            if (sortedSymbols.IsEmpty)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            // Since only indexers are named WellKnownMemberNames.Indexer.
            Debug.Assert(sortedSymbols.All(SymbolExtensions.IsIndexer));

            // NOTE: guaranteed to be a property, because only indexers are considered.
            return(ProcessCrefMemberLookupResults(
                       sortedSymbols,
                       arity,
                       syntax,
                       typeArgumentListSyntax: null,
                       parameterListSyntax: syntax.Parameters,
                       ambiguityWinner: out ambiguityWinner,
                       diagnostics: diagnostics));
        }
 public override void GenerateAnonymousFunctionConversionError(BindingDiagnosticBag diagnostics, TypeSymbol targetType)
 {
     // TODO: improved diagnostics for query expressions
     base.GenerateAnonymousFunctionConversionError(diagnostics, targetType);
 }
Beispiel #9
0
        /// <remarks>
        /// Don't call this one directly - call one of the helpers.
        /// </remarks>
        private bool ValidateNameConflictsInScope(Symbol?symbol, Location location, string name, BindingDiagnosticBag diagnostics)
        {
            if (string.IsNullOrEmpty(name))
            {
                return(false);
            }

            bool allowShadowing = Compilation.IsFeatureEnabled(MessageID.IDS_FeatureNameShadowingInNestedFunctions);

            for (Binder?binder = this; binder != null; binder = binder.Next)
            {
                // no local scopes enclose members
                if (binder is InContainerBinder)
                {
                    return(false);
                }

                var scope = binder as LocalScopeBinder;
                if (scope?.EnsureSingleDefinition(symbol, name, location, diagnostics) == true)
                {
                    return(true);
                }

                // If shadowing is enabled, avoid checking for conflicts outside of local functions or lambdas.
                if (allowShadowing && binder.IsNestedFunctionBinder)
                {
                    return(false);
                }

                if (binder.IsLastBinderWithinMember())
                {
                    // Declarations within a member do not conflict with declarations outside.
                    return(false);
                }
            }

            return(false);
        }
 protected override BoundBlock CreateBlockFromLambdaExpressionBody(Binder lambdaBodyBinder, BoundExpression expression, BindingDiagnosticBag diagnostics)
 {
     throw ExceptionUtilities.Unreachable;
 }
 protected override BoundBlock BindLambdaBody(LambdaSymbol lambdaSymbol, Binder lambdaBodyBinder, BindingDiagnosticBag diagnostics)
 {
     return(_bodyFactory(lambdaSymbol, lambdaBodyBinder, diagnostics));
 }
Beispiel #12
0
 static void reportTypeConstraintsMustBeUniqueAndFirst(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics)
 {
     diagnostics.Add(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, syntax.GetLocation());
 }
Beispiel #13
0
 static void reportOverrideWithConstraints(ref bool reportedOverrideWithConstraints, TypeParameterConstraintSyntax syntax, BindingDiagnosticBag diagnostics)
 {
     if (!reportedOverrideWithConstraints)
     {
         diagnostics.Add(ErrorCode.ERR_OverrideWithConstraints, syntax.GetLocation());
         reportedOverrideWithConstraints = true;
     }
 }
Beispiel #14
0
        /// <summary>
        /// Return a collection of bound constraint clauses indexed by type parameter
        /// ordinal. All constraint clauses are bound, even if there are multiple constraints
        /// for the same type parameter, or constraints for unrecognized type parameters.
        /// Extra constraints are not included in the returned collection however.
        /// </summary>
        internal ImmutableArray <TypeParameterConstraintClause> BindTypeParameterConstraintClauses(
            Symbol containingSymbol,
            ImmutableArray <TypeParameterSymbol> typeParameters,
            TypeParameterListSyntax typeParameterList,
            SyntaxList <TypeParameterConstraintClauseSyntax> clauses,
            BindingDiagnosticBag diagnostics,
            bool performOnlyCycleSafeValidation,
            bool isForOverride = false)
        {
            Debug.Assert(this.Flags.Includes(BinderFlags.GenericConstraintsClause));
            RoslynDebug.Assert((object)containingSymbol != null);
            Debug.Assert((containingSymbol.Kind == SymbolKind.NamedType) || (containingSymbol.Kind == SymbolKind.Method));
            Debug.Assert(typeParameters.Length > 0);
            Debug.Assert(clauses.Count > 0);

            int n = typeParameters.Length;

            // Create a map from type parameter name to ordinal.
            // No need to report duplicate names since duplicates
            // are reported when the type parameters are bound.
            var names = new Dictionary <string, int>(n, StringOrdinalComparer.Instance);

            foreach (var typeParameter in typeParameters)
            {
                var name = typeParameter.Name;
                if (!names.ContainsKey(name))
                {
                    names.Add(name, names.Count);
                }
            }

            // An array of constraint clauses, one for each type parameter, indexed by ordinal.
            var results = ArrayBuilder <TypeParameterConstraintClause?> .GetInstance(n, fillWithValue : null);

            var syntaxNodes = ArrayBuilder <ArrayBuilder <TypeConstraintSyntax>?> .GetInstance(n, fillWithValue : null);

            // Bind each clause and add to the results.
            foreach (var clause in clauses)
            {
                var name = clause.Name.Identifier.ValueText;
                RoslynDebug.Assert(name is object);
                int ordinal;
                if (names.TryGetValue(name, out ordinal))
                {
                    Debug.Assert(ordinal >= 0);
                    Debug.Assert(ordinal < n);

                    (TypeParameterConstraintClause constraintClause, ArrayBuilder <TypeConstraintSyntax>?typeConstraintNodes) = this.BindTypeParameterConstraints(typeParameterList.Parameters[ordinal], clause, isForOverride, diagnostics);
                    if (results[ordinal] == null)
                    {
                        results[ordinal]     = constraintClause;
                        syntaxNodes[ordinal] = typeConstraintNodes;
                    }
                    else
                    {
                        // "A constraint clause has already been specified for type parameter '{0}'. ..."
                        diagnostics.Add(ErrorCode.ERR_DuplicateConstraintClause, clause.Name.Location, name);
                        typeConstraintNodes?.Free();
                    }
                }
                else
                {
                    // Unrecognized type parameter. Don't bother binding the constraints
                    // (the ": I<U>" in "where U : I<U>") since that will lead to additional
                    // errors ("type or namespace 'U' could not be found") if the type
                    // parameter is referenced in the constraints.

                    // "'{1}' does not define type parameter '{0}'"
                    diagnostics.Add(ErrorCode.ERR_TyVarNotFoundInConstraint, clause.Name.Location, name, containingSymbol.ConstructedFrom());
                }
            }

            // Add default values for type parameters without constraint clauses.
            for (int i = 0; i < n; i++)
            {
                if (results[i] == null)
                {
                    results[i] = GetDefaultTypeParameterConstraintClause(typeParameterList.Parameters[i], isForOverride);
                }
            }

            RemoveInvalidConstraints(typeParameters, results !, syntaxNodes, performOnlyCycleSafeValidation, diagnostics);

            foreach (var typeConstraintsSyntaxes in syntaxNodes)
            {
                typeConstraintsSyntaxes?.Free();
            }

            syntaxNodes.Free();

            return(results.ToImmutableAndFree() !);
        }
Beispiel #15
0
        // An anonymous function can be of the form:
        //
        // delegate { }              (missing parameter list)
        // delegate (int x) { }      (typed parameter list)
        // x => ...                  (type-inferred parameter list)
        // (x) => ...                (type-inferred parameter list)
        // (x, y) => ...             (type-inferred parameter list)
        // ( ) => ...                (typed parameter list)
        // (ref int x) => ...        (typed parameter list)
        // (int x, out int y) => ... (typed parameter list)
        //
        // and so on. We want to canonicalize these various ways of writing the signatures.
        //
        // If we are in the first case then the name, modifier and type arrays are all null.
        // If we have a parameter list then the names array is non-null, but possibly empty.
        // If we have types then the types array is non-null, but possibly empty.
        // If we have no modifiers then the modifiers array is null; if we have any modifiers
        // then the modifiers array is non-null and not empty.

        private UnboundLambda AnalyzeAnonymousFunction(
            AnonymousFunctionExpressionSyntax syntax, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(syntax != null);
            Debug.Assert(syntax.IsAnonymousFunction());

            var names      = default(ImmutableArray <string>);
            var refKinds   = default(ImmutableArray <RefKind>);
            var types      = default(ImmutableArray <TypeWithAnnotations>);
            var attributes = default(ImmutableArray <SyntaxList <AttributeListSyntax> >);

            var namesBuilder = ArrayBuilder <string> .GetInstance();

            ImmutableArray <bool> discardsOpt = default;
            SeparatedSyntaxList <ParameterSyntax>?parameterSyntaxList = null;
            bool hasSignature;

            if (syntax is LambdaExpressionSyntax lambdaSyntax)
            {
                checkAttributes(syntax, lambdaSyntax.AttributeLists, diagnostics);
            }

            switch (syntax.Kind())
            {
            default:
            case SyntaxKind.SimpleLambdaExpression:
                // x => ...
                hasSignature = true;
                var simple = (SimpleLambdaExpressionSyntax)syntax;
                namesBuilder.Add(simple.Parameter.Identifier.ValueText);
                break;

            case SyntaxKind.ParenthesizedLambdaExpression:
                // (T x, U y) => ...
                // (x, y) => ...
                hasSignature = true;
                var paren = (ParenthesizedLambdaExpressionSyntax)syntax;
                parameterSyntaxList = paren.ParameterList.Parameters;
                CheckParenthesizedLambdaParameters(parameterSyntaxList.Value, diagnostics);
                break;

            case SyntaxKind.AnonymousMethodExpression:
                // delegate (int x) { }
                // delegate { }
                var anon = (AnonymousMethodExpressionSyntax)syntax;
                hasSignature = anon.ParameterList != null;
                if (hasSignature)
                {
                    parameterSyntaxList = anon.ParameterList !.Parameters;
                }
                break;
            }

            var isAsync  = syntax.Modifiers.Any(SyntaxKind.AsyncKeyword);
            var isStatic = syntax.Modifiers.Any(SyntaxKind.StaticKeyword);

            if (parameterSyntaxList != null)
            {
                var hasExplicitlyTypedParameterList = true;
                var allValue = true;

                var typesBuilder = ArrayBuilder <TypeWithAnnotations> .GetInstance();

                var refKindsBuilder = ArrayBuilder <RefKind> .GetInstance();

                var attributesBuilder = ArrayBuilder <SyntaxList <AttributeListSyntax> > .GetInstance();

                // In the batch compiler case we probably should have given a syntax error if the
                // user did something like (int x, y)=>x+y -- but in the IDE scenario we might be in
                // this case. If we are, then rather than try to make partial deductions from the
                // typed formal parameters, simply bail out and treat it as an untyped lambda.
                //
                // However, we still want to give errors on every bad type in the list, even if one
                // is missing.

                int underscoresCount = 0;
                foreach (var p in parameterSyntaxList.Value)
                {
                    if (p.Identifier.IsUnderscoreToken())
                    {
                        underscoresCount++;
                    }

                    checkAttributes(syntax, p.AttributeLists, diagnostics);

                    if (p.Default != null)
                    {
                        Error(diagnostics, ErrorCode.ERR_DefaultValueNotAllowed, p.Default.EqualsToken);
                    }

                    if (p.IsArgList)
                    {
                        Error(diagnostics, ErrorCode.ERR_IllegalVarArgs, p);
                        continue;
                    }

                    var typeSyntax           = p.Type;
                    TypeWithAnnotations type = default;
                    var refKind = RefKind.None;

                    if (typeSyntax == null)
                    {
                        hasExplicitlyTypedParameterList = false;
                    }
                    else
                    {
                        type = BindType(typeSyntax, diagnostics);
                        foreach (var modifier in p.Modifiers)
                        {
                            switch (modifier.Kind())
                            {
                            case SyntaxKind.RefKeyword:
                                refKind  = RefKind.Ref;
                                allValue = false;
                                break;

                            case SyntaxKind.OutKeyword:
                                refKind  = RefKind.Out;
                                allValue = false;
                                break;

                            case SyntaxKind.InKeyword:
                                refKind  = RefKind.In;
                                allValue = false;
                                break;

                            case SyntaxKind.ParamsKeyword:
                                // This was a parse error in the native compiler;
                                // it is a semantic analysis error in Roslyn. See comments to
                                // changeset 1674 for details.
                                Error(diagnostics, ErrorCode.ERR_IllegalParams, p);
                                break;

                            case SyntaxKind.ThisKeyword:
                                Error(diagnostics, ErrorCode.ERR_ThisInBadContext, modifier);
                                break;
                            }
                        }
                    }

                    namesBuilder.Add(p.Identifier.ValueText);
                    typesBuilder.Add(type);
                    refKindsBuilder.Add(refKind);
                    attributesBuilder.Add(syntax.Kind() == SyntaxKind.ParenthesizedLambdaExpression ? p.AttributeLists : default);
Beispiel #16
0
 private bool ValidateLambdaParameterNameConflictsInScope(Location location, string name, BindingDiagnosticBag diagnostics)
 {
     return(ValidateNameConflictsInScope(null, location, name, diagnostics));
 }
Beispiel #17
0
        private ImmutableArray <Symbol> BindMemberCref(MemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            if ((object?)containerOpt != null && containerOpt.Kind == SymbolKind.TypeParameter)
            {
                // As in normal lookup (see CreateErrorIfLookupOnTypeParameter), you can't dot into a type parameter
                // (though you can dot into an expression of type parameter type).
                CrefSyntax crefSyntax = GetRootCrefSyntax(syntax);
                var        noTrivia   = syntax.WithLeadingTrivia(null).WithTrailingTrivia(null);
                diagnostics.Add(ErrorCode.WRN_BadXMLRef, crefSyntax.Location, noTrivia.ToFullString());

                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            ImmutableArray <Symbol> result;

            switch (syntax.Kind())
            {
            case SyntaxKind.NameMemberCref:
                result = BindNameMemberCref((NameMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics);
                break;

            case SyntaxKind.IndexerMemberCref:
                result = BindIndexerMemberCref((IndexerMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics);
                break;

            case SyntaxKind.OperatorMemberCref:
                result = BindOperatorMemberCref((OperatorMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics);
                break;

            case SyntaxKind.ConversionOperatorMemberCref:
                result = BindConversionOperatorMemberCref((ConversionOperatorMemberCrefSyntax)syntax, containerOpt, out ambiguityWinner, diagnostics);
                break;

            default:
                throw ExceptionUtilities.UnexpectedValue(syntax.Kind());
            }

            if (!result.Any())
            {
                CrefSyntax crefSyntax = GetRootCrefSyntax(syntax);
                var        noTrivia   = syntax.WithLeadingTrivia(null).WithTrailingTrivia(null);
                diagnostics.Add(ErrorCode.WRN_BadXMLRef, crefSyntax.Location, noTrivia.ToFullString());
            }

            return(result);
        }
Beispiel #18
0
        internal bool ValidateDeclarationNameConflictsInScope(Symbol symbol, BindingDiagnosticBag diagnostics)
        {
            Location location = GetLocation(symbol);

            return(ValidateNameConflictsInScope(symbol, location, symbol.Name, diagnostics));
        }
Beispiel #19
0
        internal ImmutableArray <Symbol> BindCref(CrefSyntax syntax, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            ImmutableArray <Symbol> symbols = BindCrefInternal(syntax, out ambiguityWinner, diagnostics);

            Debug.Assert(!symbols.IsDefault, "Prefer empty to null.");
            Debug.Assert((symbols.Length > 1) == ((object?)ambiguityWinner != null), "ambiguityWinner should be set iff more than one symbol is returned.");
            return(symbols);
        }
Beispiel #20
0
        internal void ValidateParameterNameConflicts(
            ImmutableArray <TypeParameterSymbol> typeParameters,
            ImmutableArray <ParameterSymbol> parameters,
            bool allowShadowingNames,
            BindingDiagnosticBag diagnostics)
        {
            PooledHashSet <string>?tpNames = null;

            if (!typeParameters.IsDefaultOrEmpty)
            {
                tpNames = PooledHashSet <string> .GetInstance();

                foreach (var tp in typeParameters)
                {
                    var name = tp.Name;
                    if (string.IsNullOrEmpty(name))
                    {
                        continue;
                    }

                    if (!tpNames.Add(name))
                    {
                        // Type parameter declaration name conflicts are detected elsewhere
                    }
                    else if (!allowShadowingNames)
                    {
                        ValidateDeclarationNameConflictsInScope(tp, diagnostics);
                    }
                }
            }

            PooledHashSet <string>?pNames = null;

            if (!parameters.IsDefaultOrEmpty)
            {
                pNames = PooledHashSet <string> .GetInstance();

                foreach (var p in parameters)
                {
                    var name = p.Name;
                    if (string.IsNullOrEmpty(name))
                    {
                        continue;
                    }

                    if (tpNames != null && tpNames.Contains(name))
                    {
                        // CS0412: 'X': a parameter or local variable cannot have the same name as a method type parameter
                        diagnostics.Add(ErrorCode.ERR_LocalSameNameAsTypeParam, GetLocation(p), name);
                    }

                    if (!pNames.Add(name))
                    {
                        // The parameter name '{0}' is a duplicate
                        diagnostics.Add(ErrorCode.ERR_DuplicateParamName, GetLocation(p), name);
                    }
                    else if (!allowShadowingNames)
                    {
                        ValidateDeclarationNameConflictsInScope(p, diagnostics);
                    }
                }
            }

            tpNames?.Free();
            pNames?.Free();
        }
Beispiel #21
0
        // NOTE: not guaranteed to be a method (e.g. class op_Addition)
        // NOTE: constructor fallback logic applies
        private ImmutableArray <Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            const int arity = 0;

            CrefParameterListSyntax?parameterListSyntax = syntax.Parameters;
            bool isChecked = syntax.CheckedKeyword.IsKind(SyntaxKind.CheckedKeyword);

            // NOTE: Prefer binary to unary, unless there is exactly one parameter.
            // CONSIDER: we're following dev11 by never using a binary operator name if there's
            // exactly one parameter, but doing so would allow us to match single-parameter constructors.
            SyntaxKind operatorTokenKind = syntax.OperatorToken.Kind();
            string?    memberName        = parameterListSyntax != null && parameterListSyntax.Parameters.Count == 1
                ? null
                : OperatorFacts.BinaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind, isChecked);

            memberName = memberName ?? OperatorFacts.UnaryOperatorNameFromSyntaxKindIfAny(operatorTokenKind, isChecked: isChecked);

            if (memberName == null ||
                (isChecked && !syntax.OperatorToken.IsMissing && !SyntaxFacts.IsCheckedOperator(memberName))) // the operator cannot be checked
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            ImmutableArray <Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText: memberName, arity, syntax.Parameters != null, diagnostics);

            if (sortedSymbols.IsEmpty)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            return(ProcessCrefMemberLookupResults(
                       sortedSymbols,
                       arity,
                       syntax,
                       typeArgumentListSyntax: null,
                       parameterListSyntax: parameterListSyntax,
                       ambiguityWinner: out ambiguityWinner,
                       diagnostics: diagnostics));
        }
Beispiel #22
0
        private bool ReportConflictWithLocal(Symbol local, Symbol newSymbol, string name, Location newLocation, BindingDiagnosticBag diagnostics)
        {
            // Quirk of the way we represent lambda parameters.
            SymbolKind newSymbolKind = (object)newSymbol == null ? SymbolKind.Parameter : newSymbol.Kind;

            if (newSymbolKind == SymbolKind.ErrorType)
            {
                return(true);
            }

            var declaredInThisScope = false;

            declaredInThisScope |= newSymbolKind == SymbolKind.Local && this.Locals.Contains((LocalSymbol)newSymbol);
            declaredInThisScope |= newSymbolKind == SymbolKind.Method && this.LocalFunctions.Contains((LocalFunctionSymbol)newSymbol);

            if (declaredInThisScope && newLocation.SourceSpan.Start >= local.Locations[0].SourceSpan.Start)
            {
                // A local variable or function named '{0}' is already defined in this scope
                diagnostics.Add(ErrorCode.ERR_LocalDuplicate, newLocation, name);
                return(true);
            }

            switch (newSymbolKind)
            {
            case SymbolKind.Local:
            case SymbolKind.Parameter:
            case SymbolKind.Method:
            case SymbolKind.TypeParameter:
                // A local or parameter named '{0}' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
                diagnostics.Add(ErrorCode.ERR_LocalIllegallyOverrides, newLocation, name);
                return(true);

            case SymbolKind.RangeVariable:
                // The range variable '{0}' conflicts with a previous declaration of '{0}'
                diagnostics.Add(ErrorCode.ERR_QueryRangeVariableOverrides, newLocation, name);
                return(true);
            }

            Debug.Assert(false, "what else can be declared inside a local scope?");
            diagnostics.Add(ErrorCode.ERR_InternalError, newLocation);
            return(false);
        }
Beispiel #23
0
        // NOTE: not guaranteed to be a method (e.g. class op_Implicit)
        private ImmutableArray <Symbol> BindConversionOperatorMemberCref(ConversionOperatorMemberCrefSyntax syntax, NamespaceOrTypeSymbol?containerOpt, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            const int arity     = 0;
            bool      isChecked = syntax.CheckedKeyword.IsKind(SyntaxKind.CheckedKeyword);

            string memberName;

            if (syntax.ImplicitOrExplicitKeyword.Kind() == SyntaxKind.ImplicitKeyword)
            {
                if (isChecked)
                {
                    // checked form is not supported
                    ambiguityWinner = null;
                    return(ImmutableArray <Symbol> .Empty);
                }

                memberName = WellKnownMemberNames.ImplicitConversionName;
            }
            else if (isChecked)
            {
                memberName = WellKnownMemberNames.CheckedExplicitConversionName;
            }
            else
            {
                memberName = WellKnownMemberNames.ExplicitConversionName;
            }

            ImmutableArray <Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText: memberName, arity, syntax.Parameters != null, diagnostics);

            if (sortedSymbols.IsEmpty)
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            TypeSymbol returnType = BindCrefParameterOrReturnType(syntax.Type, syntax, diagnostics);

            // Filter out methods with the wrong return type, since overload resolution won't catch these.
            sortedSymbols = sortedSymbols.WhereAsArray((symbol, returnType) =>
                                                       symbol.Kind != SymbolKind.Method || TypeSymbol.Equals(((MethodSymbol)symbol).ReturnType, returnType, TypeCompareKind.ConsiderEverything2), returnType);

            if (!sortedSymbols.Any())
            {
                ambiguityWinner = null;
                return(ImmutableArray <Symbol> .Empty);
            }

            return(ProcessCrefMemberLookupResults(
                       sortedSymbols,
                       arity,
                       syntax,
                       typeArgumentListSyntax: null,
                       parameterListSyntax: syntax.Parameters,
                       ambiguityWinner: out ambiguityWinner,
                       diagnostics: diagnostics));
        }
Beispiel #24
0
        internal virtual bool EnsureSingleDefinition(Symbol symbol, string name, Location location, BindingDiagnosticBag diagnostics)
        {
            LocalSymbol         existingLocal         = null;
            LocalFunctionSymbol existingLocalFunction = null;

            var localsMap         = this.LocalsMap;
            var localFunctionsMap = this.LocalFunctionsMap;

            // TODO: Handle case where 'name' exists in both localsMap and localFunctionsMap. Right now locals are preferred over local functions.
            if ((localsMap != null && localsMap.TryGetValue(name, out existingLocal)) ||
                (localFunctionsMap != null && localFunctionsMap.TryGetValue(name, out existingLocalFunction)))
            {
                var existingSymbol = (Symbol)existingLocal ?? existingLocalFunction;
                if (symbol == existingSymbol)
                {
                    // reference to same symbol, by far the most common case.
                    return(false);
                }

                return(ReportConflictWithLocal(existingSymbol, symbol, name, location, diagnostics));
            }

            return(false);
        }
Beispiel #25
0
        private ImmutableArray <Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol?ambiguityWinner, BindingDiagnosticBag diagnostics)
        {
            NamespaceOrTypeSymbol result = BindNamespaceOrTypeSymbolInCref(syntax.Type);

            // NOTE: we don't have to worry about the case where a non-error type is constructed
            // with erroneous type arguments, because only MemberCrefs have type arguments -
            // all other crefs only have type parameters.
            if (result.Kind == SymbolKind.ErrorType)
            {
                var noTrivia = syntax.WithLeadingTrivia(null).WithTrailingTrivia(null);
                diagnostics.Add(ErrorCode.WRN_BadXMLRef, syntax.Location, noTrivia.ToFullString());
            }

            // We'll never have more than one type, but it is conceivable that result could
            // be an ExtendedErrorTypeSymbol with multiple candidates.
            ambiguityWinner = null;
            return(ImmutableArray.Create <Symbol>(result));
        }
Beispiel #26
0
        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);
            }
        }
Beispiel #27
0
 internal static BoundBlock ConstructFieldLikeEventAccessorBody(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, BindingDiagnosticBag diagnostics)
 {
     Debug.Assert(eventSymbol.HasAssociatedField);
     return(eventSymbol.IsWindowsRuntimeEvent
         ? ConstructFieldLikeEventAccessorBody_WinRT(eventSymbol, isAddMethod, compilation, diagnostics)
         : ConstructFieldLikeEventAccessorBody_Regular(eventSymbol, isAddMethod, compilation, diagnostics));
 }
Beispiel #28
0
 internal override ConstantValue GetConstantValue(SyntaxNode node, LocalSymbol inProgress, BindingDiagnosticBag diagnostics = null) => null;
Beispiel #29
0
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_Regular(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, BindingDiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            TypeSymbol      delegateType  = eventSymbol.Type;
            MethodSymbol    accessor      = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;
            ParameterSymbol thisParameter = accessor.ThisParameter;

            TypeSymbol boolType = compilation.GetSpecialType(SpecialType.System_Boolean);

            SpecialMember updateMethodId = isAddMethod ? SpecialMember.System_Delegate__Combine : SpecialMember.System_Delegate__Remove;
            MethodSymbol  updateMethod   = (MethodSymbol)compilation.GetSpecialTypeMember(updateMethodId);

            BoundStatement @return = new BoundReturnStatement(syntax,
                                                              refKind: RefKind.None,
                                                              expressionOpt: null)
            {
                WasCompilerGenerated = true
            };

            if (updateMethod == null)
            {
                MemberDescriptor memberDescriptor = SpecialMembers.GetDescriptor(updateMethodId);
                diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_MissingPredefinedMember,
                                                                      memberDescriptor.DeclaringTypeMetadataName,
                                                                      memberDescriptor.Name),
                                                 syntax.Location));

                return(BoundBlock.SynthesizedNoLocals(syntax, @return));
            }

            Binder.ReportUseSite(updateMethod, diagnostics, syntax);

            BoundThisReference fieldReceiver = eventSymbol.IsStatic ?
                                               null :
                                               new BoundThisReference(syntax, thisParameter.Type)
            {
                WasCompilerGenerated = true
            };

            BoundFieldAccess boundBackingField = new BoundFieldAccess(syntax,
                                                                      receiver: fieldReceiver,
                                                                      fieldSymbol: eventSymbol.AssociatedField,
                                                                      constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            BoundParameter boundParameter = new BoundParameter(syntax,
                                                               parameterSymbol: accessor.Parameters[0])
            {
                WasCompilerGenerated = true
            };

            BoundExpression delegateUpdate;

            MethodSymbol compareExchangeMethod = (MethodSymbol)compilation.GetWellKnownTypeMember(WellKnownMember.System_Threading_Interlocked__CompareExchange_T);

            if ((object)compareExchangeMethod == null)
            {
                // (DelegateType)Delegate.Combine(_event, value)
                delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax,
                                                                           operand: BoundCall.Synthesized(syntax,
                                                                                                          receiverOpt: null,
                                                                                                          method: updateMethod,
                                                                                                          arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundParameter)),
                                                                           conversion: Conversion.ExplicitReference,
                                                                           type: delegateType);

                // _event = (DelegateType)Delegate.Combine(_event, value);
                BoundStatement eventUpdate = new BoundExpressionStatement(syntax,
                                                                          expression: new BoundAssignmentOperator(syntax,
                                                                                                                  left: boundBackingField,
                                                                                                                  right: delegateUpdate,
                                                                                                                  type: delegateType)
                {
                    WasCompilerGenerated = true
                })
                {
                    WasCompilerGenerated = true
                };

                return(BoundBlock.SynthesizedNoLocals(syntax,
                                                      statements: ImmutableArray.Create <BoundStatement>(
                                                          eventUpdate,
                                                          @return)));
            }

            compareExchangeMethod = compareExchangeMethod.Construct(ImmutableArray.Create <TypeSymbol>(delegateType));

            Binder.ReportUseSite(compareExchangeMethod, diagnostics, syntax);

            GeneratedLabelSymbol loopLabel = new GeneratedLabelSymbol("loop");

            const int numTemps = 3;

            LocalSymbol[] tmps      = new LocalSymbol[numTemps];
            BoundLocal[]  boundTmps = new BoundLocal[numTemps];

            for (int i = 0; i < numTemps; i++)
            {
                tmps[i]      = new SynthesizedLocal(accessor, TypeWithAnnotations.Create(delegateType), SynthesizedLocalKind.LoweringTemp);
                boundTmps[i] = new BoundLocal(syntax, tmps[i], null, delegateType)
                {
                    WasCompilerGenerated = true
                };
            }

            // tmp0 = _event;
            BoundStatement tmp0Init = new BoundExpressionStatement(syntax,
                                                                   expression: new BoundAssignmentOperator(syntax,
                                                                                                           left: boundTmps[0],
                                                                                                           right: boundBackingField,
                                                                                                           type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // LOOP:
            BoundStatement loopStart = new BoundLabelStatement(syntax,
                                                               label: loopLabel)
            {
                WasCompilerGenerated = true
            };

            // tmp1 = tmp0;
            BoundStatement tmp1Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[1],
                                                                                                             right: boundTmps[0],
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // (DelegateType)Delegate.Combine(tmp1, value)
            delegateUpdate = BoundConversion.SynthesizedNonUserDefined(syntax,
                                                                       operand: BoundCall.Synthesized(syntax,
                                                                                                      receiverOpt: null,
                                                                                                      method: updateMethod,
                                                                                                      arguments: ImmutableArray.Create <BoundExpression>(boundTmps[1], boundParameter)),
                                                                       conversion: Conversion.ExplicitReference,
                                                                       type: delegateType);

            // tmp2 = (DelegateType)Delegate.Combine(tmp1, value);
            BoundStatement tmp2Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[2],
                                                                                                             right: delegateUpdate,
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1)
            BoundExpression compareExchange = BoundCall.Synthesized(syntax,
                                                                    receiverOpt: null,
                                                                    method: compareExchangeMethod,
                                                                    arguments: ImmutableArray.Create <BoundExpression>(boundBackingField, boundTmps[2], boundTmps[1]));

            // tmp0 = Interlocked.CompareExchange<DelegateType>(ref _event, tmp2, tmp1);
            BoundStatement tmp0Update = new BoundExpressionStatement(syntax,
                                                                     expression: new BoundAssignmentOperator(syntax,
                                                                                                             left: boundTmps[0],
                                                                                                             right: compareExchange,
                                                                                                             type: delegateType)
            {
                WasCompilerGenerated = true
            })
            {
                WasCompilerGenerated = true
            };

            // tmp0 == tmp1 // i.e. exit when they are equal, jump to start otherwise
            BoundExpression loopExitCondition = new BoundBinaryOperator(syntax,
                                                                        operatorKind: BinaryOperatorKind.ObjectEqual,
                                                                        left: boundTmps[0],
                                                                        right: boundTmps[1],
                                                                        constantValueOpt: null,
                                                                        methodOpt: null,
                                                                        constrainedToTypeOpt: null,
                                                                        resultKind: LookupResultKind.Viable,
                                                                        type: boolType)
            {
                WasCompilerGenerated = true
            };

            // branchfalse (tmp0 == tmp1) LOOP
            BoundStatement loopEnd = new BoundConditionalGoto(syntax,
                                                              condition: loopExitCondition,
                                                              jumpIfTrue: false,
                                                              label: loopLabel)
            {
                WasCompilerGenerated = true
            };

            return(new BoundBlock(syntax,
                                  locals: tmps.AsImmutable(),
                                  statements: ImmutableArray.Create <BoundStatement>(
                                      tmp0Init,
                                      loopStart,
                                      tmp1Update,
                                      tmp2Update,
                                      tmp0Update,
                                      loopEnd,
                                      @return))
            {
                WasCompilerGenerated = true
            });
        }
Beispiel #30
0
        public static Imports FromSyntax(
            CSharpSyntaxNode declarationSyntax,
            InContainerBinder binder,
            ConsList <TypeSymbol> basesBeingResolved,
            bool inUsing)
        {
            SyntaxList <UsingDirectiveSyntax>       usingDirectives;
            SyntaxList <ExternAliasDirectiveSyntax> externAliasDirectives;

            if (declarationSyntax.Kind() == SyntaxKind.CompilationUnit)
            {
                var compilationUnit = (CompilationUnitSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives       = inUsing ? default(SyntaxList <UsingDirectiveSyntax>) : compilationUnit.Usings;
                externAliasDirectives = compilationUnit.Externs;
            }
            else if (declarationSyntax.Kind() == SyntaxKind.NamespaceDeclaration)
            {
                var namespaceDecl = (NamespaceDeclarationSyntax)declarationSyntax;
                // using directives are not in scope within using directives
                usingDirectives       = inUsing ? default(SyntaxList <UsingDirectiveSyntax>) : namespaceDecl.Usings;
                externAliasDirectives = namespaceDecl.Externs;
            }
            else
            {
                return(Empty);
            }

            if (usingDirectives.Count == 0 && externAliasDirectives.Count == 0)
            {
                return(Empty);
            }

            // define all of the extern aliases first. They may used by the target of a using

            // using Bar=Goo::Bar;
            // using Goo::Baz;
            // extern alias Goo;

            var diagnostics = new DiagnosticBag();

            var compilation = binder.Compilation;

            var externAliases = BuildExternAliases(externAliasDirectives, binder, diagnostics);
            var usings        = ArrayBuilder <NamespaceOrTypeAndUsingDirective> .GetInstance();

            ImmutableDictionary <string, AliasAndUsingDirective> .Builder usingAliases = null;
            if (usingDirectives.Count > 0)
            {
                // A binder that contains the extern aliases but not the usings. The resolution of the target of a using directive or alias
                // should not make use of other peer usings.
                Binder usingsBinder;
                if (declarationSyntax.SyntaxTree.Options.Kind != SourceCodeKind.Regular)
                {
                    usingsBinder = compilation.GetBinderFactory(declarationSyntax.SyntaxTree).GetImportsBinder(declarationSyntax, inUsing: true);
                }
                else
                {
                    var imports = externAliases.Length == 0
                        ? Empty
                        : new Imports(
                        compilation,
                        ImmutableDictionary <string, AliasAndUsingDirective> .Empty,
                        ImmutableArray <NamespaceOrTypeAndUsingDirective> .Empty,
                        externAliases,
                        diagnostics: null);
                    usingsBinder = new InContainerBinder(binder.Container, binder.Next, imports);
                }

                var uniqueUsings = SpecializedSymbolCollections.GetPooledSymbolHashSetInstance <NamespaceOrTypeSymbol>();

                foreach (var usingDirective in usingDirectives)
                {
                    compilation.RecordImport(usingDirective);

                    if (usingDirective.Alias != null)
                    {
                        SyntaxToken identifier = usingDirective.Alias.Name.Identifier;
                        Location    location   = usingDirective.Alias.Name.Location;

                        if (identifier.ContextualKind() == SyntaxKind.GlobalKeyword)
                        {
                            diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, location);
                        }

                        if (usingDirective.StaticKeyword != default(SyntaxToken))
                        {
                            diagnostics.Add(ErrorCode.ERR_NoAliasHere, location);
                        }

                        SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, compilation, diagnostics, location);

                        string identifierValueText = identifier.ValueText;
                        if (usingAliases != null && usingAliases.ContainsKey(identifierValueText))
                        {
                            // Suppress diagnostics if we're already broken.
                            if (!usingDirective.Name.IsMissing)
                            {
                                // The using alias '{0}' appeared previously in this namespace
                                diagnostics.Add(ErrorCode.ERR_DuplicateAlias, location, identifierValueText);
                            }
                        }
                        else
                        {
                            // an O(m*n) algorithm here but n (number of extern aliases) will likely be very small.
                            foreach (var externAlias in externAliases)
                            {
                                if (externAlias.Alias.Name == identifierValueText)
                                {
                                    // The using alias '{0}' appeared previously in this namespace
                                    diagnostics.Add(ErrorCode.ERR_DuplicateAlias, usingDirective.Location, identifierValueText);
                                    break;
                                }
                            }

                            if (usingAliases == null)
                            {
                                usingAliases = ImmutableDictionary.CreateBuilder <string, AliasAndUsingDirective>();
                            }

                            // construct the alias sym with the binder for which we are building imports. That
                            // way the alias target can make use of extern alias definitions.
                            usingAliases.Add(identifierValueText, new AliasAndUsingDirective(new AliasSymbol(usingsBinder, usingDirective.Name, usingDirective.Alias), usingDirective));
                        }
                    }
                    else
                    {
                        if (usingDirective.Name.IsMissing)
                        {
                            //don't try to lookup namespaces inserted by parser error recovery
                            continue;
                        }

                        var directiveDiagnostics = BindingDiagnosticBag.GetInstance();

                        var declarationBinder = usingsBinder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);
                        var imported          = declarationBinder.BindNamespaceOrTypeSymbol(usingDirective.Name, directiveDiagnostics, basesBeingResolved).NamespaceOrTypeSymbol;

                        if (imported.Kind == SymbolKind.Namespace)
                        {
                            Debug.Assert(directiveDiagnostics.DependenciesBag.IsEmpty());

                            if (usingDirective.StaticKeyword != default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingType, usingDirective.Name.Location, imported);
                            }
                            else if (!uniqueUsings.Add(imported))
                            {
                                diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                usings.Add(new NamespaceOrTypeAndUsingDirective(imported, usingDirective, dependencies: default));
                            }
                        }
                        else if (imported.Kind == SymbolKind.NamedType)
                        {
                            if (usingDirective.StaticKeyword == default(SyntaxToken))
                            {
                                diagnostics.Add(ErrorCode.ERR_BadUsingNamespace, usingDirective.Name.Location, imported);
                            }
                            else
                            {
                                var importedType = (NamedTypeSymbol)imported;
                                if (uniqueUsings.Contains(importedType))
                                {
                                    diagnostics.Add(ErrorCode.WRN_DuplicateUsing, usingDirective.Name.Location, importedType);
                                }
                                else
                                {
                                    declarationBinder.ReportDiagnosticsIfObsolete(diagnostics, importedType, usingDirective.Name, hasBaseReceiver: false);

                                    uniqueUsings.Add(importedType);
                                    usings.Add(new NamespaceOrTypeAndUsingDirective(importedType, usingDirective, directiveDiagnostics.DependenciesBag.ToImmutableArray()));
                                }
                            }
                        }
                        else if (imported.Kind != SymbolKind.ErrorType)
                        {
                            // Do not report additional error if the symbol itself is erroneous.

                            // error: '<symbol>' is a '<symbol kind>' but is used as 'type or namespace'
                            diagnostics.Add(ErrorCode.ERR_BadSKknown, usingDirective.Name.Location,
                                            usingDirective.Name,
                                            imported.GetKindText(),
                                            MessageID.IDS_SK_TYPE_OR_NAMESPACE.Localize());
                        }

                        diagnostics.AddRange(directiveDiagnostics.DiagnosticBag);
                        directiveDiagnostics.Free();
                    }
                }

                uniqueUsings.Free();
            }

            if (diagnostics.IsEmptyWithoutResolution)
            {
                diagnostics = null;
            }

            return(new Imports(compilation, usingAliases.ToImmutableDictionaryOrEmpty(), usings.ToImmutableAndFree(), externAliases, diagnostics));
        }