Beispiel #1
0
        protected BoundExpression ConvertCaseExpression(CSharpSyntaxNode node, BoundExpression caseExpression, Binder sectionBinder, out ConstantValue constantValueOpt, BindingDiagnosticBag diagnostics, bool isGotoCaseExpr = false)
        {
            bool hasErrors = false;

            if (isGotoCaseExpr)
            {
                // SPEC VIOLATION for Dev10 COMPATIBILITY:

                // Dev10 compiler violates the SPEC comment below:
                //      "if the constant-expression is not implicitly convertible (§6.1) to
                //      the governing type of the nearest enclosing switch statement,
                //      a compile-time error occurs"

                // If there is no implicit conversion from gotoCaseExpression to switchGoverningType,
                // but there exists an explicit conversion, Dev10 compiler generates a warning "WRN_GotoCaseShouldConvert"
                // instead of an error. See test "CS0469_NoImplicitConversionWarning".

                CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
                Conversion conversion = Conversions.ClassifyConversionFromExpression(caseExpression, SwitchGoverningType, ref useSiteInfo);
                diagnostics.Add(node, useSiteInfo);
                if (!conversion.IsValid)
                {
                    GenerateImplicitConversionError(diagnostics, node, conversion, caseExpression, SwitchGoverningType);
                    hasErrors = true;
                }
                else if (!conversion.IsImplicit)
                {
                    diagnostics.Add(ErrorCode.WRN_GotoCaseShouldConvert, node.Location, SwitchGoverningType);
                    hasErrors = true;
                }

                caseExpression = CreateConversion(caseExpression, conversion, SwitchGoverningType, diagnostics);
            }

            return(ConvertPatternExpression(SwitchGoverningType, node, caseExpression, out constantValueOpt, hasErrors, diagnostics));
        }
Beispiel #2
0
        internal static bool CheckFeatureAvailability(
            this MessageID feature,
            BindingDiagnosticBag diagnostics,
            SyntaxNode syntax,
            Location?location = null)
        {
            var diag = GetFeatureAvailabilityDiagnosticInfo(feature, (CSharpParseOptions)syntax.SyntaxTree.Options);

            if (diag is object)
            {
                diagnostics.Add(diag, location ?? syntax.GetLocation());
                return(false);
            }
            return(true);
        }
Beispiel #3
0
 internal static bool CheckFeatureAvailability(
     this MessageID feature,
     BindingDiagnosticBag diagnostics,
     Compilation compilation,
     Location location
     )
 {
     if (
         GetFeatureAvailabilityDiagnosticInfo(feature, (CSharpCompilation)compilation) is
         { } diagInfo
         )
     {
         diagnostics.Add(diagInfo, location);
         return(false);
     }
     return(true);
 }
Beispiel #4
0
        /// <summary>
        /// Checks that the Awaiter implements System.Runtime.CompilerServices.INotifyCompletion.
        /// </summary>
        /// <remarks>
        /// Spec 7.7.7.1:
        /// An Awaiter A implements the interface System.Runtime.CompilerServices.INotifyCompletion.
        /// </remarks>
        private bool AwaiterImplementsINotifyCompletion(TypeSymbol awaiterType, SyntaxNode node, BindingDiagnosticBag diagnostics)
        {
            var INotifyCompletion = GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_INotifyCompletion, diagnostics, node);
            CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);

            var conversion = this.Conversions.ClassifyImplicitConversionFromType(awaiterType, INotifyCompletion, ref useSiteInfo);

            if (!conversion.IsImplicit)
            {
                diagnostics.Add(node, useSiteInfo);
                Error(diagnostics, ErrorCode.ERR_DoesntImplementAwaitInterface, node, awaiterType, INotifyCompletion);
                return(false);
            }

            Debug.Assert(conversion.IsValid);
            return(true);
        }
Beispiel #5
0
        private static bool ReportQueryInferenceFailedSelectMany(
            FromClauseSyntax fromClause,
            string methodName,
            BoundExpression receiver,
            AnalyzedArguments arguments,
            ImmutableArray <Symbol> symbols,
            BindingDiagnosticBag diagnostics
            )
        {
            Debug.Assert(methodName == "SelectMany");

            // Estimate the return type of Select's lambda argument
            BoundExpression arg  = arguments.Argument(arguments.IsExtensionMethodInvocation ? 1 : 0);
            TypeSymbol      type = null;

            if (arg.Kind == BoundKind.UnboundLambda)
            {
                var unbound = (UnboundLambda)arg;
                foreach (var t in unbound.Data.InferredReturnTypes())
                {
                    if (!t.IsErrorType())
                    {
                        type = t;
                        break;
                    }
                }
            }

            if ((object)type == null || type.IsErrorType())
            {
                return(false);
            }

            TypeSymbol receiverType = receiver?.Type;

            diagnostics.Add(
                new DiagnosticInfoWithSymbols(
                    ErrorCode.ERR_QueryTypeInferenceFailedSelectMany,
                    new object[] { type, receiverType, methodName },
                    symbols
                    ),
                fromClause.Expression.Location
                );
            return(true);
        }
Beispiel #6
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));
        }
        internal override BoundStatement BindSwitchStatementCore(SwitchStatementSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(SwitchSyntax.Equals(node));

            if (node.Sections.Count == 0)
            {
                diagnostics.Add(ErrorCode.WRN_EmptySwitch, node.OpenBraceToken.GetLocation());
            }

            // Bind switch expression and set the switch governing type.
            BoundExpression boundSwitchGoverningExpression = SwitchGoverningExpression;

            diagnostics.AddRange(SwitchGoverningDiagnostics, allowMismatchInDependencyAccumulation: true);

            ImmutableArray <BoundSwitchSection>  switchSections = BindSwitchSections(originalBinder, diagnostics, out BoundSwitchLabel defaultLabel);
            ImmutableArray <LocalSymbol>         locals         = GetDeclaredLocalsForScope(node);
            ImmutableArray <LocalFunctionSymbol> functions      = GetDeclaredLocalFunctionsForScope(node);
            BoundDecisionDag decisionDag = DecisionDagBuilder.CreateDecisionDagForSwitchStatement(
                compilation: this.Compilation,
                syntax: node,
                switchGoverningExpression: boundSwitchGoverningExpression,
                switchSections: switchSections,
                // If there is no explicit default label, the default action is to break out of the switch
                defaultLabel: defaultLabel?.Label ?? BreakLabel,
                diagnostics);

            // Report subsumption errors, but ignore the input's constant value for that.
            CheckSwitchErrors(node, boundSwitchGoverningExpression, ref switchSections, decisionDag, diagnostics);

            // When the input is constant, we use that to reshape the decision dag that is returned
            // so that flow analysis will see that some of the cases may be unreachable.
            decisionDag = decisionDag.SimplifyDecisionDagIfConstantInput(boundSwitchGoverningExpression);

            return(new BoundSwitchStatement(
                       syntax: node,
                       expression: boundSwitchGoverningExpression,
                       innerLocals: locals,
                       innerLocalFunctions: functions,
                       switchSections: switchSections,
                       defaultLabel: defaultLabel,
                       breakLabel: this.BreakLabel,
                       reachabilityDecisionDag: decisionDag));
        }
Beispiel #8
0
        internal bool ReportUnsafeIfNotAllowed(
            SyntaxNode node,
            BindingDiagnosticBag diagnostics,
            TypeSymbol sizeOfTypeOpt = null
            )
        {
            Debug.Assert(
                (node.Kind() == SyntaxKind.SizeOfExpression) == ((object)sizeOfTypeOpt != null),
                "Should have a type for (only) sizeof expressions."
                );
            var diagnosticInfo = GetUnsafeDiagnosticInfo(sizeOfTypeOpt);

            if (diagnosticInfo == null)
            {
                return(false);
            }

            diagnostics.Add(new CSDiagnostic(diagnosticInfo, node.Location));
            return(true);
        }
Beispiel #9
0
        private TypeSymbol InferResultType(ImmutableArray <BoundSwitchExpressionArm> switchCases, BindingDiagnosticBag diagnostics)
        {
            var seenTypes    = Symbols.SpecializedSymbolCollections.GetPooledSymbolHashSetInstance <TypeSymbol>();
            var typesInOrder = ArrayBuilder <TypeSymbol> .GetInstance();

            foreach (var @case in switchCases)
            {
                var type = @case.Value.Type;
                if (type is object && seenTypes.Add(type))
                {
                    typesInOrder.Add(type);
                }
            }

            seenTypes.Free();
            CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
            var commonType = BestTypeInferrer.GetBestType(typesInOrder, Conversions, ref useSiteInfo);

            typesInOrder.Free();

            // We've found a candidate common type among those arms that have a type.  Also check that every arm's
            // expression (even those without a type) can be converted to that type.
            if (commonType is object)
            {
                foreach (var @case in switchCases)
                {
                    if (!this.Conversions.ClassifyImplicitConversionFromExpression(@case.Value, commonType, ref useSiteInfo).Exists)
                    {
                        commonType = null;
                        break;
                    }
                }
            }

            diagnostics.Add(SwitchExpressionSyntax, useSiteInfo);
            return(commonType);
        }
            internal RangeVariableSymbol AddRangeVariable(
                Binder binder,
                SyntaxToken identifier,
                BindingDiagnosticBag diagnostics
                )
            {
                string name   = identifier.ValueText;
                var    result = new RangeVariableSymbol(
                    name,
                    binder.ContainingMemberOrLambda,
                    identifier.GetLocation()
                    );
                bool error = false;

                foreach (var existingRangeVariable in allRangeVariables.Keys)
                {
                    if (existingRangeVariable.Name == name)
                    {
                        diagnostics.Add(
                            ErrorCode.ERR_QueryDuplicateRangeVariable,
                            identifier.GetLocation(),
                            name
                            );
                        error = true;
                    }
                }

                if (!error)
                {
                    var collisionDetector = new LocalScopeBinder(binder);
                    collisionDetector.ValidateDeclarationNameConflictsInScope(result, diagnostics);
                }

                allRangeVariables.Add(result, ArrayBuilder <string> .GetInstance());
                return(result);
            }
Beispiel #11
0
        private bool CheckSwitchExpressionExhaustive(
            SwitchExpressionSyntax node,
            BoundExpression boundInputExpression,
            ImmutableArray <BoundSwitchExpressionArm> switchArms,
            out BoundDecisionDag decisionDag,
            out LabelSymbol defaultLabel,
            BindingDiagnosticBag diagnostics)
        {
            defaultLabel = new GeneratedLabelSymbol("default");
            decisionDag  = DecisionDagBuilder.CreateDecisionDagForSwitchExpression(this.Compilation, node, boundInputExpression, switchArms, defaultLabel, diagnostics);
            var  reachableLabels = decisionDag.ReachableLabels;
            bool hasErrors       = false;

            foreach (BoundSwitchExpressionArm arm in switchArms)
            {
                hasErrors |= arm.HasErrors;
                if (!hasErrors && !reachableLabels.Contains(arm.Label))
                {
                    diagnostics.Add(ErrorCode.ERR_SwitchArmSubsumed, arm.Pattern.Syntax.Location);
                }
            }

            if (!reachableLabels.Contains(defaultLabel))
            {
                // switch expression is exhaustive; no default label needed.
                defaultLabel = null;
                return(false);
            }

            if (hasErrors)
            {
                return(true);
            }

            // We only report exhaustive warnings when the default label is reachable through some series of
            // tests that do not include a test in which the value is known to be null.  Handling paths with
            // nulls is the job of the nullable walker.
            bool wasAcyclic = TopologicalSort.TryIterativeSort <BoundDecisionDagNode>(new[] { decisionDag.RootNode }, nonNullSuccessors, out var nodes);

            // Since decisionDag.RootNode is acyclic by construction, its subset of nodes sorted here cannot be cyclic
            Debug.Assert(wasAcyclic);
            foreach (var n in nodes)
            {
                if (n is BoundLeafDecisionDagNode leaf && leaf.Label == defaultLabel)
                {
                    var samplePattern = PatternExplainer.SamplePatternForPathToDagNode(
                        BoundDagTemp.ForOriginalInput(boundInputExpression), nodes, n, nullPaths: false, out bool requiresFalseWhenClause, out bool unnamedEnumValue);
                    ErrorCode warningCode =
                        requiresFalseWhenClause ? ErrorCode.WRN_SwitchExpressionNotExhaustiveWithWhen :
                        unnamedEnumValue ? ErrorCode.WRN_SwitchExpressionNotExhaustiveWithUnnamedEnumValue :
                        ErrorCode.WRN_SwitchExpressionNotExhaustive;
                    diagnostics.Add(
                        warningCode,
                        node.SwitchKeyword.GetLocation(),
                        samplePattern);
                    return(true);
                }
            }

            return(false);

            ImmutableArray <BoundDecisionDagNode> nonNullSuccessors(BoundDecisionDagNode n)
            {
                switch (n)
                {
                case BoundTestDecisionDagNode p:
                    switch (p.Test)
                    {
                    case BoundDagNonNullTest t:         // checks that the input is not null
                        return(ImmutableArray.Create(p.WhenTrue));

                    case BoundDagExplicitNullTest t:         // checks that the input is null
                        return(ImmutableArray.Create(p.WhenFalse));

                    default:
                        return(BoundDecisionDag.Successors(n));
                    }

                default:
                    return(BoundDecisionDag.Successors(n));
                }
            }
        }
Beispiel #12
0
        private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, BindingDiagnosticBag diagnostics)
        {
            //  prepare
            var  initializers = node.Initializers;
            int  fieldCount   = initializers.Count;
            bool hasError     = false;

            //  bind field initializers
            BoundExpression[]    boundExpressions = new BoundExpression[fieldCount];
            AnonymousTypeField[] fields           = new AnonymousTypeField[fieldCount];
            CSharpSyntaxNode[]   fieldSyntaxNodes = new CSharpSyntaxNode[fieldCount];

            // WARNING: Note that SemanticModel.GetDeclaredSymbol for field initializer node relies on
            //          the fact that the order of properties in anonymous type template corresponds
            //          1-to-1 to the appropriate filed initializer syntax nodes; This means such
            //          correspondence must be preserved all the time including erroneous scenarios

            // set of names already used
            var uniqueFieldNames = PooledHashSet <string> .GetInstance();

            for (int i = 0; i < fieldCount; i++)
            {
                AnonymousObjectMemberDeclaratorSyntax fieldInitializer = initializers[i];
                NameEqualsSyntax?nameEquals = fieldInitializer.NameEquals;
                ExpressionSyntax expression = fieldInitializer.Expression;

                SyntaxToken nameToken = default(SyntaxToken);
                if (nameEquals != null)
                {
                    nameToken = nameEquals.Name.Identifier;
                }
                else
                {
                    if (!IsAnonymousTypeMemberExpression(expression))
                    {
                        hasError = true;
                        diagnostics.Add(ErrorCode.ERR_InvalidAnonymousTypeMemberDeclarator, expression.GetLocation());
                    }

                    nameToken = expression.ExtractAnonymousTypeMemberName();
                }

                hasError           |= expression.HasErrors;
                boundExpressions[i] = BindRValueWithoutTargetType(expression, diagnostics);

                //  check the name to be unique
                string?fieldName = null;
                if (nameToken.Kind() == SyntaxKind.IdentifierToken)
                {
                    fieldName = nameToken.ValueText;
                    if (!uniqueFieldNames.Add(fieldName !))
                    {
                        //  name duplication
                        Error(diagnostics, ErrorCode.ERR_AnonymousTypeDuplicatePropertyName, fieldInitializer);
                        hasError  = true;
                        fieldName = null;
                    }
                }
                else
                {
                    // there is something wrong with field's name
                    hasError = true;
                }

                //  calculate the expression's type and report errors if needed
                TypeSymbol fieldType = GetAnonymousTypeFieldType(boundExpressions[i], fieldInitializer, diagnostics, ref hasError);

                // build anonymous type field descriptor
                fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent ! : fieldInitializer;
                fields[i]           = new AnonymousTypeField(
                    fieldName == null ? "$" + i.ToString() : fieldName,
                    fieldSyntaxNodes[i].Location,
                    TypeWithAnnotations.Create(fieldType),
                    RefKind.None,
                    DeclarationScope.Unscoped);

                //  NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed
            }

            uniqueFieldNames.Free();

            //  Create anonymous type
            AnonymousTypeManager    manager       = this.Compilation.AnonymousTypeManager;
            AnonymousTypeDescriptor descriptor    = new AnonymousTypeDescriptor(fields.AsImmutableOrNull(), node.NewKeyword.GetLocation());
            NamedTypeSymbol         anonymousType = manager.ConstructAnonymousTypeSymbol(descriptor);

            // declarators - bound nodes created for providing semantic info
            // on anonymous type fields having explicitly specified name
            ArrayBuilder <BoundAnonymousPropertyDeclaration> declarators =
                ArrayBuilder <BoundAnonymousPropertyDeclaration> .GetInstance();

            for (int i = 0; i < fieldCount; i++)
            {
                NameEqualsSyntax?explicitName = initializers[i].NameEquals;
                if (explicitName != null)
                {
                    AnonymousTypeField field = fields[i];
                    if (field.Name != null)
                    {
                        //  get property symbol and create a bound property declaration node
                        foreach (var symbol in anonymousType.GetMembers(field.Name))
                        {
                            if (symbol.Kind == SymbolKind.Property)
                            {
                                declarators.Add(new BoundAnonymousPropertyDeclaration(fieldSyntaxNodes[i], (PropertySymbol)symbol, field.Type));
                                break;
                            }
                        }
                    }
                }
            }

            // check if anonymous object creation is allowed in this context
            if (!this.IsAnonymousTypesAllowed())
            {
                Error(diagnostics, ErrorCode.ERR_AnonymousTypeNotAvailable, node.NewKeyword);
                hasError = true;
            }

            //  Finally create a bound node
            return(new BoundAnonymousObjectCreationExpression(
                       node,
                       anonymousType.InstanceConstructors[0],
                       boundExpressions.AsImmutableOrNull(),
                       declarators.ToImmutableAndFree(),
                       anonymousType,
                       hasError));
        }
            private BoundExpression SelectField(
                SimpleNameSyntax node,
                BoundExpression receiver,
                string name,
                BindingDiagnosticBag diagnostics
                )
            {
                var receiverType = receiver.Type as NamedTypeSymbol;

                if ((object)receiverType == null || !receiverType.IsAnonymousType)
                {
                    // We only construct transparent query variables using anonymous types, so if we're trying to navigate through
                    // some other type, we must have some query API where the types don't match up as expected.
                    var info = new CSDiagnosticInfo(
                        ErrorCode.ERR_UnsupportedTransparentIdentifierAccess,
                        name,
                        receiver.ExpressionSymbol ?? receiverType
                        );
                    if (receiver.Type?.IsErrorType() != true)
                    {
                        Error(diagnostics, info, node);
                    }

                    return(new BoundBadExpression(
                               node,
                               LookupResultKind.Empty,
                               ImmutableArray.Create <Symbol>(receiver.ExpressionSymbol),
                               ImmutableArray.Create(BindToTypeForErrorRecovery(receiver)),
                               new ExtendedErrorTypeSymbol(this.Compilation, "", 0, info)
                               ));
                }

                LookupResult  lookupResult = LookupResult.GetInstance();
                LookupOptions options      = LookupOptions.MustBeInstance;
                CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(
                    diagnostics
                    );

                LookupMembersWithFallback(
                    lookupResult,
                    receiver.Type,
                    name,
                    0,
                    ref useSiteInfo,
                    basesBeingResolved: null,
                    options: options
                    );
                diagnostics.Add(node, useSiteInfo);

                var result = BindMemberOfType(
                    node,
                    node,
                    name,
                    0,
                    indexed: false,
                    receiver,
                    default(SeparatedSyntaxList <TypeSyntax>),
                    default(ImmutableArray <TypeWithAnnotations>),
                    lookupResult,
                    BoundMethodGroupFlags.None,
                    diagnostics
                    );

                lookupResult.Free();
                return(result);
            }
Beispiel #14
0
        /// <summary>
        /// Given a list of viable lookup results (based on the name, arity, and containing symbol),
        /// attempt to select one.
        /// </summary>
        private ImmutableArray <Symbol> ProcessCrefMemberLookupResults(
            ImmutableArray <Symbol> symbols,
            int arity,
            MemberCrefSyntax memberSyntax,
            TypeArgumentListSyntax?typeArgumentListSyntax,
            BaseCrefParameterListSyntax?parameterListSyntax,
            out Symbol?ambiguityWinner,
            BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(!symbols.IsEmpty);

            if (parameterListSyntax == null)
            {
                return(ProcessParameterlessCrefMemberLookupResults(symbols, arity, memberSyntax, typeArgumentListSyntax, out ambiguityWinner, diagnostics));
            }

            ArrayBuilder <Symbol> candidates = ArrayBuilder <Symbol> .GetInstance();

            GetCrefOverloadResolutionCandidates(symbols, arity, typeArgumentListSyntax, candidates);

            ImmutableArray <ParameterSymbol> parameterSymbols = BindCrefParameters(parameterListSyntax, diagnostics);
            ImmutableArray <Symbol>          results          = PerformCrefOverloadResolution(candidates, parameterSymbols, arity, memberSyntax, out ambiguityWinner, diagnostics);

            candidates.Free();

            // NOTE: This diagnostic is just a hint that might help fix a broken cref, so don't do
            // any work unless there are no viable candidates.
            if (results.Length == 0)
            {
                for (int i = 0; i < parameterSymbols.Length; i++)
                {
                    if (ContainsNestedTypeOfUnconstructedGenericType(parameterSymbols[i].Type))
                    {
                        // This warning is new in Roslyn, because our better-defined semantics for
                        // cref lookup disallow some things that were possible in dev12.
                        //
                        // Consider the following code:
                        //
                        //   public class C<T>
                        //   {
                        //       public class Inner { }
                        //
                        //       public void M(Inner i) { }
                        //
                        //       /// <see cref="M"/>
                        //       /// <see cref="C{T}.M"/>
                        //       /// <see cref="C{Q}.M"/>
                        //       /// <see cref="C{Q}.M(C{Q}.Inner)"/>
                        //       /// <see cref="C{Q}.M(Inner)"/> // WRN_UnqualifiedNestedTypeInCref
                        //       public void N() { }
                        //   }
                        //
                        // Dev12 binds all of the crefs as "M:C`1.M(C{`0}.Inner)".
                        // Roslyn accepts all but the last.  The issue is that the context for performing
                        // the lookup is not C<Q>, but C<T>.  Consequently, Inner binds to C<T>.Inner and
                        // then overload resolution fails because C<T>.Inner does not match C<Q>.Inner,
                        // the parameter type of C<Q>.M.  Since we could not agree that the old behavior
                        // was desirable (other than for backwards compatibility) and since mimicking it
                        // would have been expensive, we settled on introducing a new warning that at
                        // least hints to the user how then can work around the issue (i.e. by qualifying
                        // Inner as C{Q}.Inner).  Additional details are available in DevDiv #743425.
                        //
                        // CONSIDER: We could actually put the qualified form in the warning message,
                        // but that would probably just make it more frustrating (i.e. if the compiler
                        // knows exactly what I mean, why do I have to type it).
                        //
                        // NOTE: This is not a great location (whole parameter instead of problematic type),
                        // but it's better than nothing.
                        diagnostics.Add(ErrorCode.WRN_UnqualifiedNestedTypeInCref, parameterListSyntax.Parameters[i].Location);
                        break;
                    }
                }
            }

            return(results);
        }
Beispiel #15
0
        /// <summary>
        /// At this point, we have a list of viable symbols and no parameter list with which to perform
        /// overload resolution.  We'll just return the first symbol, giving a diagnostic if there are
        /// others.
        /// Caveat: If there are multiple candidates and only one is from source, then the source symbol
        /// wins and no diagnostic is reported.
        /// </summary>
        private ImmutableArray <Symbol> ProcessParameterlessCrefMemberLookupResults(
            ImmutableArray <Symbol> symbols,
            int arity,
            MemberCrefSyntax memberSyntax,
            TypeArgumentListSyntax?typeArgumentListSyntax,
            out Symbol?ambiguityWinner,
            BindingDiagnosticBag diagnostics)
        {
            // If the syntax indicates arity zero, then we match methods of any arity.
            // However, if there are both generic and non-generic methods, then the
            // generic methods should be ignored.
            if (symbols.Length > 1 && arity == 0)
            {
                bool hasNonGenericMethod = false;
                bool hasGenericMethod    = false;
                foreach (Symbol s in symbols)
                {
                    if (s.Kind != SymbolKind.Method)
                    {
                        continue;
                    }

                    if (((MethodSymbol)s).Arity == 0)
                    {
                        hasNonGenericMethod = true;
                    }
                    else
                    {
                        hasGenericMethod = true;
                    }

                    if (hasGenericMethod && hasNonGenericMethod)
                    {
                        break; //Nothing else to be learned.
                    }
                }

                if (hasNonGenericMethod && hasGenericMethod)
                {
                    symbols = symbols.WhereAsArray(s =>
                                                   s.Kind != SymbolKind.Method || ((MethodSymbol)s).Arity == 0);
                }
            }

            Debug.Assert(!symbols.IsEmpty);

            Symbol symbol = symbols[0];

            // If there's ambiguity, prefer source symbols.
            // Logic is similar to ResultSymbol, but separate because the error handling is totally different.
            if (symbols.Length > 1)
            {
                // Size is known, but IndexOfSymbolFromCurrentCompilation expects a builder.
                ArrayBuilder <Symbol> unwrappedSymbols = ArrayBuilder <Symbol> .GetInstance(symbols.Length);

                foreach (Symbol wrapped in symbols)
                {
                    unwrappedSymbols.Add(UnwrapAliasNoDiagnostics(wrapped));
                }

                BestSymbolInfo secondBest;
                BestSymbolInfo best = GetBestSymbolInfo(unwrappedSymbols, out secondBest);

                Debug.Assert(!best.IsNone);
                Debug.Assert(!secondBest.IsNone);

                unwrappedSymbols.Free();

                int symbolIndex = 0;

                if (best.IsFromCompilation)
                {
                    symbolIndex = best.Index;
                    symbol      = symbols[symbolIndex]; // NOTE: symbols, not unwrappedSymbols.
                }

                if (symbol.Kind == SymbolKind.TypeParameter)
                {
                    CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                    diagnostics.Add(ErrorCode.WRN_BadXMLRefTypeVar, crefSyntax.Location, crefSyntax.ToString());
                }
                else if (secondBest.IsFromCompilation == best.IsFromCompilation)
                {
                    CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                    int        otherIndex = symbolIndex == 0 ? 1 : 0;
                    diagnostics.Add(ErrorCode.WRN_AmbiguousXMLReference, crefSyntax.Location, crefSyntax.ToString(), symbol, symbols[otherIndex]);

                    ambiguityWinner = ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, symbol);
                    return(symbols.SelectAsArray(sym => ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, sym)));
                }
            }
            else if (symbol.Kind == SymbolKind.TypeParameter)
            {
                CrefSyntax crefSyntax = GetRootCrefSyntax(memberSyntax);
                diagnostics.Add(ErrorCode.WRN_BadXMLRefTypeVar, crefSyntax.Location, crefSyntax.ToString());
            }

            ambiguityWinner = null;
            return(ImmutableArray.Create <Symbol>(ConstructWithCrefTypeParameters(arity, typeArgumentListSyntax, symbol)));
        }
Beispiel #16
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,
                                                              @checked: false)
            {
                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 #17
0
        public static BoundBlock Rewrite(
            MethodSymbol method,
            BoundBlock block,
            TypeCompilationState compilationState,
            BindingDiagnosticBag diagnostics,
            bool hasTrailingExpression,
            bool originalBodyNested)
        {
#if DEBUG
            // We should only see a trailingExpression if we're in a Script initializer.
            Debug.Assert(!hasTrailingExpression || method.IsScriptInitializer);
            var initialDiagnosticCount = diagnostics.ToReadOnly().Diagnostics.Length;
#endif
            var compilation = method.DeclaringCompilation;

            if (method.ReturnsVoid || method.IsIterator || method.IsAsyncEffectivelyReturningTask(compilation))
            {
                ImmutableArray <FieldSymbol> implicitlyInitializedFields = default;
                bool needsImplicitReturn = true;
                // we don't analyze synthesized void methods.
                if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) ||
                    Analyze(compilation, method, block, diagnostics.DiagnosticBag, out needsImplicitReturn, out implicitlyInitializedFields))
                {
                    if (!implicitlyInitializedFields.IsDefault)
                    {
                        Debug.Assert(!implicitlyInitializedFields.IsEmpty);
                        block = PrependImplicitInitializations(block, method, implicitlyInitializedFields, compilationState, diagnostics);
                    }
                    if (needsImplicitReturn)
                    {
                        block = AppendImplicitReturn(block, method, originalBodyNested);
                    }
                }
            }
            else if (Analyze(compilation, method, block, diagnostics.DiagnosticBag, out var needsImplicitReturn, out var unusedImplicitlyInitializedFields))
            {
                Debug.Assert(unusedImplicitlyInitializedFields.IsDefault);
                Debug.Assert(needsImplicitReturn);
                // If the method is a lambda expression being converted to a non-void delegate type
                // and the end point is reachable then suppress the error here; a special error
                // will be reported by the lambda binder.
                Debug.Assert(method.MethodKind != MethodKind.AnonymousFunction);

                // Add implicit "return default(T)" if this is a submission that does not have a trailing expression.
                var submissionResultType = (method as SynthesizedInteractiveInitializerMethod)?.ResultType;
                if (!hasTrailingExpression && ((object)submissionResultType != null))
                {
                    Debug.Assert(!submissionResultType.IsVoidType());

                    var trailingExpression = new BoundDefaultExpression(method.GetNonNullSyntaxNode(), submissionResultType);
                    var newStatements      = block.Statements.Add(new BoundReturnStatement(trailingExpression.Syntax, RefKind.None, trailingExpression, @checked: false));
                    block = new BoundBlock(block.Syntax, ImmutableArray <LocalSymbol> .Empty, newStatements)
                    {
                        WasCompilerGenerated = true
                    };
#if DEBUG
                    // It should not be necessary to repeat analysis after adding this node, because adding a trailing
                    // return in cases where one was missing should never produce different Diagnostics.
                    IEnumerable <Diagnostic> getErrorsOnly(IEnumerable <Diagnostic> diags) => diags.Where(d => d.Severity == DiagnosticSeverity.Error);

                    var flowAnalysisDiagnostics = DiagnosticBag.GetInstance();
                    Debug.Assert(!Analyze(compilation, method, block, flowAnalysisDiagnostics, needsImplicitReturn: out _, out unusedImplicitlyInitializedFields));
                    Debug.Assert(unusedImplicitlyInitializedFields.IsDefault);
                    // Ignore warnings since flow analysis reports nullability mismatches.
                    Debug.Assert(getErrorsOnly(flowAnalysisDiagnostics.ToReadOnly()).SequenceEqual(getErrorsOnly(diagnostics.ToReadOnly().Diagnostics.Skip(initialDiagnosticCount))));
                    flowAnalysisDiagnostics.Free();
#endif
                }
                // If there's more than one location, then the method is partial and we
                // have already reported a non-void partial method error.
                else if (method.Locations.Length == 1)
                {
                    diagnostics.Add(ErrorCode.ERR_ReturnExpected, method.Locations[0], method);
                }
            }

            return(block);
        }
Beispiel #18
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 #19
0
 public void AddAnError(BindingDiagnosticBag diagnostics)
 {
     diagnostics.Add(ErrorCode.ERR_InsufficientStack, GetTooLongOrComplexExpressionErrorLocation(Node));
 }
Beispiel #20
0
        private static void ReportNamesMismatchesIfAny(
            BoundExpression left,
            BoundExpression right,
            ImmutableArray <string> leftNames,
            ImmutableArray <string> rightNames,
            BindingDiagnosticBag diagnostics
            )
        {
            bool leftIsTupleLiteral  = left is BoundTupleExpression;
            bool rightIsTupleLiteral = right is BoundTupleExpression;

            if (!leftIsTupleLiteral && !rightIsTupleLiteral)
            {
                return;
            }

            bool leftNoNames  = leftNames.IsDefault;
            bool rightNoNames = rightNames.IsDefault;

            if (leftNoNames && rightNoNames)
            {
                return;
            }

            Debug.Assert(leftNoNames || rightNoNames || leftNames.Length == rightNames.Length);

            ImmutableArray <bool> leftInferred = leftIsTupleLiteral
                ? ((BoundTupleExpression)left).InferredNamesOpt
                : default;
            bool leftNoInferredNames = leftInferred.IsDefault;

            ImmutableArray <bool> rightInferred = rightIsTupleLiteral
                ? ((BoundTupleExpression)right).InferredNamesOpt
                : default;
            bool rightNoInferredNames = rightInferred.IsDefault;

            int length = leftNoNames ? rightNames.Length : leftNames.Length;

            for (int i = 0; i < length; i++)
            {
                string leftName  = leftNoNames ? null : leftNames[i];
                string rightName = rightNoNames ? null : rightNames[i];

                bool different = string.CompareOrdinal(rightName, leftName) != 0;
                if (!different)
                {
                    continue;
                }

                bool leftWasInferred  = leftNoInferredNames ? false : leftInferred[i];
                bool rightWasInferred = rightNoInferredNames ? false : rightInferred[i];

                bool leftComplaint  = leftIsTupleLiteral && leftName != null && !leftWasInferred;
                bool rightComplaint = rightIsTupleLiteral && rightName != null && !rightWasInferred;

                if (!leftComplaint && !rightComplaint)
                {
                    // No complaints, let's move on
                    continue;
                }

                // When in doubt, we'll complain on the right side if it's a literal
                bool useRight =
                    (leftComplaint && rightComplaint) ? rightIsTupleLiteral : rightComplaint;
                Location location =
                    ((BoundTupleExpression)(useRight ? right : left)).Arguments[
                        i
                    ].Syntax.Parent.Location;
                string complaintName = useRight ? rightName : leftName;

                diagnostics.Add(
                    ErrorCode.WRN_TupleBinopLiteralNameMismatch,
                    location,
                    complaintName
                    );
            }
        }
Beispiel #21
0
        private BoundExpression BindInterpolatedString(InterpolatedStringExpressionSyntax node, BindingDiagnosticBag diagnostics)
        {
            var builder = ArrayBuilder <BoundExpression> .GetInstance();

            var           stringType       = GetSpecialType(SpecialType.System_String, diagnostics, node);
            ConstantValue?resultConstant   = null;
            bool          isResultConstant = true;

            if (node.Contents.Count == 0)
            {
                resultConstant = ConstantValue.Create(string.Empty);
            }
            else
            {
                var objectType = GetSpecialType(SpecialType.System_Object, diagnostics, node);
                var intType    = GetSpecialType(SpecialType.System_Int32, diagnostics, node);
                foreach (var content in node.Contents)
                {
                    switch (content.Kind())
                    {
                    case SyntaxKind.Interpolation:
                    {
                        var interpolation = (InterpolationSyntax)content;
                        var value         = BindValue(interpolation.Expression, diagnostics, BindValueKind.RValue);
                        if (value.Type is null)
                        {
                            value = GenerateConversionForAssignment(objectType, value, diagnostics);
                        }
                        else
                        {
                            value = BindToNaturalType(value, diagnostics);
                            _     = GenerateConversionForAssignment(objectType, value, diagnostics);
                        }

                        // We need to ensure the argument is not a lambda, method group, etc. It isn't nice to wait until lowering,
                        // when we perform overload resolution, to report a problem. So we do that check by calling
                        // GenerateConversionForAssignment with objectType. However we want to preserve the original expression's
                        // natural type so that overload resolution may select a specialized implementation of string.Format,
                        // so we discard the result of that call and only preserve its diagnostics.
                        BoundExpression?alignment = null;
                        BoundLiteral?   format    = null;
                        if (interpolation.AlignmentClause != null)
                        {
                            alignment = GenerateConversionForAssignment(intType, BindValue(interpolation.AlignmentClause.Value, diagnostics, Binder.BindValueKind.RValue), diagnostics);
                            var alignmentConstant = alignment.ConstantValue;
                            if (alignmentConstant != null && !alignmentConstant.IsBad)
                            {
                                const int magnitudeLimit = 32767;
                                // check that the magnitude of the alignment is "in range".
                                int alignmentValue = alignmentConstant.Int32Value;
                                //  We do the arithmetic using negative numbers because the largest negative int has no corresponding positive (absolute) value.
                                alignmentValue = (alignmentValue > 0) ? -alignmentValue : alignmentValue;
                                if (alignmentValue < -magnitudeLimit)
                                {
                                    diagnostics.Add(ErrorCode.WRN_AlignmentMagnitude, alignment.Syntax.Location, alignmentConstant.Int32Value, magnitudeLimit);
                                }
                            }
                            else if (!alignment.HasErrors)
                            {
                                diagnostics.Add(ErrorCode.ERR_ConstantExpected, interpolation.AlignmentClause.Value.Location);
                            }
                        }

                        if (interpolation.FormatClause != null)
                        {
                            var  text = interpolation.FormatClause.FormatStringToken.ValueText;
                            char lastChar;
                            bool hasErrors = false;
                            if (text.Length == 0)
                            {
                                diagnostics.Add(ErrorCode.ERR_EmptyFormatSpecifier, interpolation.FormatClause.Location);
                                hasErrors = true;
                            }
                            else if (SyntaxFacts.IsWhitespace(lastChar = text[text.Length - 1]) || SyntaxFacts.IsNewLine(lastChar))
                            {
                                diagnostics.Add(ErrorCode.ERR_TrailingWhitespaceInFormatSpecifier, interpolation.FormatClause.Location);
                                hasErrors = true;
                            }

                            format = new BoundLiteral(interpolation.FormatClause, ConstantValue.Create(text), stringType, hasErrors);
                        }

                        builder.Add(new BoundStringInsert(interpolation, value, alignment, format, null));
                        if (!isResultConstant ||
                            value.ConstantValue == null ||
                            !(interpolation is { FormatClause: null, AlignmentClause: null }) ||
                            !(value.ConstantValue is { IsString: true, IsBad: false }))
        /// <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.AddAll(this, questionToken, type: null, 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 #23
0
        private bool ValidateAttributeUsage(
            CSharpAttributeData attribute,
            AttributeSyntax node,
            CSharpCompilation compilation,
            AttributeLocation symbolPart,
            BindingDiagnosticBag diagnostics,
            HashSet <NamedTypeSymbol> uniqueAttributeTypes
            )
        {
            Debug.Assert(!attribute.HasErrors);

            NamedTypeSymbol    attributeType      = attribute.AttributeClass;
            AttributeUsageInfo attributeUsageInfo = attributeType.GetAttributeUsageInfo();

            // Given attribute can't be specified more than once if AllowMultiple is false.
            if (!uniqueAttributeTypes.Add(attributeType) && !attributeUsageInfo.AllowMultiple)
            {
                diagnostics.Add(
                    ErrorCode.ERR_DuplicateAttribute,
                    node.Name.Location,
                    node.GetErrorDisplayName()
                    );
                return(false);
            }

            // Verify if the attribute type can be applied to given owner symbol.
            AttributeTargets attributeTarget;

            if (symbolPart == AttributeLocation.Return)
            {
                // attribute on return type
                Debug.Assert(this.Kind == SymbolKind.Method);
                attributeTarget = AttributeTargets.ReturnValue;
            }
            else
            {
                attributeTarget = this.GetAttributeTarget();
            }

            if ((attributeTarget & attributeUsageInfo.ValidTargets) == 0)
            {
                // generate error
                diagnostics.Add(
                    ErrorCode.ERR_AttributeOnBadSymbolType,
                    node.Name.Location,
                    node.GetErrorDisplayName(),
                    attributeUsageInfo.GetValidTargetsErrorArgument()
                    );
                return(false);
            }

            if (attribute.IsSecurityAttribute(compilation))
            {
                switch (this.Kind)
                {
                case SymbolKind.Assembly:
                case SymbolKind.NamedType:
                case SymbolKind.Method:
                    break;

                default:
                    // CS7070: Security attribute '{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations.
                    diagnostics.Add(
                        ErrorCode.ERR_SecurityAttributeInvalidTarget,
                        node.Name.Location,
                        node.GetErrorDisplayName()
                        );
                    return(false);
                }
            }

            return(true);
        }
Beispiel #24
0
        private static bool MatchAttributeTarget(
            IAttributeTargetSymbol attributeTarget,
            AttributeLocation symbolPart,
            AttributeTargetSpecifierSyntax targetOpt,
            BindingDiagnosticBag diagnostics
            )
        {
            IAttributeTargetSymbol attributesOwner = attributeTarget.AttributesOwner;

            // Determine if the target symbol owns the attribute declaration.
            // We need to report diagnostics only once, so do it when visiting attributes for the owner.
            bool isOwner =
                symbolPart == AttributeLocation.None &&
                ReferenceEquals(attributesOwner, attributeTarget);

            if (targetOpt == null)
            {
                // only attributes with an explicit target match if the symbol doesn't own the attributes:
                return(isOwner);
            }

            AttributeLocation allowedTargets = attributesOwner.AllowedAttributeLocations;

            AttributeLocation explicitTarget = targetOpt.GetAttributeLocation();

            if (explicitTarget == AttributeLocation.None)
            {
                // error: unknown attribute location
                if (isOwner)
                {
                    //NOTE: ValueText so that we accept targets like "@return", to match dev10 (DevDiv #2591).
                    diagnostics.Add(
                        ErrorCode.WRN_InvalidAttributeLocation,
                        targetOpt.Identifier.GetLocation(),
                        targetOpt.Identifier.ValueText,
                        allowedTargets.ToDisplayString()
                        );
                }

                return(false);
            }

            if ((explicitTarget & allowedTargets) == 0)
            {
                // error: invalid target for symbol
                if (isOwner)
                {
                    if (allowedTargets == AttributeLocation.None)
                    {
                        switch (attributeTarget.DefaultAttributeLocation)
                        {
                        case AttributeLocation.Assembly:
                        case AttributeLocation.Module:
                            // global attributes are disallowed in interactive code:
                            diagnostics.Add(
                                ErrorCode.ERR_GlobalAttributesNotAllowed,
                                targetOpt.Identifier.GetLocation()
                                );
                            break;

                        default:
                            // currently this can't happen
                            throw ExceptionUtilities.UnexpectedValue(
                                      attributeTarget.DefaultAttributeLocation
                                      );
                        }
                    }
                    else
                    {
                        diagnostics.Add(
                            ErrorCode.WRN_AttributeLocationOnBadDeclaration,
                            targetOpt.Identifier.GetLocation(),
                            targetOpt.Identifier.ToString(),
                            allowedTargets.ToDisplayString()
                            );
                    }
                }

                return(false);
            }

            if (symbolPart == AttributeLocation.None)
            {
                return(explicitTarget == attributeTarget.DefaultAttributeLocation);
            }
            else
            {
                return(explicitTarget == symbolPart);
            }
        }
Beispiel #25
0
        internal static BoundStatement Rewrite(
            BoundStatement bodyWithAwaitLifted,
            MethodSymbol method,
            int methodOrdinal,
            VariableSlotAllocator slotAllocatorOpt,
            TypeCompilationState compilationState,
            BindingDiagnosticBag diagnostics,
            out AsyncStateMachine stateMachineType
            )
        {
            if (!method.IsAsync)
            {
                stateMachineType = null;
                return(bodyWithAwaitLifted);
            }

            CSharpCompilation compilation      = method.DeclaringCompilation;
            bool isAsyncEnumerableOrEnumerator =
                method.IsAsyncReturningIAsyncEnumerable(compilation) ||
                method.IsAsyncReturningIAsyncEnumerator(compilation);

            if (isAsyncEnumerableOrEnumerator && !method.IsIterator)
            {
                bool containsAwait = AwaitDetector.ContainsAwait(bodyWithAwaitLifted);
                diagnostics.Add(
                    containsAwait
                      ? ErrorCode.ERR_PossibleAsyncIteratorWithoutYield
                      : ErrorCode.ERR_PossibleAsyncIteratorWithoutYieldOrAwait,
                    method.Locations[0],
                    method.ReturnTypeWithAnnotations
                    );

                stateMachineType = null;
                return(bodyWithAwaitLifted);
            }

            // The CLR doesn't support adding fields to structs, so in order to enable EnC in an async method we need to generate a class.
            // For async-iterators, we also need to generate a class.
            var typeKind =
                (compilationState.Compilation.Options.EnableEditAndContinue || method.IsIterator)
                    ? TypeKind.Class
                    : TypeKind.Struct;

            stateMachineType = new AsyncStateMachine(
                slotAllocatorOpt,
                compilationState,
                method,
                methodOrdinal,
                typeKind
                );
            compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(
                method,
                stateMachineType
                );

            AsyncRewriter rewriter = isAsyncEnumerableOrEnumerator
                ? new AsyncIteratorRewriter(
                bodyWithAwaitLifted,
                method,
                methodOrdinal,
                stateMachineType,
                slotAllocatorOpt,
                compilationState,
                diagnostics
                )
                : new AsyncRewriter(
                bodyWithAwaitLifted,
                method,
                methodOrdinal,
                stateMachineType,
                slotAllocatorOpt,
                compilationState,
                diagnostics
                );

            if (!rewriter.VerifyPresenceOfRequiredAPIs())
            {
                return(bodyWithAwaitLifted);
            }

            try
            {
                return(rewriter.Rewrite());
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
            {
                diagnostics.Add(ex.Diagnostic);
                return(new BoundBadStatement(
                           bodyWithAwaitLifted.Syntax,
                           ImmutableArray.Create <BoundNode>(bodyWithAwaitLifted),
                           hasErrors: true
                           ));
            }
        }
Beispiel #26
0
        internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnosticBag diagnostics)
        {
            var fromClause          = node.FromClause;
            var boundFromExpression = BindLeftOfPotentialColorColorMemberAccess(fromClause.Expression, diagnostics);

            // If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
            // Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
            if (boundFromExpression.HasDynamicType())
            {
                diagnostics.Add(ErrorCode.ERR_BadDynamicQuery, fromClause.Expression.Location);
                boundFromExpression = BadExpression(fromClause.Expression, boundFromExpression);
            }
            else
            {
                boundFromExpression = BindToNaturalType(boundFromExpression, diagnostics);
            }

            QueryTranslationState state = new QueryTranslationState();

            state.fromExpression = MakeMemberAccessValue(boundFromExpression, diagnostics);

            var x = state.rangeVariable = state.AddRangeVariable(this, fromClause.Identifier, diagnostics);

            for (int i = node.Body.Clauses.Count - 1; i >= 0; i--)
            {
                state.clauses.Push(node.Body.Clauses[i]);
            }

            state.selectOrGroup = node.Body.SelectOrGroup;

            // A from clause that explicitly specifies a range variable type
            //     from T x in e
            // is translated into
            //     from x in ( e ) . Cast < T > ( )
            BoundExpression?cast = null;

            if (fromClause.Type != null)
            {
                var typeRestriction = BindTypeArgument(fromClause.Type, diagnostics);
                cast = MakeQueryInvocation(fromClause, state.fromExpression, "Cast", fromClause.Type, typeRestriction, diagnostics);
                state.fromExpression = cast;
            }

            state.fromExpression = MakeQueryClause(fromClause, state.fromExpression, x, castInvocation: cast);
            BoundExpression result = BindQueryInternal1(state, diagnostics);

            for (QueryContinuationSyntax?continuation = node.Body.Continuation; continuation != null; continuation = continuation.Body.Continuation)
            {
                // A query expression with a continuation
                //     from ... into x ...
                // is translated into
                //     from x in ( from ... ) ...
                state.Clear();
                state.fromExpression = result;
                x = state.rangeVariable = state.AddRangeVariable(this, continuation.Identifier, diagnostics);
                Debug.Assert(state.clauses.IsEmpty());
                var clauses = continuation.Body.Clauses;
                for (int i = clauses.Count - 1; i >= 0; i--)
                {
                    state.clauses.Push(clauses[i]);
                }

                state.selectOrGroup = continuation.Body.SelectOrGroup;
                result = BindQueryInternal1(state, diagnostics);
                result = MakeQueryClause(continuation.Body, result, x);
                result = MakeQueryClause(continuation, result, x);
            }

            state.Free();
            return(MakeQueryClause(node, result));
        }
Beispiel #27
0
            private XNode[] RewriteIncludeElement(XElement includeElement, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax, out string commentMessage)
            {
                Location location = GetIncludeElementLocation(includeElement, ref currentXmlFilePath, ref originatingSyntax);

                Debug.Assert(originatingSyntax != null);

                bool diagnose = originatingSyntax.SyntaxTree.ReportDocumentationCommentDiagnostics();

                if (!EnterIncludeElement(location))
                {
                    // NOTE: these must exist since we're already processed this node elsewhere in the call stack.
                    XAttribute fileAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr      = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));
                    string     filePathValue = fileAttr.Value;
                    string     xpathValue    = pathAttr.Value;

                    if (diagnose)
                    {
                        _diagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new LocalizableErrorArgument(MessageID.IDS_OperationCausedStackOverflow));
                    }

                    commentMessage = ErrorFacts.GetMessage(MessageID.IDS_XMLNOINCLUDE, CultureInfo.CurrentUICulture);

                    // Don't inspect the children - we're already in a cycle.
                    return(new XNode[] { new XComment(commentMessage), includeElement.Copy(copyAttributeAnnotations: false) });
                }

                DiagnosticBag includeDiagnostics = DiagnosticBag.GetInstance();

                try
                {
                    XAttribute fileAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.FileAttributeName));
                    XAttribute pathAttr = includeElement.Attribute(XName.Get(DocumentationCommentXmlNames.PathAttributeName));

                    bool hasFileAttribute = fileAttr != null;
                    bool hasPathAttribute = pathAttr != null;
                    if (!hasFileAttribute || !hasPathAttribute)
                    {
                        var subMessage = hasFileAttribute ? MessageID.IDS_XMLMISSINGINCLUDEPATH.Localize() : MessageID.IDS_XMLMISSINGINCLUDEFILE.Localize();
                        includeDiagnostics.Add(ErrorCode.WRN_InvalidInclude, location, subMessage);
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLBADINCLUDE);
                        return(null);
                    }

                    string xpathValue    = pathAttr.Value;
                    string filePathValue = fileAttr.Value;

                    var resolver = _compilation.Options.XmlReferenceResolver;
                    if (resolver == null)
                    {
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.XmlReferencesNotSupported)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    string resolvedFilePath = resolver.ResolveReference(filePathValue, currentXmlFilePath);

                    if (resolvedFilePath == null)
                    {
                        // NOTE: same behavior as IOException.
                        includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, new CodeAnalysisResourcesLocalizableErrorArgument(nameof(CodeAnalysisResources.FileNotFound)));
                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                        return(null);
                    }

                    if (_includedFileCache == null)
                    {
                        _includedFileCache = new DocumentationCommentIncludeCache(resolver);
                    }

                    try
                    {
                        XDocument doc;

                        try
                        {
                            doc = _includedFileCache.GetOrMakeDocument(resolvedFilePath);
                        }
                        catch (IOException e)
                        {
                            // NOTE: same behavior as resolvedFilePath == null.
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, e.Message);
                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            return(null);
                        }

                        Debug.Assert(doc != null);

                        string     errorMessage;
                        bool       invalidXPath;
                        XElement[] loadedElements = XmlUtilities.TrySelectElements(doc, xpathValue, out errorMessage, out invalidXPath);
                        if (loadedElements == null)
                        {
                            includeDiagnostics.Add(ErrorCode.WRN_FailedInclude, location, filePathValue, xpathValue, errorMessage);

                            commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLFAILEDINCLUDE);
                            if (invalidXPath)
                            {
                                // leave the include node as is
                                return(null);
                            }

                            if (location.IsInSource)
                            {
                                // As in Dev11, return only the comment - drop the include element.
                                return(new XNode[] { new XComment(commentMessage) });
                            }
                            else
                            {
                                commentMessage = null;
                                return(Array.Empty <XNode>());
                            }
                        }

                        if (loadedElements != null && loadedElements.Length > 0)
                        {
                            // change the current XML file path for nodes contained in the document:
                            XNode[] result = RewriteMany(loadedElements, resolvedFilePath, originatingSyntax);

                            // The elements could be rewritten away if they are includes that refer to invalid
                            // (but existing and accessible) XML files.  If this occurs, behave as if we
                            // had failed to find any XPath results (as in Dev11).
                            if (result.Length > 0)
                            {
                                // NOTE: in this case, we do NOT visit the children of the include element -
                                // they are dropped.
                                commentMessage = null;
                                return(result);
                            }
                        }

                        commentMessage = MakeCommentMessage(location, MessageID.IDS_XMLNOINCLUDE);
                        return(null);
                    }
                    catch (XmlException e)
                    {
                        // NOTE: invalid XML is handled differently from other errors - we don't include the include element
                        // in the results and the location is in the included (vs includING) file.

                        Location errorLocation = XmlLocation.Create(e, resolvedFilePath);
                        includeDiagnostics.Add(ErrorCode.WRN_XMLParseIncludeError, errorLocation, GetDescription(e)); //NOTE: location is in included file.

                        if (location.IsInSource)
                        {
                            commentMessage = string.Format(ErrorFacts.GetMessage(MessageID.IDS_XMLIGNORED2, CultureInfo.CurrentUICulture), resolvedFilePath);

                            // As in Dev11, return only the comment - drop the include element.
                            return(new XNode[] { new XComment(commentMessage) });
                        }
                        else
                        {
                            commentMessage = null;
                            return(Array.Empty <XNode>());
                        }
                    }
                }
                finally
                {
                    if (diagnose)
                    {
                        _diagnostics.AddRange(includeDiagnostics);
                    }

                    includeDiagnostics.Free();

                    LeaveIncludeElement(location);
                }
            }
 static void reportTypeConstraintsMustBeUniqueAndFirst(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics)
 {
     diagnostics.Add(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, syntax.GetLocation());
 }
        /// <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() !);
        }
 private void Error(ErrorCode code, BoundNode node, params object[] args)
 {
     _diagnostics.Add(code, node.Syntax.Location, args);
 }