internal SourceMemberFieldSymbol(
            SourceMemberContainerTypeSymbol containingType,
            VariableDeclaratorSyntax declarator,
            DeclarationModifiers modifiers,
            bool modifierErrors,
            DiagnosticBag diagnostics)
            : base(containingType, declarator.Identifier.ValueText, declarator.GetReference(), declarator.Identifier.GetLocation())
        {
            this.modifiers = modifiers;

            this.CheckAccessibility(diagnostics);

            var location = Location;
            if (modifierErrors)
            {
                // skip the following checks
            }
            else if (containingType.IsSealed && (DeclaredAccessibility == Accessibility.Protected || DeclaredAccessibility == Accessibility.ProtectedOrInternal))
            {
                diagnostics.Add(AccessCheck.GetProtectedMemberInSealedTypeError(containingType), location, this);
            }
            else if (IsVolatile && IsReadOnly)
            {
                diagnostics.Add(ErrorCode.ERR_VolatileAndReadonly, location, this);
            }
            else if (containingType.IsStatic && !IsStatic)
            {
                diagnostics.Add(ErrorCode.ERR_InstanceMemberInStaticClass, location, this);
            }

            // TODO: Consider checking presence of core type System.Runtime.CompilerServices.IsVolatile 
            // if there is a volatile modifier. Perhaps an appropriate error should be reported if the 
            // type isn’t available.
        }
Exemple #2
0
        internal static DeclarationModifiers CheckModifiers(
            DeclarationModifiers modifiers,
            DeclarationModifiers allowedModifiers,
            Location errorLocation,
            DiagnosticBag diagnostics,
            out bool modifierErrors)
        {
            modifierErrors = false;
            DeclarationModifiers errorModifiers = modifiers & ~allowedModifiers;
            DeclarationModifiers result = modifiers & allowedModifiers;
            while (errorModifiers != DeclarationModifiers.None)
            {
                DeclarationModifiers oneError = errorModifiers & ~(errorModifiers - 1);
                Debug.Assert(oneError != DeclarationModifiers.None);
                errorModifiers = errorModifiers & ~oneError;
                switch (oneError)
                {
                    case DeclarationModifiers.Partial:
                        diagnostics.Add(ErrorCode.ERR_PartialMethodOnlyMethods, errorLocation);
                        break;

                    default:
                        diagnostics.Add(ErrorCode.ERR_BadMemberFlag, errorLocation, ConvertSingleModifierToSyntaxText(oneError));
                        break;
                }
                modifierErrors = true;
            }

            bool isMethod = (allowedModifiers & (DeclarationModifiers.Partial | DeclarationModifiers.Virtual)) == (DeclarationModifiers.Partial | DeclarationModifiers.Virtual);
            if (isMethod && ((result & (DeclarationModifiers.Partial | DeclarationModifiers.Private)) == (DeclarationModifiers.Partial | DeclarationModifiers.Private)))
            {
                diagnostics.Add(ErrorCode.ERR_PartialMethodInvalidModifier, errorLocation);
            }
            return result;
        }
        protected override void MethodChecks(DiagnosticBag diagnostics)
        {
            var syntax = (ConstructorDeclarationSyntax)syntaxReference.GetSyntax();
            var binderFactory = this.DeclaringCompilation.GetBinderFactory(syntaxReference.SyntaxTree);

            // NOTE: if we asked for the binder for the body of the constructor, we'd risk a stack overflow because
            // we might still be constructing the member list of the containing type.  However, getting the binder
            // for the parameters should be safe.
            var bodyBinder = binderFactory.GetBinder(syntax.ParameterList).WithContainingMemberOrLambda(this);

            SyntaxToken arglistToken;
            this.lazyParameters = ParameterHelpers.MakeParameters(bodyBinder, this, syntax.ParameterList, true, out arglistToken, diagnostics);
            this.lazyIsVararg = (arglistToken.CSharpKind() == SyntaxKind.ArgListKeyword);
            this.lazyReturnType = bodyBinder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax);

            if (MethodKind == MethodKind.StaticConstructor && (lazyParameters.Length != 0))
            {
                diagnostics.Add(ErrorCode.ERR_StaticConstParam, Locations[0], this);
            }

            this.CheckEffectiveAccessibility(lazyReturnType, lazyParameters, diagnostics);

            if (this.lazyIsVararg && (IsGenericMethod || ContainingType.IsGenericType || this.lazyParameters.Length > 0 && this.lazyParameters[this.lazyParameters.Length - 1].IsParams))
            {
                diagnostics.Add(ErrorCode.ERR_BadVarargs, Locations[0]);
            }
        }
        private SourceConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            ConstructorDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body.GetReferenceOrNull(), ImmutableArray.Create(location))
        {
            bool modifierErrors;
            var declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, location, diagnostics, out modifierErrors);
            this.flags = MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false);

            var bodyOpt = syntax.Body;
            if (bodyOpt != null)
            {
                if (IsExtern)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
                this.CheckModifiers(methodKind, location, diagnostics);
            }
        }
        private void TypeChecks(TypeSymbol type, BaseFieldDeclarationSyntax fieldSyntax, VariableDeclaratorSyntax declarator, DiagnosticBag diagnostics)
        {
            if (type.IsStatic)
            {
                // Cannot declare a variable of static type '{0}'
                diagnostics.Add(ErrorCode.ERR_VarDeclIsStaticClass, this.Location, type);
            }
            else if (type.SpecialType == SpecialType.System_Void)
            {
                diagnostics.Add(ErrorCode.ERR_FieldCantHaveVoidType, fieldSyntax.Declaration.Type.Location);
            }
            else if (type.IsRestrictedType())
            {
                diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, fieldSyntax.Declaration.Type.Location, type);
            }
            else if (IsConst && !type.CanBeConst())
            {
                SyntaxToken constToken = default(SyntaxToken);
                foreach (var modifier in fieldSyntax.Modifiers)
                {
                    if (modifier.CSharpKind() == SyntaxKind.ConstKeyword)
                    {
                        constToken = modifier;
                        break;
                    }
                }
                Debug.Assert(constToken.CSharpKind() == SyntaxKind.ConstKeyword);

                diagnostics.Add(ErrorCode.ERR_BadConstType, constToken.GetLocation(), type);
            }
            else
            {
                if (ContainingType.TypeKind == TypeKind.Struct && !IsStatic && !IsConst)
                {
                    var initializerOpt = declarator.Initializer;
                    if (initializerOpt != null)
                    {
                        // '{0}': cannot have instance field initializers in structs
                        diagnostics.Add(ErrorCode.ERR_FieldInitializerInStruct, this.Location, this);
                    }
                }

                if (IsVolatile && !type.IsValidVolatileFieldType())
                {
                    // '{0}': a volatile field cannot be of the type '{1}'
                    diagnostics.Add(ErrorCode.ERR_VolatileStruct, this.Location, this, type);
                }
            }

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            if (!this.IsNoMoreVisibleThan(type, ref useSiteDiagnostics))
            {
                // Inconsistent accessibility: field type '{1}' is less accessible than field '{0}'
                diagnostics.Add(ErrorCode.ERR_BadVisFieldType, this.Location, this, type);
            }

            diagnostics.Add(this.Location, useSiteDiagnostics);
        }
        public void DiagnosticBag()
        {
            DiagnosticBag bag1 = new DiagnosticBag();
            bag1.Add(CreateDiagnostic(4));
            bag1.Add(CreateDiagnostic(7));
            Assert.False(bag1.IsEmpty);
            Assert.Equal(2, bag1.Count());
            Assert.NotNull(bag1.ToString());

            bool found4 = false, found7 = false;
            foreach (Diagnostic d in bag1)
            {
                if (d.Code == 4)
                {
                    Assert.False(found4);
                    found4 = true;
                }
                else if (d.Code == 7)
                {
                    Assert.False(found7);
                    found7 = true;
                }
                else
                    Assert.True(false);
            }

            DiagnosticBag bag2 = new DiagnosticBag();
            bag1.Add(bag2);
            Assert.False(bag1.IsEmpty);
            Assert.Equal(2, bag1.Count());

            found4 = false; found7 = false;
            foreach (Diagnostic d in bag1)
            {
                if (d.Code == 4)
                {
                    Assert.False(found4);
                    found4 = true;
                }
                else if (d.Code == 7)
                {
                    Assert.False(found7);
                    found7 = true;
                }
                else
                    Assert.True(false);
            }

            DiagnosticBag bag3 = new DiagnosticBag();
            bag3.Add(CreateDiagnostic(3));
            bag3.Add(CreateDiagnostic(2));
            bag3.Add(CreateDiagnostic(1));
            bag1.Add(bag3);
            Assert.False(bag1.IsEmpty);
            Assert.Equal(5, bag1.Count());
        }
        /// <summary>
        /// This is a clone of the Dev10 logic for reporting query errors.
        /// </summary>
        internal void ReportQueryLookupFailed(
            CSharpSyntaxNode queryClause,
            BoundExpression instanceArgument,
            string name,
            ImmutableArray<Symbol> symbols,
            DiagnosticBag diagnostics)
        {
            FromClauseSyntax fromClause = null;
            for (CSharpSyntaxNode node = queryClause; ; node = node.Parent)
            {
                var e = node as QueryExpressionSyntax;
                if (e != null)
                {
                    fromClause = e.FromClause;
                    break;
                }
            }

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;

            if (instanceArgument.Type.IsDynamic())
            {
                // CS1979: Query expressions over source type 'dynamic' or with a join sequence of type 'dynamic' are not allowed
                diagnostics.Add(
                    new DiagnosticInfoWithSymbols(ErrorCode.ERR_BadDynamicQuery, SpecializedCollections.EmptyObjects, symbols),
                    new SourceLocation(queryClause));
            }
            else if (ImplementsStandardQueryInterface(instanceArgument.Type, name, ref useSiteDiagnostics))
            {
                // Could not find an implementation of the query pattern for source type '{0}'.  '{1}' not found.  Are you missing a reference to 'System.Core.dll' or a using directive for 'System.Linq'?
                diagnostics.Add(new DiagnosticInfoWithSymbols(
                    ErrorCode.ERR_QueryNoProviderStandard,
                    new object[] { instanceArgument.Type, name },
                    symbols), new SourceLocation(fromClause != null ? fromClause.Expression : queryClause));
            }
            else if (fromClause != null && fromClause.Type == null && HasCastToQueryProvider(instanceArgument.Type, ref useSiteDiagnostics))
            {
                // Could not find an implementation of the query pattern for source type '{0}'.  '{1}' not found.  Consider explicitly specifying the type of the range variable '{2}'.
                diagnostics.Add(new DiagnosticInfoWithSymbols(
                    ErrorCode.ERR_QueryNoProviderCastable,
                    new object[] { instanceArgument.Type, name, fromClause.Identifier.ValueText },
                    symbols), new SourceLocation(fromClause.Expression));
            }
            else
            {
                // Could not find an implementation of the query pattern for source type '{0}'.  '{1}' not found.
                diagnostics.Add(new DiagnosticInfoWithSymbols(
                    ErrorCode.ERR_QueryNoProvider,
                    new object[] { instanceArgument.Type, name },
                    symbols), new SourceLocation(fromClause != null ? fromClause.Expression : queryClause));
            }

            diagnostics.Add(queryClause, useSiteDiagnostics);
        }
Exemple #8
0
        /// <summary>
        /// The flow analysis pass.  This pass reports required diagnostics for unreachable
        /// statements and uninitialized variables (through the call to FlowAnalysisWalker.Analyze),
        /// and inserts a final return statement if the end of a void-returning method is reachable.
        /// </summary>
        /// <param name="method">the method to be analyzed</param>
        /// <param name="block">the method's body</param>
        /// <param name="diagnostics">the receiver of the reported diagnostics</param>
        /// <returns>the rewritten block for the method (with a return statement possibly inserted)</returns>
        public static BoundBlock Rewrite(
            MethodSymbol method,
            BoundBlock block,
            DiagnosticBag diagnostics)
        {
            var compilation = method.DeclaringCompilation;

            if (method.ReturnsVoid || (object)method.IteratorElementType != null
                || (method.IsAsync && compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) == method.ReturnType))
            {
                if (method.IsImplicitlyDeclared || Analyze(compilation, method, block, diagnostics))
                {
                    // we don't analyze synthesized void methods.
                    var sourceMethod = method as SourceMethodSymbol;
                    block = AppendImplicitReturn(block, method, (object)sourceMethod != null ? sourceMethod.BlockSyntax : null);
                }
            }
            else if (Analyze(compilation, method, block, diagnostics))
            {
                // 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);

                // If there's more than one location, then the method is partial and we
                // have already reported a non-void partial method error.
                if (method.Locations.Length == 1)
                {
                    diagnostics.Add(ErrorCode.ERR_ReturnExpected, method.Locations[0], method);
                }
            }

            return block;
        }
Exemple #9
0
 internal void Add(DiagnosticInfo?info, Location location)
 {
     if (info is object)
     {
         DiagnosticBag?.Add(info, location);
     }
 }
        /// <summary>
        /// Determine the effective base type, effective interface set, and set of type
        /// parameters (excluding cycles) from the type parameter constraints. Conflicts
        /// within the constraints and constraint types are returned as diagnostics.
        /// 'inherited' should be true if the type parameters are from an overridden
        /// generic method. In those cases, additional constraint checks are applied.
        /// </summary>
        public static TypeParameterBounds ResolveBounds(
            this TypeParameterSymbol typeParameter,
            AssemblySymbol corLibrary,
            ConsList<TypeParameterSymbol> inProgress,
            ImmutableArray<TypeSymbol> constraintTypes,
            bool inherited,
            CSharpCompilation currentCompilation,
            DiagnosticBag diagnostics)
        {
            var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance();
            ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null;
            var bounds = typeParameter.ResolveBounds(corLibrary, inProgress, constraintTypes, inherited, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder);

            if (useSiteDiagnosticsBuilder != null)
            {
                diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder);
            }

            foreach (var pair in diagnosticsBuilder)
            {
                diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, pair.TypeParameter.Locations[0]));
            }

            diagnosticsBuilder.Free();
            return bounds;
        }
        // NOTE: Specifically not overriding IsIndirectlyInIterator.

        internal override TypeSymbol GetIteratorElementType(YieldStatementSyntax node, DiagnosticBag diagnostics)
        {
            if (node != null)
            {
                diagnostics.Add(ErrorCode.ERR_YieldInAnonMeth, node.YieldKeyword.GetLocation());
            }
            return CreateErrorType();
        }
        private void AddDelegateMembers(
            ArrayBuilder<Symbol> symbols,
            DelegateDeclarationSyntax syntax,
            BinderFactory binderFactory,
            DiagnosticBag diagnostics)
        {
            var bodyBinder = binderFactory.GetBinder(syntax.ParameterList);

            // A delegate has the following members: (see CLI spec 13.6)
            // (1) a method named Invoke with the specified signature
            var invoke = new DelegateInvokeMethodImplementation(this, syntax, bodyBinder, diagnostics);
            invoke.CheckMethodVarianceSafety(diagnostics);
            symbols.Add(invoke);

            // (2) a constructor with argument types (object, System.IntPtr)
            symbols.Add(new DelegateConstructor(this, syntax, bodyBinder));

            var delegateBinder = new DelegateBinder(bodyBinder, this, invoke);

            // (3) BeginInvoke
            symbols.Add(new DelegateBeginInvokeMethod(this, syntax, delegateBinder, diagnostics));

            // and (4) EndInvoke methods
            symbols.Add(new DelegateEndInvokeMethod(this, syntax, delegateBinder, diagnostics));

            if (this.DeclaredAccessibility <= Accessibility.Private)
            {
                return;
            }

            if (!this.IsNoMoreVisibleThan(invoke.ReturnType))
            {
                // Inconsistent accessibility: return type '{1}' is less accessible than delegate '{0}'
                diagnostics.Add(ErrorCode.ERR_BadVisDelegateReturn, Locations[0], this, invoke.ReturnType);
            }

            foreach (var parameter in invoke.Parameters)
            {
                if (!parameter.Type.IsAtLeastAsVisibleAs(this))
                {
                    // Inconsistent accessibility: parameter type '{1}' is less accessible than delegate '{0}'
                    diagnostics.Add(ErrorCode.ERR_BadVisDelegateParam, Locations[0], this, parameter.Type);
                }
            }

        }
 protected SourceEnumConstantSymbol(SourceMemberContainerTypeSymbol containingEnum, EnumMemberDeclarationSyntax syntax, DiagnosticBag diagnostics)
     : base(containingEnum, syntax.Identifier.ValueText, syntax.GetReference(), syntax.Identifier.GetLocation())
 {
     if (this.Name == WellKnownMemberNames.EnumBackingFieldName)
     {
         diagnostics.Add(ErrorCode.ERR_ReservedEnumerator, this.Location, WellKnownMemberNames.EnumBackingFieldName);
     }
 }
 internal override CSDiagnosticInfo NotFound(Location location, string name, DiagnosticBag diagnostics)
 {
     return diagnostics.Add(
         ReferenceEquals(qualifier, Compilation.GlobalNamespace) ? ErrorCode.ERR_GlobalSingleTypeNameNotFound :
             qualifier.IsNamespace ? ErrorCode.ERR_DottedTypeNameNotFoundInNS :
             ErrorCode.ERR_DottedTypeNameNotFoundInAgg,
         location, name, qualifier.GetFullName());
 }
        /// <summary>
        /// The flow analysis pass.  This pass reports required diagnostics for unreachable
        /// statements and uninitialized variables (through the call to FlowAnalysisWalker.Analyze),
        /// and inserts a final return statement if the end of a void-returning method is reachable.
        /// </summary>
        /// <param name="method">the method to be analyzed</param>
        /// <param name="block">the method's body</param>
        /// <param name="diagnostics">the receiver of the reported diagnostics</param>
        /// <param name="hasTrailingExpression">indicates whether this Script had a trailing expression</param>
        /// <param name="originalBodyNested">the original method body is the last statement in the block</param>
        /// <returns>the rewritten block for the method (with a return statement possibly inserted)</returns>
        public static BoundBlock Rewrite(
            MethodSymbol method,
            BoundBlock block,
            DiagnosticBag 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().Length;
#endif
            var compilation = method.DeclaringCompilation;

            if (method.ReturnsVoid || method.IsIterator ||
                (method.IsAsync && compilation.GetWellKnownType(WellKnownType.System_Threading_Tasks_Task) == method.ReturnType))
            {
                // we don't analyze synthesized void methods.
                if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) || Analyze(compilation, method, block, diagnostics))
                {
                    block = AppendImplicitReturn(block, method, (CSharpSyntaxNode)(method as SourceMethodSymbol)?.BodySyntax, originalBodyNested);
                }
            }
            else if (Analyze(compilation, method, block, diagnostics))
            {
                // 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.SpecialType != SpecialType.System_Void);

                    var trailingExpression = new BoundDefaultOperator(method.GetNonNullSyntaxNode(), submissionResultType);
                    var newStatements = block.Statements.Add(new BoundReturnStatement(trailingExpression.Syntax, trailingExpression));
                    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.
                    var flowAnalysisDiagnostics = DiagnosticBag.GetInstance();
                    Debug.Assert(!Analyze(compilation, method, block, flowAnalysisDiagnostics));
                    Debug.Assert(flowAnalysisDiagnostics.ToReadOnly().SequenceEqual(diagnostics.ToReadOnly().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;
        }
        internal override ConstantValue GetConstantValue(SyntaxNode node, LocalSymbol inProgress, DiagnosticBag diagnostics)
        {
            if (diagnostics != null && _value.IsBad)
            {
                diagnostics.Add(ErrorCode.ERR_BadPdbData, Location.None, Name);
            }

            return _value;
        }
        protected BoundExpression CreateConversion(
            BoundExpression source,
            TypeSymbol destination,
            DiagnosticBag diagnostics)
        {
            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            var conversion = Conversions.ClassifyConversionFromExpression(source, destination, ref useSiteDiagnostics);

            diagnostics.Add(source.Syntax, useSiteDiagnostics);
            return CreateConversion(source.Syntax, source, conversion, isCast: false, destination: destination, diagnostics: diagnostics);
        }
Exemple #18
0
        /// <returns>True if a diagnostic was reported, or would have been reported if not for
        /// the suppress flag.</returns>
        private bool ReportUnsafeIfNotAllowed(Location location, TypeSymbol sizeOfTypeOpt, DiagnosticBag diagnostics)
        {
            var diagnosticInfo = GetUnsafeDiagnosticInfo(sizeOfTypeOpt);
            if (diagnosticInfo == null || this.Flags.Includes(BinderFlags.SuppressUnsafeDiagnostics))
            {
                return false;
            }

            diagnostics.Add(new CSDiagnostic(diagnosticInfo, location));
            return true;
        }
        /// <summary>
        /// Traverses the symbol table checking for CLS compliance.
        /// </summary>
        /// <param name="compilation">Compilation that owns the symbol table.</param>
        /// <param name="diagnostics">Will be supplemented with documentation comment diagnostics.</param>
        /// <param name="cancellationToken">To stop traversing the symbol table early.</param>
        /// <param name="filterTree">Only report diagnostics from this syntax tree, if non-null.</param>
        /// <param name="filterSpanWithinTree">If <paramref name="filterTree"/> and <paramref name="filterSpanWithinTree"/> is non-null, report diagnostics within this span in the <paramref name="filterTree"/>.</param>
        public static void CheckCompliance(CSharpCompilation compilation, DiagnosticBag diagnostics, CancellationToken cancellationToken, SyntaxTree filterTree = null, TextSpan? filterSpanWithinTree = null)
        {
            var queue = new ConcurrentQueue<Diagnostic>();
            var checker = new ClsComplianceChecker(compilation, filterTree, filterSpanWithinTree, queue, cancellationToken);
            checker.Visit(compilation.Assembly);

            foreach (Diagnostic diag in queue)
            {
                diagnostics.Add(diag);
            }
        }
        internal SourceDestructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            DestructorDeclarationSyntax syntax,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference() , syntax.Identifier.GetLocation())
        {
            const MethodKind methodKind = MethodKind.Destructor;
            Location location = this.Locations[0];

            bool modifierErrors;
            var declarationModifiers = MakeModifiers(syntax.Modifiers, location, diagnostics, out modifierErrors);
            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false);

            bool hasBlockBody = syntax.Body != null;
            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;

            if (hasBlockBody || _isExpressionBodied)
            {
                if (IsExtern)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

            if (!modifierErrors && bodySyntaxReferenceOpt == null && !IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            Debug.Assert(syntax.ParameterList.Parameters.Count == 0);

            if (containingType.IsStatic)
            {
                diagnostics.Add(ErrorCode.ERR_DestructorInStaticClass, location, this);
            }
            else if (!containingType.IsReferenceType)
            {
                diagnostics.Add(ErrorCode.ERR_OnlyClassesCanContainDestructors, location, this);
            }
        }
        private SourceConstructorSymbol(
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            ConstructorDeclarationSyntax syntax,
            MethodKind methodKind,
            DiagnosticBag diagnostics) :
            base(containingType, syntax.GetReference(), syntax.Body?.GetReference() ?? syntax.ExpressionBody?.GetReference(), ImmutableArray.Create(location))
        {
            bool modifierErrors;
            var declarationModifiers = this.MakeModifiers(syntax.Modifiers, methodKind, location, diagnostics, out modifierErrors);
            this.MakeFlags(methodKind, declarationModifiers, returnsVoid: true, isExtensionMethod: false);

            bool hasBlockBody = syntax.Body != null;
            _isExpressionBodied = !hasBlockBody && syntax.ExpressionBody != null;

            if (IsExtern)
            {
                if (methodKind == MethodKind.Constructor && syntax.Initializer != null)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasConstructorInitializer, location, this);
                }

                if (hasBlockBody || _isExpressionBodied)
                {
                    diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
                }
            }

            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);
            if (info != null)
            {
                diagnostics.Add(info, location);
            }

            if (!modifierErrors)
            {
                this.CheckModifiers(methodKind, location, diagnostics);
            }
        }
        // Returns deterministically ordered list of variables that ought to be hoisted.
        public static OrderedSet<Symbol> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node, DiagnosticBag diagnostics)
        {
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, convertInsufficientExecutionStackExceptionToCancelledByStackGuardException: true);
            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, new NeverEmptyStructTypeCache(), initiallyAssignedVariables);

            walker._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true;

            bool badRegion = false;
            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                walker.CaptureVariable(method.ThisParameter, node.Syntax);
            }

            var variablesToHoist = walker._variablesToHoist;
            var lazyDisallowedCaptures = walker._lazyDisallowedCaptures;
            var allVariables = walker.variableBySlot;

            walker.Free();

            if (lazyDisallowedCaptures != null)
            {
                foreach (var kvp in lazyDisallowedCaptures)
                {
                    var variable = kvp.Key;
                    var type = (variable.Kind == SymbolKind.Local) ? ((LocalSymbol)variable).Type : ((ParameterSymbol)variable).Type;

                    foreach (CSharpSyntaxNode syntax in kvp.Value)
                    {
                        // CS4013: Instance of type '{0}' cannot be used inside an anonymous function, query expression, iterator block or async method
                        diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, type);
                    }
                }
            }

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

                // In debug build we hoist all locals and parameters:
                variablesToHoist.AddRange(from v in allVariables
                                          where v.Symbol != null && HoistInDebugBuild(v.Symbol)
                                          select v.Symbol);
            }

            return variablesToHoist;
        }
 private static void ReportErrorOnSpecialMember(Symbol symbol, SpecialMember member, DiagnosticBag diagnostics, ref bool hasError)
 {
     if ((object)symbol == null)
     {
         MemberDescriptor memberDescriptor = SpecialMembers.GetDescriptor(member);
         diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, NoLocation.Singleton,
             ((SpecialType)memberDescriptor.DeclaringTypeId).GetMetadataName(), memberDescriptor.Name);
         hasError = true;
     }
     else
     {
         ReportErrorOnSymbol(symbol, diagnostics, ref hasError);
     }
 }
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = this.GetNonNullSyntaxNode();
            SyntheticBoundNodeFactory factory = new SyntheticBoundNodeFactory(this, syntax, compilationState, diagnostics);
            factory.CurrentMethod = this;
            ArrayBuilder<BoundStatement> body = ArrayBuilder<BoundStatement>.GetInstance();

            // Initialize the payload root for each kind of dynamic analysis instrumentation.
            // A payload root is an array of arrays of per-method instrumentation payloads.
            // For each kind of instrumentation:
            //
            //     payloadRoot = new T[MaximumMethodDefIndex + 1][];
            //
            // where T is the type of the payload at each instrumentation point, and MaximumMethodDefIndex is the 
            // index portion of the greatest method definition token in the compilation. This guarantees that any
            // method can use the index portion of its own method definition token as an index into the payload array.

            try
            {
                foreach (KeyValuePair<int, InstrumentationPayloadRootField> payloadRoot in ContainingPrivateImplementationDetailsType.GetInstrumentationPayloadRoots())
                {
                    int analysisKind = payloadRoot.Key;
                    ArrayTypeSymbol payloadArrayType = (ArrayTypeSymbol)payloadRoot.Value.Type;

                    BoundStatement payloadInitialization =
                        factory.Assignment(
                            factory.InstrumentationPayloadRoot(analysisKind, payloadArrayType),
                            factory.Array(payloadArrayType.ElementType, factory.Binary(BinaryOperatorKind.Addition, factory.SpecialType(SpecialType.System_Int32), factory.MaximumMethodDefIndex(), factory.Literal(1))));
                    body.Add(payloadInitialization);
                }

                // Initialize the module version ID (MVID) field. Dynamic instrumentation requires the MVID of the executing module, and this field makes that accessible.
                // MVID = Guid.Parse(ModuleVersionIdString);
                body.Add(
                    factory.Assignment(
                       factory.ModuleVersionId(),
                       factory.StaticCall(
                           WellKnownMember.System_Guid__Parse,
                           factory.ModuleVersionIdString())));
            }
            catch (SyntheticBoundNodeFactory.MissingPredefinedMember missing)
            {
                diagnostics.Add(missing.Diagnostic);
            }

            BoundStatement returnStatement = factory.Return();
            body.Add(returnStatement);

            factory.CloseMethod(factory.Block(body.ToImmutableAndFree()));
        }
            public override Stream CreateStream(DiagnosticBag diagnostics)
            {
                Debug.Assert(_streamToDispose == null);

                try
                {
                    return _streamToDispose = _compiler.FileOpen(_filePath, PortableShim.FileMode.Create, PortableShim.FileAccess.ReadWrite, PortableShim.FileShare.None);
                }
                catch (Exception e)
                {
                    var messageProvider = _compiler.MessageProvider;
                    diagnostics.Add(messageProvider.CreateDiagnostic(messageProvider.ERR_CantOpenFileWrite, Location.None, _filePath, e.Message));
                    return null;
                }
            }
 private static void ReportErrorOnWellKnownMember(Symbol symbol, WellKnownMember member, DiagnosticBag diagnostics, ref bool hasError)
 {
     if ((object)symbol == null)
     {
         MemberDescriptor memberDescriptor = WellKnownMembers.GetDescriptor(member);
         diagnostics.Add(ErrorCode.ERR_MissingPredefinedMember, NoLocation.Singleton,
             memberDescriptor.DeclaringTypeMetadataName, memberDescriptor.Name);
         hasError = true;
     }
     else
     {
         ReportErrorOnSymbol(symbol, diagnostics, ref hasError);
         ReportErrorOnSymbol(symbol.ContainingType, diagnostics, ref hasError);
     }
 }
Exemple #27
0
        private ImmutableArray<Symbol> BindTypeCref(TypeCrefSyntax syntax, out Symbol ambiguityWinner, DiagnosticBag 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)
            {
                diagnostics.Add(ErrorCode.WRN_BadXMLRef, syntax.Location, syntax.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 TypeParameterSymbol MakeSymbol(int ordinal, IList<TypeParameterBuilder> builders, DiagnosticBag diagnostics)
        {
            var syntaxNode = (TypeParameterSyntax)this.syntaxRef.GetSyntax();
            var result = new SourceTypeParameterSymbol(
                this.owner,
                syntaxNode.Identifier.ValueText,
                ordinal,
                syntaxNode.VarianceKeyword.VarianceKindFromToken(),
                ToLocations(builders),
                ToSyntaxRefs(builders));

            if (result.Name == result.ContainingSymbol.Name)
            {
                diagnostics.Add(ErrorCode.ERR_TypeVariableSameAsParent, result.Locations[0], result.Name);
            }

            return result;
        }
 private AsyncRewriter(
     BoundStatement body,
     MethodSymbol method,
     AsyncStateMachine stateMachineClass,
     TypeCompilationState compilationState,
     DiagnosticBag diagnostics)
     : base(body, method, stateMachineClass, compilationState, diagnostics)
 {
     try
     {
         constructedSuccessfully = AsyncMethodBuilderMemberCollection.TryCreate(F, method, this.stateMachineClass.TypeMap, out this.asyncMethodBuilderMemberCollection);
     }
     catch (SyntheticBoundNodeFactory.MissingPredefinedMember ex)
     {
         diagnostics.Add(ex.Diagnostic);
         constructedSuccessfully = false;
     }
 }
        internal SynthesizedSubmissionConstructor(NamedTypeSymbol containingType, DiagnosticBag diagnostics)
            : base(containingType)
        {
            Debug.Assert(containingType.TypeKind == TypeKind.Submission);
            Debug.Assert(diagnostics != null);

            var compilation = containingType.DeclaringCompilation;

            var submissionArrayType = compilation.CreateArrayTypeSymbol(compilation.GetSpecialType(SpecialType.System_Object));
            var useSiteError = submissionArrayType.GetUseSiteDiagnostic();
            if (useSiteError != null)
            {
                diagnostics.Add(useSiteError, NoLocation.Singleton);
            }

            _parameters = ImmutableArray.Create<ParameterSymbol>(
                new SynthesizedParameterSymbol(this, submissionArrayType, 0, RefKind.None, "submissionArray"));
        }
        protected void TypeChecks(TypeSymbol type, DiagnosticBag diagnostics)
        {
            if (type.IsStatic)
            {
                // Cannot declare a variable of static type '{0}'
                diagnostics.Add(ErrorCode.ERR_VarDeclIsStaticClass, this.ErrorLocation, type);
            }
            else if (type.SpecialType == SpecialType.System_Void)
            {
                diagnostics.Add(ErrorCode.ERR_FieldCantHaveVoidType, TypeSyntax.Location);
            }
            else if (type.IsRestrictedType())
            {
                diagnostics.Add(ErrorCode.ERR_FieldCantBeRefAny, TypeSyntax.Location, type);
            }
            else if (IsConst && !type.CanBeConst())
            {
                SyntaxToken constToken = default(SyntaxToken);
                foreach (var modifier in ModifiersTokenList)
                {
                    if (modifier.Kind() == SyntaxKind.ConstKeyword)
                    {
                        constToken = modifier;
                        break;
                    }
                }
                Debug.Assert(constToken.Kind() == SyntaxKind.ConstKeyword);

                diagnostics.Add(ErrorCode.ERR_BadConstType, constToken.GetLocation(), type);
            }
            else if (IsVolatile && !type.IsValidVolatileFieldType())
            {
                // '{0}': a volatile field cannot be of the type '{1}'
                diagnostics.Add(ErrorCode.ERR_VolatileStruct, this.ErrorLocation, this, type);
            }

            HashSet<DiagnosticInfo> useSiteDiagnostics = null;
            if (!this.IsNoMoreVisibleThan(type, ref useSiteDiagnostics))
            {
                // Inconsistent accessibility: field type '{1}' is less accessible than field '{0}'
                diagnostics.Add(ErrorCode.ERR_BadVisFieldType, this.ErrorLocation, this, type);
            }

            diagnostics.Add(this.ErrorLocation, useSiteDiagnostics);
        }
Exemple #32
0
        internal BoundExpression BindQuery(QueryExpressionSyntax node, DiagnosticBag 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));
        }
        /// <summary>
        /// Matches all methods that can be overriden (non-static, public or protected, abstract or virtual)
        /// within this type sub-tree (this type, its base and interfaces)
        /// with its override.
        /// Methods without an override are either abstract or a ghost stup has to be synthesized.
        /// </summary>
        /// <param name="diagnostics"></param>
        internal OverrideInfo[] ResolveOverrides(DiagnosticBag diagnostics)
        {
            if (_lazyOverrides != null)
            {
                // already resolved
                return(_lazyOverrides);
            }

            // inherit abstracts from base type
            // ignoring System.Object (we don't override its methods from PHP)
            var overrides = new List <OverrideInfo>();

            if (BaseType != null && BaseType.SpecialType != SpecialType.System_Object)
            {
                overrides.AddRange(BaseType.ResolveOverrides(diagnostics));
            }

            // collect this type declared methods including synthesized methods
            var methods       = this.GetMembers().OfType <MethodSymbol>();
            var methodslookup = methods.Where(OverrideHelper.CanOverride).ToLookup(m => m.RoutineName, StringComparer.OrdinalIgnoreCase);

            // resolve overrides of inherited members
            for (int i = 0; i < overrides.Count; i++)
            {
                var m = overrides[i];
                if (m.HasOverride == false)
                {
                    // update override info of the inherited member
                    overrides[i] = new OverrideInfo(m.Method, OverrideHelper.ResolveMethodImplementation(m.Method, methodslookup[m.RoutineName]));
                }
                else
                {
                    // clear the interface flag of inherited override info
                    m.ImplementsInterface = false;
                    overrides[i]          = m;
                }
            }

            // resolve overrides of interface methods
            foreach (var iface in Interfaces)
            {
                // skip interfaces implemented by base type or other interfaces,
                // we don't want to add redundant override entries:
                if ((BaseType != null && BaseType.ImplementsInterface(iface)) ||
                    Interfaces.Any(x => x != iface && x.ImplementsInterface(iface)))
                {
                    // iface is already handled within overrides => skip
                    // note: iface can be ignored in metadata at all actually
                    continue;
                }

                var iface_abstracts = iface.ResolveOverrides(diagnostics);
                foreach (var m in iface_abstracts)
                {
                    if (BaseType != null && m.Method.ContainingType != iface && BaseType.ImplementsInterface(m.Method.ContainingType))
                    {
                        // iface {m.Method.ContainingType} already handled within overrides => skip
                        continue;
                    }

                    // ignore interface method that is already implemented:
                    if (overrides.Any(o => OverrideHelper.SignaturesMatch(o.Method, m.Method)))
                    {
                        continue;
                    }

                    // add interface member,
                    // resolve its override
                    overrides.Add(new OverrideInfo(m.Method, this.IsInterface ? null : OverrideHelper.ResolveMethodImplementation(m.Method, this))
                    {
                        ImplementsInterface = true
                    });
                }
            }

            // add overrideable routines from this type
            foreach (var m in methods)
            {
                if (m.IsOverrideable())
                {
                    overrides.Add(new OverrideInfo(m));
                }
            }

            // report unresolved abstracts
            if (!this.IsAbstract && !this.IsInterface && this is SourceTypeSymbol srct)
            {
                foreach (var m in overrides)
                {
                    if (m.IsUnresolvedAbstract)
                    {
                        // Class '{0}' doesn't implement abstract method {1}::{2}()
                        diagnostics.Add(DiagnosticBagExtensions.ParserDiagnostic(srct.ContainingFile.SyntaxTree, srct.Syntax.HeadingSpan,
                                                                                 Devsense.PHP.Errors.Errors.AbstractMethodNotImplemented,
                                                                                 srct.FullName.ToString(), ((IPhpTypeSymbol)m.Method.ContainingType).FullName.ToString(), m.RoutineName));
                    }
                }
            }

            // cache & return
            return(_lazyOverrides = overrides.ToArray());
        }
Exemple #34
0
        private ConstantValue DecodeDefaultParameterValueAttribute(CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt)
        {
            Debug.Assert(!diagnose || diagnosticsOpt != null);

            if (HasDefaultArgumentSyntax)
            {
                // error CS1745: Cannot specify default parameter value in conjunction with DefaultParameterAttribute or OptionalAttribute
                if (diagnose)
                {
                    diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueUsedWithAttributes, node.Name.Location);
                }
                return(ConstantValue.Bad);
            }

            // BREAK: In dev10, DefaultParameterValueAttribute could not be applied to System.Type or array parameters.
            // When this was attempted, dev10 produced CS1909, ERR_DefaultValueBadParamType.  Roslyn takes a different
            // approach: instead of looking at the parameter type, we look at the argument type.  There's nothing wrong
            // with providing a default value for a System.Type or array parameter, as long as the default parameter
            // is not a System.Type or an array (i.e. null is fine).  Since we are no longer interested in the type of
            // the parameter, all occurrences of CS1909 have been replaced with CS1910, ERR_DefaultValueBadValueType,
            // to indicate that the argument type, rather than the parameter type, is the source of the problem.

            Debug.Assert(attribute.CommonConstructorArguments.Length == 1);

            // the type of the value is the type of the expression in the attribute:
            var arg = attribute.CommonConstructorArguments[0];

            SpecialType specialType = arg.Kind == TypedConstantKind.Enum ?
                                      ((INamedTypeSymbol)arg.Type).EnumUnderlyingType.SpecialType :
                                      arg.Type.SpecialType;

            var compilation = this.DeclaringCompilation;
            var constantValueDiscriminator = ConstantValue.GetDiscriminator(specialType);
            HashSet <DiagnosticInfo> useSiteDiagnostics = null;

            if (constantValueDiscriminator == ConstantValueTypeDiscriminator.Bad)
            {
                if (arg.Kind != TypedConstantKind.Array && arg.Value == null)
                {
                    if (this.Type.IsReferenceType)
                    {
                        constantValueDiscriminator = ConstantValueTypeDiscriminator.Null;
                    }
                    else
                    {
                        // error CS1908: The type of the argument to the DefaultParameterValue attribute must match the parameter type
                        if (diagnose)
                        {
                            diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueTypeMustMatch, node.Name.Location);
                        }
                        return(ConstantValue.Bad);
                    }
                }
                else
                {
                    // error CS1910: Argument of type '{0}' is not applicable for the DefaultParameterValue attribute
                    if (diagnose)
                    {
                        diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueBadValueType, node.Name.Location, arg.Type);
                    }
                    return(ConstantValue.Bad);
                }
            }
            else if (!compilation.Conversions.ClassifyConversion((TypeSymbol)arg.Type, this.Type, ref useSiteDiagnostics).Kind.IsImplicitConversion())
            {
                // error CS1908: The type of the argument to the DefaultParameterValue attribute must match the parameter type
                if (diagnose)
                {
                    diagnosticsOpt.Add(ErrorCode.ERR_DefaultValueTypeMustMatch, node.Name.Location);
                    diagnosticsOpt.Add(node.Name.Location, useSiteDiagnostics);
                }
                return(ConstantValue.Bad);
            }

            if (diagnose)
            {
                diagnosticsOpt.Add(node.Name.Location, useSiteDiagnostics);
            }

            return(ConstantValue.Create(arg.Value, constantValueDiscriminator));
        }
Exemple #35
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, SyntaxToken token)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code), token.GetLocation()));
 }
Exemple #36
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,
            DiagnosticBag 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);
        }
Exemple #37
0
        public static BoundBlock Rewrite(
            MethodSymbol method,
            BoundBlock block,
            DiagnosticBag 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().Length;
#endif
            var compilation = method.DeclaringCompilation;

            if (method.ReturnsVoid || method.IsIterator || method.IsAsyncReturningTask(compilation))
            {
                // we don't analyze synthesized void methods.
                if ((method.IsImplicitlyDeclared && !method.IsScriptInitializer) ||
                    Analyze(compilation, method, block, diagnostics))
                {
                    block = AppendImplicitReturn(block, method, originalBodyNested);
                }
            }
            else if (Analyze(compilation, method, block, diagnostics))
            {
                // 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));
                    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));
                    // Ignore warnings since flow analysis reports nullability mismatches.
                    Debug.Assert(GetErrorsOnly(flowAnalysisDiagnostics.ToReadOnly()).SequenceEqual(GetErrorsOnly(diagnostics.ToReadOnly().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);
        }
Exemple #38
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, Location location)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code), location));
 }
Exemple #39
0
        protected override void MethodChecks(DiagnosticBag diagnostics)
        {
            var binder = this.DeclaringCompilation.
                         GetBinderFactory(syntaxReference.SyntaxTree).GetBinder(ReturnTypeSyntax);

            SyntaxToken arglistToken;

            var signatureBinder = binder.WithAdditionalFlags(BinderFlags.SuppressConstraintChecks);

            this.lazyParameters = ParameterHelpers.MakeParameters(
                signatureBinder,
                this,
                ParameterListSyntax,
                true,
                out arglistToken,
                diagnostics);

            if (arglistToken.CSharpKind() == SyntaxKind.ArgListKeyword)
            {
                // This is a parse-time error in the native compiler; it is a semantic analysis error in Roslyn.

                // error CS1669: __arglist is not valid in this context
                diagnostics.Add(ErrorCode.ERR_IllegalVarArgs, new SourceLocation(arglistToken));

                // Regardless of whether __arglist appears in the source code, we do not mark
                // the operator method as being a varargs method.
            }

            this.lazyReturnType = signatureBinder.BindType(ReturnTypeSyntax, diagnostics);

            if (this.lazyReturnType.IsRestrictedType())
            {
                // Method or delegate cannot return type '{0}'
                diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, ReturnTypeSyntax.Location, this.lazyReturnType);
            }

            if (this.lazyReturnType.IsStatic)
            {
                // '{0}': static types cannot be used as return types
                diagnostics.Add(ErrorCode.ERR_ReturnTypeIsStaticClass, ReturnTypeSyntax.Location, this.lazyReturnType);
            }

            this.flags |= MakeFlags(
                MethodKind,
                DeclarationModifiers,
                this.lazyReturnType.SpecialType == SpecialType.System_Void,
                IsExtensionMethod);

            // If we have an operator in an interface or static class then we already
            // have reported that fact as  an error. No need to cascade the error further.
            if (this.ContainingType.IsInterfaceType() || this.ContainingType.IsStatic)
            {
                return;
            }

            // SPEC: All types referenced in an operator declaration must be at least as accessible
            // SPEC: as the operator itself.

            CheckEffectiveAccessibility(lazyReturnType, lazyParameters, diagnostics);
            CheckValueParameters(diagnostics);
            CheckOperatorSignatures(diagnostics);
        }
Exemple #40
0
 internal static void Error(DiagnosticBag diagnostics, DiagnosticInfo info, SyntaxNode syntax)
 {
     diagnostics.Add(new CSDiagnostic(info, syntax.Location));
 }
Exemple #41
0
        internal override void GenerateMethodBody(TypeCompilationState compilationState, DiagnosticBag diagnostics)
        {
            ImmutableArray <LocalSymbol> declaredLocalsArray;
            var body        = _generateMethodBody(this, diagnostics, out declaredLocalsArray, out _lazyResultProperties);
            var compilation = compilationState.Compilation;

            _lazyReturnType = TypeWithAnnotations.Create(CalculateReturnType(compilation, body));

            // Can't do this until the return type has been computed.
            TypeParameterChecker.Check(this, _allTypeParameters);

            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            DiagnosticsPass.IssueDiagnostics(compilation, body, diagnostics, this);
            if (diagnostics.HasAnyErrors())
            {
                return;
            }

            // Check for use-site diagnostics (e.g. missing types in the signature).
            DiagnosticInfo useSiteDiagnosticInfo = null;

            this.CalculateUseSiteDiagnostic(ref useSiteDiagnosticInfo);
            if (useSiteDiagnosticInfo != null && useSiteDiagnosticInfo.Severity == DiagnosticSeverity.Error)
            {
                diagnostics.Add(useSiteDiagnosticInfo, this.Locations[0]);
                return;
            }

            try
            {
                var declaredLocals = PooledHashSet <LocalSymbol> .GetInstance();

                try
                {
                    // Rewrite local declaration statement.
                    body = (BoundStatement)LocalDeclarationRewriter.Rewrite(
                        compilation,
                        _container,
                        declaredLocals,
                        body,
                        declaredLocalsArray,
                        diagnostics);

                    // Verify local declaration names.
                    foreach (var local in declaredLocals)
                    {
                        Debug.Assert(local.Locations.Length > 0);
                        var name = local.Name;
                        if (name.StartsWith("$", StringComparison.Ordinal))
                        {
                            diagnostics.Add(ErrorCode.ERR_UnexpectedCharacter, local.Locations[0], name[0]);
                            return;
                        }
                    }

                    // Rewrite references to placeholder "locals".
                    body = (BoundStatement)PlaceholderLocalRewriter.Rewrite(compilation, _container, declaredLocals, body, diagnostics);

                    if (diagnostics.HasAnyErrors())
                    {
                        return;
                    }
                }
                finally
                {
                    declaredLocals.Free();
                }

                var syntax            = body.Syntax;
                var statementsBuilder = ArrayBuilder <BoundStatement> .GetInstance();

                statementsBuilder.Add(body);
                // Insert an implicit return statement if necessary.
                if (body.Kind != BoundKind.ReturnStatement)
                {
                    statementsBuilder.Add(new BoundReturnStatement(syntax, RefKind.None, expressionOpt: null));
                }

                var localsSet = PooledHashSet <LocalSymbol> .GetInstance();

                try
                {
                    var localsBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

                    foreach (var local in this.LocalsForBinding)
                    {
                        Debug.Assert(!localsSet.Contains(local));
                        localsBuilder.Add(local);
                        localsSet.Add(local);
                    }
                    foreach (var local in this.Locals)
                    {
                        if (localsSet.Add(local))
                        {
                            localsBuilder.Add(local);
                        }
                    }

                    body = new BoundBlock(syntax, localsBuilder.ToImmutableAndFree(), statementsBuilder.ToImmutableAndFree())
                    {
                        WasCompilerGenerated = true
                    };

                    Debug.Assert(!diagnostics.HasAnyErrors());
                    Debug.Assert(!body.HasErrors);

                    bool sawLambdas;
                    bool sawLocalFunctions;
                    bool sawAwaitInExceptionHandler;
                    ImmutableArray <SourceSpan> dynamicAnalysisSpans = ImmutableArray <SourceSpan> .Empty;
                    body = LocalRewriter.Rewrite(
                        compilation: this.DeclaringCompilation,
                        method: this,
                        methodOrdinal: _methodOrdinal,
                        containingType: _container,
                        statement: body,
                        compilationState: compilationState,
                        previousSubmissionFields: null,
                        allowOmissionOfConditionalCalls: false,
                        instrumentForDynamicAnalysis: false,
                        debugDocumentProvider: null,
                        dynamicAnalysisSpans: ref dynamicAnalysisSpans,
                        diagnostics: diagnostics,
                        sawLambdas: out sawLambdas,
                        sawLocalFunctions: out sawLocalFunctions,
                        sawAwaitInExceptionHandler: out sawAwaitInExceptionHandler);

                    Debug.Assert(!sawAwaitInExceptionHandler);
                    Debug.Assert(dynamicAnalysisSpans.Length == 0);

                    if (body.HasErrors)
                    {
                        return;
                    }

                    // Variables may have been captured by lambdas in the original method
                    // or in the expression, and we need to preserve the existing values of
                    // those variables in the expression. This requires rewriting the variables
                    // in the expression based on the closure classes from both the original
                    // method and the expression, and generating a preamble that copies
                    // values into the expression closure classes.
                    //
                    // Consider the original method:
                    // static void M()
                    // {
                    //     int x, y, z;
                    //     ...
                    //     F(() => x + y);
                    // }
                    // and the expression in the EE: "F(() => x + z)".
                    //
                    // The expression is first rewritten using the closure class and local <1>
                    // from the original method: F(() => <1>.x + z)
                    // Then lambda rewriting introduces a new closure class that includes
                    // the locals <1> and z, and a corresponding local <2>: F(() => <2>.<1>.x + <2>.z)
                    // And a preamble is added to initialize the fields of <2>:
                    //     <2> = new <>c__DisplayClass0();
                    //     <2>.<1> = <1>;
                    //     <2>.z = z;

                    // Rewrite "this" and "base" references to parameter in this method.
                    // Rewrite variables within body to reference existing display classes.
                    body = (BoundStatement)CapturedVariableRewriter.Rewrite(
                        this.GenerateThisReference,
                        compilation.Conversions,
                        _displayClassVariables,
                        body,
                        diagnostics);

                    if (body.HasErrors)
                    {
                        Debug.Assert(false, "Please add a test case capturing whatever caused this assert.");
                        return;
                    }

                    if (diagnostics.HasAnyErrors())
                    {
                        return;
                    }

                    if (sawLambdas || sawLocalFunctions)
                    {
                        var closureDebugInfoBuilder = ArrayBuilder <ClosureDebugInfo> .GetInstance();

                        var lambdaDebugInfoBuilder = ArrayBuilder <LambdaDebugInfo> .GetInstance();

                        body = LambdaRewriter.Rewrite(
                            loweredBody: body,
                            thisType: this.SubstitutedSourceMethod.ContainingType,
                            thisParameter: _thisParameter,
                            method: this,
                            methodOrdinal: _methodOrdinal,
                            substitutedSourceMethod: this.SubstitutedSourceMethod.OriginalDefinition,
                            closureDebugInfoBuilder: closureDebugInfoBuilder,
                            lambdaDebugInfoBuilder: lambdaDebugInfoBuilder,
                            slotAllocatorOpt: null,
                            compilationState: compilationState,
                            diagnostics: diagnostics,
                            assignLocals: localsSet);

                        // we don't need this information:
                        closureDebugInfoBuilder.Free();
                        lambdaDebugInfoBuilder.Free();
                    }
                }
                finally
                {
                    localsSet.Free();
                }

                // Insert locals from the original method,
                // followed by any new locals.
                var block        = (BoundBlock)body;
                var localBuilder = ArrayBuilder <LocalSymbol> .GetInstance();

                foreach (var local in this.Locals)
                {
                    Debug.Assert(!(local is EELocalSymbol) || (((EELocalSymbol)local).Ordinal == localBuilder.Count));
                    localBuilder.Add(local);
                }
                foreach (var local in block.Locals)
                {
                    if (local is EELocalSymbol oldLocal)
                    {
                        Debug.Assert(localBuilder[oldLocal.Ordinal] == oldLocal);
                        continue;
                    }
                    localBuilder.Add(local);
                }

                body = block.Update(localBuilder.ToImmutableAndFree(), block.LocalFunctions, block.Statements);
                TypeParameterChecker.Check(body, _allTypeParameters);
                compilationState.AddSynthesizedMethod(this, body);
            }
            catch (BoundTreeVisitor.CancelledByStackGuardException ex)
            {
                ex.AddAnError(diagnostics);
            }
        }
Exemple #42
0
 internal static void Error(DiagnosticBag diagnostics, DiagnosticInfo info, Location location)
 {
     diagnostics.Add(new CSDiagnostic(info, location));
 }
Exemple #43
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, CSharpSyntaxNode syntax)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code), syntax.Location));
 }
Exemple #44
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, CSharpSyntaxNode syntax, params object[] args)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code, args), syntax.Location));
 }
Exemple #45
0
        private void CheckUserDefinedConversionSignature(DiagnosticBag diagnostics)
        {
            if (this.ReturnsVoid)
            {
                // CS0590: User-defined operators cannot return void
                diagnostics.Add(ErrorCode.ERR_OperatorCantReturnVoid, this.Locations[0]);
            }

            // SPEC: For a given source type S and target type T, if S or T are
            // SPEC: nullable types let S0 and T0 refer to their underlying types,
            // SPEC: otherise, S0 and T0 are equal to S and T, respectively.

            var source  = this.ParameterTypes[0];
            var target  = this.ReturnType;
            var source0 = source.StrippedType();
            var target0 = target.StrippedType();

            // SPEC: A class or struct is permitted to declare a conversion from S to T
            // SPEC: only if all the following are true:

            // SPEC: Neither S0 nor T0 is an interface type.

            if (source0.IsInterfaceType() || target0.IsInterfaceType())
            {
                // CS0552: '{0}': user-defined conversions to or from an interface are not allowed
                diagnostics.Add(ErrorCode.ERR_ConversionWithInterface, this.Locations[0], this);
                return;
            }

            // SPEC: Either S0 or T0 is the class or struct type in which the operator
            // SPEC: declaration takes place.

            if (source0 != this.ContainingType && target0 != this.ContainingType &&
                // allow conversion between T and Nullable<T> in declaration of Nullable<T>
                source != this.ContainingType && target != this.ContainingType)
            {
                // CS0556: User-defined conversion must convert to or from the enclosing type
                diagnostics.Add(ErrorCode.ERR_ConversionNotInvolvingContainedType, this.Locations[0]);
                return;
            }

            // SPEC: * S0 and T0 are different types:

            if ((ContainingType.SpecialType == SpecialType.System_Nullable_T) ? source == target : source0 == target0)
            {
                // CS0555: User-defined operator cannot take an object of the enclosing type
                // and convert to an object of the enclosing type
                diagnostics.Add(ErrorCode.ERR_IdentityConversion, this.Locations[0]);
                return;
            }

            // Those are the easy ones. Now we come to:

            // SPEC:
            // Exluding user-defined conversions, a conversion does not exist from
            // S to T or T to S. For the purposes of these rules, any type parameters
            // associated with S or T are considered to be unique types that have
            // no inheritance relationship with other types, and any constraints on
            // those type parameters are ignored.

            // A counter-intuative consequence of this rule is that:
            //
            // class X<U> where U : X<U>
            // {
            //     public implicit operator X<U>(U u) { return u; }
            // }
            //
            // is *legal*, even though there is *already* an implicit conversion
            // from U to X<U> because U is constrained to have such a conversion.
            //
            // In discussing the implications of this rule, let's call the
            // containing type (which may be a class or struct) "C". S and T
            // are the source and target types.
            //
            // If we have made it this far in the error analysis we already know that
            // exactly one of S and T is C or C? -- if two or zero were, then we'd
            // have already reported ERR_ConversionNotInvolvingContainedType or
            // ERR_IdentityConversion and returned.
            //
            // WOLOG for the purposes of this discussion let's assume that S is
            // the one that is C or C?, and that T is the one that is neither C nor C?.
            //
            // So the question is: under what circumstances could T-to-S or S-to-T,
            // be a valid conversion, by the definition of valid above?
            //
            // Let's consider what kinds of types T could be. T cannot be an interface
            // because we've already reported an error and returned if it is. If T is
            // a delegate, array, enum, pointer, struct or nullable type then there
            // is no built-in conversion from T to the user-declared class/struct
            // C, or to C?. If T is a type parameter, then by assumption the type
            // parameter has no constraints, and therefore is not convertible to
            // C or C?.
            //
            // That leaves T to be a class. We already know that T is not C, (or C?,
            // since T is a class) and therefore there is no identity conversion from T to S.
            //
            // Suppose S is C and C is a class. Then the only way that there can be a
            // conversion between T and S is if T is a base class of S or S is a base class of T.
            //
            // Suppose S is C and C is a struct. Then the only way that there can be a
            // conversion between T and S is if T is a base class of S. (And T would
            // have to be System.Object or System.ValueType.)
            //
            // Suppose S is C? and C is a struct. Then the only way that there can be a
            // conversion between T and S is again, if T is a base class of S.
            //
            // Summing up:
            //
            // WOLOG, we assume that T is not C or C?, and S is C or C?. The conversion is
            // illegal only if T is a class, and either T is a base class of S, or S is a
            // base class of T.

            if (source.IsDynamic() || target.IsDynamic())
            {
                // '{0}': user-defined conversions to or from the dynamic type are not allowed
                diagnostics.Add(ErrorCode.ERR_BadDynamicConversion, this.Locations[0], this);
                return;
            }

            TypeSymbol same;
            TypeSymbol different;

            if (source0 == this.ContainingType)
            {
                same      = source;
                different = target;
            }
            else
            {
                same      = target;
                different = source;
            }

            if (different.IsClassType())
            {
                // different is a class type:
                Debug.Assert(!different.IsTypeParameter());

                // "same" is the containing class, so it can't be a type parameter
                Debug.Assert(!same.IsTypeParameter());

                HashSet <DiagnosticInfo> useSiteDiagnostics = null;

                if (same.IsDerivedFrom(different, ignoreDynamic: false, useSiteDiagnostics: ref useSiteDiagnostics)) // tomat: ignoreDynamic should be true, but we don't want to introduce breaking change. See bug 605326.
                {
                    // '{0}': user-defined conversions to or from a base class are not allowed
                    diagnostics.Add(ErrorCode.ERR_ConversionWithBase, this.Locations[0], this);
                }
                else if (different.IsDerivedFrom(same, ignoreDynamic: false, useSiteDiagnostics: ref useSiteDiagnostics)) // tomat: ignoreDynamic should be true, but we don't want to introduce breaking change. See bug 605326.
                {
                    // '{0}': user-defined conversions to or from a derived class are not allowed
                    diagnostics.Add(ErrorCode.ERR_ConversionWithDerived, this.Locations[0], this);
                }

                diagnostics.Add(this.Locations[0], useSiteDiagnostics);
            }
        }
        internal static void Add(this DiagnosticBag diagnostics, DiagnosticInfo info, Location location)
        {
            var diag = new CSDiagnostic(info, location);

            diagnostics.Add(diag);
        }
Exemple #47
0
        protected SourceUserDefinedOperatorSymbolBase(
            MethodKind methodKind,
            string name,
            SourceMemberContainerTypeSymbol containingType,
            Location location,
            SyntaxReference syntaxReference,
            SyntaxReference bodySyntaxReference,
            SyntaxTokenList modifiersSyntax,
            DiagnosticBag diagnostics,
            bool isExpressionBodied) :
            base(containingType, syntaxReference, bodySyntaxReference, location)
        {
            this.name = name;
            this.isExpressionBodied = isExpressionBodied;

            var defaultAccess    = DeclarationModifiers.Private;
            var allowedModifiers =
                DeclarationModifiers.AccessibilityMask |
                DeclarationModifiers.Static |
                DeclarationModifiers.Extern |
                DeclarationModifiers.Unsafe;

            bool modifierErrors;
            var  declarationModifiers = ModifierUtils.MakeAndCheckNontypeMemberModifiers(
                modifiersSyntax,
                defaultAccess,
                allowedModifiers,
                location,
                diagnostics,
                out modifierErrors);

            this.CheckUnsafeModifier(declarationModifiers, diagnostics);

            // We will bind the formal parameters and the return type lazily. For now,
            // assume that the return type is non-void; when we do the lazy initialization
            // of the parameters and return type we will update the flag if necessary.

            this.flags = MakeFlags(methodKind, declarationModifiers, returnsVoid: false, isExtensionMethod: false);

            if (this.ContainingType.IsInterface)
            {
                // If we have an operator in an interface, we already have reported that fact as
                // an error. No need to cascade the error further.
                return;
            }

            if (this.ContainingType.IsStatic)
            {
                // Similarly if we're in a static class, though we have not reported it yet.

                // CS0715: '{0}': static classes cannot contain user-defined operators
                diagnostics.Add(ErrorCode.ERR_OperatorInStaticClass, location, this);
                return;
            }

            // SPEC: An operator declaration must include both a public and a
            // SPEC: static modifier
            if (this.DeclaredAccessibility != Accessibility.Public || !this.IsStatic)
            {
                // CS0558: User-defined operator '...' must be declared static and public
                diagnostics.Add(ErrorCode.ERR_OperatorsMustBeStatic, this.Locations[0], this);
            }

            // SPEC: Because an external operator provides no actual implementation,
            // SPEC: its operator body consists of a semicolon. For expression-bodied
            // SPEC: operators, the body is an expression. For all other operators,
            // SPEC: the operator body consists of a block...
            if (bodySyntaxReference != null && IsExtern)
            {
                diagnostics.Add(ErrorCode.ERR_ExternHasBody, location, this);
            }
            else if (bodySyntaxReference == null && !IsExtern && !IsAbstract && !IsPartial)
            {
                // Do not report that the body is missing if the operator is marked as
                // partial or abstract; we will already have given an error for that so
                // there's no need to "cascade" the error.
                diagnostics.Add(ErrorCode.ERR_ConcreteMissingBody, location, this);
            }

            // SPEC: It is an error for the same modifier to appear multiple times in an
            // SPEC: operator declaration.
            var info = ModifierUtils.CheckAccessibility(this.DeclarationModifiers);

            if (info != null)
            {
                diagnostics.Add(info, location);
            }
        }
Exemple #48
0
        internal VariableSlotAllocator?TryCreateVariableSlotAllocator(
            EmitBaseline baseline,
            Compilation compilation,
            IMethodSymbolInternal method,
            IMethodSymbolInternal topLevelMethod,
            DiagnosticBag diagnostics
            )
        {
            // Top-level methods are always included in the semantic edit list. Lambda methods are not.
            if (!mappedMethods.TryGetValue(topLevelMethod, out var mappedMethod))
            {
                return(null);
            }

            // TODO (bug https://github.com/dotnet/roslyn/issues/2504):
            // Handle cases when the previous method doesn't exist.

            if (
                !TryGetMethodHandle(
                    baseline,
                    (Cci.IMethodDefinition)method.GetCciAdapter(),
                    out var previousHandle
                    )
                )
            {
                // Unrecognized method. Must have been added in the current compilation.
                return(null);
            }

            ImmutableArray <EncLocalInfo> previousLocals;
            IReadOnlyDictionary <EncHoistedLocalInfo, int>?         hoistedLocalMap = null;
            IReadOnlyDictionary <Cci.ITypeReference, int>?          awaiterMap      = null;
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> >?lambdaMap       = null;
            IReadOnlyDictionary <int, DebugId>?closureMap = null;

            int           hoistedLocalSlotCount = 0;
            int           awaiterSlotCount      = 0;
            string?       stateMachineTypeName  = null;
            SymbolMatcher symbolMap;

            int     methodIndex = MetadataTokens.GetRowNumber(previousHandle);
            DebugId methodId;

            // Check if method has changed previously. If so, we already have a map.
            if (
                baseline.AddedOrChangedMethods.TryGetValue(
                    methodIndex,
                    out var addedOrChangedMethod
                    )
                )
            {
                methodId = addedOrChangedMethod.MethodId;

                MakeLambdaAndClosureMaps(
                    addedOrChangedMethod.LambdaDebugInfo,
                    addedOrChangedMethod.ClosureDebugInfo,
                    out lambdaMap,
                    out closureMap
                    );

                if (addedOrChangedMethod.StateMachineTypeName != null)
                {
                    // method is async/iterator kickoff method
                    GetStateMachineFieldMapFromPreviousCompilation(
                        addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt,
                        addedOrChangedMethod.StateMachineAwaiterSlotsOpt,
                        out hoistedLocalMap,
                        out awaiterMap
                        );

                    hoistedLocalSlotCount =
                        addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt.Length;
                    awaiterSlotCount = addedOrChangedMethod.StateMachineAwaiterSlotsOpt.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = addedOrChangedMethod.StateMachineTypeName;
                }
                else
                {
                    previousLocals = addedOrChangedMethod.Locals;
                }

                // All types that AddedOrChangedMethodInfo refers to have been mapped to the previous generation.
                // Therefore we don't need to fall back to metadata if we don't find the type reference, like we do in DefinitionMap.MapReference.
                symbolMap = MapToPreviousSymbolMatcher;
            }
            else
            {
                // Method has not changed since initial generation. Generate a map
                // using the local names provided with the initial metadata.
                EditAndContinueMethodDebugInformation debugInfo;
                StandaloneSignatureHandle             localSignature;
                try
                {
                    debugInfo      = baseline.DebugInformationProvider(previousHandle);
                    localSignature = baseline.LocalSignatureProvider(previousHandle);
                }
                catch (Exception e) when(e is InvalidDataException || e is IOException)
                {
                    diagnostics.Add(
                        MessageProvider.CreateDiagnostic(
                            MessageProvider.ERR_InvalidDebugInfo,
                            method.Locations.First(),
                            method,
                            MetadataTokens.GetToken(previousHandle),
                            method.ContainingAssembly
                            )
                        );

                    return(null);
                }

                methodId = new DebugId(debugInfo.MethodOrdinal, 0);

                if (!debugInfo.Lambdas.IsDefaultOrEmpty)
                {
                    MakeLambdaAndClosureMaps(
                        debugInfo.Lambdas,
                        debugInfo.Closures,
                        out lambdaMap,
                        out closureMap
                        );
                }

                ITypeSymbolInternal?stateMachineType = TryGetStateMachineType(previousHandle);
                if (stateMachineType != null)
                {
                    // method is async/iterator kickoff method
                    var localSlotDebugInfo = debugInfo.LocalSlots.NullToEmpty();
                    GetStateMachineFieldMapFromMetadata(
                        stateMachineType,
                        localSlotDebugInfo,
                        out hoistedLocalMap,
                        out awaiterMap,
                        out awaiterSlotCount
                        );
                    hoistedLocalSlotCount = localSlotDebugInfo.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = stateMachineType.Name;
                }
                else
                {
                    // If the current method is async/iterator then either the previous method wasn't declared as async/iterator and it's updated to be one,
                    // or it was but is not marked by the corresponding state machine attribute because it was missing in the compilation.
                    // In the later case we need to report an error since we don't known how to map to the previous state machine.

                    // The IDE already checked that the attribute type is present in the base compilation, but didn't validate that it is well-formed.
                    // We don't have the base compilation to directly query for the attribute, only the source compilation.
                    // But since constructor signatures can't be updated during EnC we can just check the current compilation.

                    if (method.IsAsync)
                    {
                        if (
                            compilation.CommonGetWellKnownTypeMember(
                                WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor
                                ) == null
                            )
                        {
                            ReportMissingStateMachineAttribute(
                                diagnostics,
                                method,
                                AttributeDescription.AsyncStateMachineAttribute.FullName
                                );
                            return(null);
                        }
                    }
                    else if (method.IsIterator)
                    {
                        if (
                            compilation.CommonGetWellKnownTypeMember(
                                WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor
                                ) == null
                            )
                        {
                            ReportMissingStateMachineAttribute(
                                diagnostics,
                                method,
                                AttributeDescription.IteratorStateMachineAttribute.FullName
                                );
                            return(null);
                        }
                    }

                    try
                    {
                        previousLocals = localSignature.IsNil
                            ? ImmutableArray <EncLocalInfo> .Empty
                            : GetLocalSlotMapFromMetadata(localSignature, debugInfo);
                    }
                    catch (Exception e)
                        when(e is UnsupportedSignatureContent ||
                             e is BadImageFormatException ||
                             e is IOException
                             )
                        {
                            diagnostics.Add(
                                MessageProvider.CreateDiagnostic(
                                    MessageProvider.ERR_InvalidDebugInfo,
                                    method.Locations.First(),
                                    method,
                                    MetadataTokens.GetToken(localSignature),
                                    method.ContainingAssembly
                                    )
                                );

                            return(null);
                        }
                }

                symbolMap = MapToMetadataSymbolMatcher;
            }

            return(new EncVariableSlotAllocator(
                       symbolMap,
                       mappedMethod.SyntaxMap,
                       mappedMethod.PreviousMethod,
                       methodId,
                       previousLocals,
                       lambdaMap,
                       closureMap,
                       stateMachineTypeName,
                       hoistedLocalSlotCount,
                       hoistedLocalMap,
                       awaiterSlotCount,
                       awaiterMap,
                       GetLambdaSyntaxFacts()
                       ));
        }
Exemple #49
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,
            DiagnosticBag 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)));
        }
Exemple #50
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, Location location, params object[] args)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code, args), location));
 }
        /// <summary>
        /// Recursively builds a Conversion object with Kind=Deconstruction including information about any necessary
        /// Deconstruct method and any element-wise conversion.
        ///
        /// Note that the variables may either be plain or nested variables.
        /// The variables may be updated with inferred types if they didn't have types initially.
        /// Returns false if there was an error.
        /// </summary>
        private bool MakeDeconstructionConversion(
            TypeSymbol type,
            SyntaxNode syntax,
            SyntaxNode rightSyntax,
            DiagnosticBag diagnostics,
            ArrayBuilder <DeconstructionVariable> variables,
            out Conversion conversion)
        {
            Debug.Assert(type != null);
            ImmutableArray <TypeSymbol> tupleOrDeconstructedTypes;

            conversion = Conversion.Deconstruction;

            // Figure out the deconstruct method (if one is required) and determine the types we get from the RHS at this level
            var deconstructInfo = default(DeconstructionInfo);

            if (type.IsTupleType)
            {
                // tuple literal such as `(1, 2)`, `(null, null)`, `(x.P, y.M())`
                tupleOrDeconstructedTypes = type.TupleElementTypes;
                SetInferredTypes(variables, tupleOrDeconstructedTypes, diagnostics);

                if (variables.Count != tupleOrDeconstructedTypes.Length)
                {
                    Error(diagnostics, ErrorCode.ERR_DeconstructWrongCardinality, syntax, tupleOrDeconstructedTypes.Length, variables.Count);
                    return(false);
                }
            }
            else
            {
                ImmutableArray <BoundDeconstructValuePlaceholder> outPlaceholders;
                var inputPlaceholder      = new BoundDeconstructValuePlaceholder(syntax, type);
                var deconstructInvocation = MakeDeconstructInvocationExpression(variables.Count,
                                                                                inputPlaceholder, rightSyntax, diagnostics, out outPlaceholders);

                if (deconstructInvocation.HasAnyErrors)
                {
                    return(false);
                }

                deconstructInfo = new DeconstructionInfo(deconstructInvocation, inputPlaceholder, outPlaceholders);

                tupleOrDeconstructedTypes = outPlaceholders.SelectAsArray(p => p.Type);
                SetInferredTypes(variables, tupleOrDeconstructedTypes, diagnostics);
            }

            // Figure out whether those types will need conversions, including further deconstructions
            bool hasErrors = false;

            int count             = variables.Count;
            var nestedConversions = ArrayBuilder <Conversion> .GetInstance(count);

            for (int i = 0; i < count; i++)
            {
                var variable = variables[i];

                Conversion nestedConversion;
                if (variable.HasNestedVariables)
                {
                    var elementSyntax = syntax.Kind() == SyntaxKind.TupleExpression ? ((TupleExpressionSyntax)syntax).Arguments[i] : syntax;

                    hasErrors |= !MakeDeconstructionConversion(tupleOrDeconstructedTypes[i], syntax, rightSyntax, diagnostics,
                                                               variable.NestedVariables, out nestedConversion);
                }
                else
                {
                    var single = variable.Single;
                    HashSet <DiagnosticInfo> useSiteDiagnostics = null;
                    nestedConversion = this.Conversions.ClassifyConversionFromType(tupleOrDeconstructedTypes[i], single.Type, ref useSiteDiagnostics);
                    diagnostics.Add(single.Syntax, useSiteDiagnostics);

                    if (!nestedConversion.IsImplicit)
                    {
                        hasErrors = true;
                        GenerateImplicitConversionError(diagnostics, Compilation, single.Syntax, nestedConversion, tupleOrDeconstructedTypes[i], single.Type);
                    }
                }
                nestedConversions.Add(nestedConversion);
            }

            conversion = new Conversion(ConversionKind.Deconstruction, deconstructInfo, nestedConversions.ToImmutableAndFree());

            return(!hasErrors);
        }
Exemple #52
0
 private void Error(ErrorCode code, BoundNode node, params object[] args)
 {
     diagnostics.Add(code, node.Syntax.Location, args);
 }
Exemple #53
0
        public LocalFunctionSymbol(
            Binder binder,
            Symbol containingSymbol,
            LocalFunctionStatementSyntax syntax)
            : base(syntax.GetReference())
        {
            _containingSymbol = containingSymbol;

            _declarationDiagnostics = new DiagnosticBag();

            _declarationModifiers =
                DeclarationModifiers.Private |
                syntax.Modifiers.ToDeclarationModifiers(diagnostics: _declarationDiagnostics);

            if (SyntaxFacts.HasYieldOperations(syntax.Body))
            {
                _lazyIteratorElementType = TypeWithAnnotations.Boxed.Sentinel;
            }

            this.CheckUnsafeModifier(_declarationModifiers, _declarationDiagnostics);

            ScopeBinder = binder;

            binder = binder.WithUnsafeRegionIfNecessary(syntax.Modifiers);

            if (syntax.TypeParameterList != null)
            {
                binder          = new WithMethodTypeParametersBinder(this, binder);
                _typeParameters = MakeTypeParameters(_declarationDiagnostics);
            }
            else
            {
                _typeParameters = ImmutableArray <SourceMethodTypeParameterSymbol> .Empty;
                ReportErrorIfHasConstraints(syntax.ConstraintClauses, _declarationDiagnostics);
            }

            if (IsExtensionMethod)
            {
                _declarationDiagnostics.Add(ErrorCode.ERR_BadExtensionAgg, Locations[0]);
            }

            foreach (var param in syntax.ParameterList.Parameters)
            {
                ReportAttributesDisallowed(param.AttributeLists, _declarationDiagnostics);
            }

            if (syntax.ReturnType.Kind() == SyntaxKind.RefType)
            {
                var returnType = (RefTypeSyntax)syntax.ReturnType;
                if (returnType.ReadOnlyKeyword.Kind() == SyntaxKind.ReadOnlyKeyword)
                {
                    _refKind = RefKind.RefReadOnly;
                }
                else
                {
                    _refKind = RefKind.Ref;
                }
            }
            else
            {
                _refKind = RefKind.None;
            }

            _binder = binder;
        }
        private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpressionSyntax node, DiagnosticBag 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] = this.BindValue(expression, diagnostics, BindValueKind.RValue);

                //  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;
                // https://github.com/dotnet/roslyn/issues/24018: Initial binding should set NullableAnnotation.Unknown
                NullableAnnotation nullableAnnotation;
                switch (((CSharpParseOptions)node.SyntaxTree?.Options)?.IsFeatureEnabled(MessageID.IDS_FeatureNullableReferenceTypes))
                {
                case true:
                    nullableAnnotation = fieldType.IsReferenceType ? NullableAnnotation.Annotated : NullableAnnotation.NotAnnotated;
                    break;

                case false:
                    nullableAnnotation = NullableAnnotation.NotAnnotated;
                    break;

                default:
                    nullableAnnotation = NullableAnnotation.Unknown;
                    break;
                }

                fields[i] = new AnonymousTypeField(
                    fieldName == null ? "$" + i.ToString() : fieldName,
                    fieldSyntaxNodes[i].Location,
                    TypeSymbolWithAnnotations.Create(fieldType, nullableAnnotation));

                //  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.TypeSymbol));
                                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 static Symbol FindExplicitlyImplementedMember(
            Symbol implementingMember,
            TypeSymbol explicitInterfaceType,
            string interfaceMemberName,
            ExplicitInterfaceSpecifierSyntax explicitInterfaceSpecifierSyntax,
            DiagnosticBag diagnostics)
        {
            if ((object)explicitInterfaceType == null)
            {
                return(null);
            }

            var memberLocation     = implementingMember.Locations[0];
            var containingType     = implementingMember.ContainingType;
            var containingTypeKind = containingType.TypeKind;

            if (containingTypeKind != TypeKind.Class && containingTypeKind != TypeKind.Struct)
            {
                diagnostics.Add(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, memberLocation, implementingMember);
                return(null);
            }

            if (!explicitInterfaceType.IsInterfaceType())
            {
                //we'd like to highlight just the type part of the name
                var explicitInterfaceSyntax = explicitInterfaceSpecifierSyntax.Name;
                var location = new SourceLocation(explicitInterfaceSyntax);

                diagnostics.Add(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, location, explicitInterfaceType);
                return(null);
            }

            var explicitInterfaceNamedType = (NamedTypeSymbol)explicitInterfaceType;

            // 13.4.1: "For an explicit interface member implementation to be valid, the class or struct must name an
            // interface in its base class list that contains a member ..."
            MultiDictionary <NamedTypeSymbol, NamedTypeSymbol> .ValueSet set = containingType.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics[explicitInterfaceNamedType];
            int setCount = set.Count;

            if (setCount == 0 || !set.Contains(explicitInterfaceNamedType))
            {
                //we'd like to highlight just the type part of the name
                var explicitInterfaceSyntax = explicitInterfaceSpecifierSyntax.Name;
                var location = new SourceLocation(explicitInterfaceSyntax);

                if (setCount > 0 && set.Contains(explicitInterfaceNamedType, TypeSymbol.EqualsIgnoringNullableComparer))
                {
                    diagnostics.Add(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, location);
                }
                else
                {
                    diagnostics.Add(ErrorCode.ERR_ClassDoesntImplementInterface, location, implementingMember, explicitInterfaceNamedType);
                }

                //do a lookup anyway
            }

            var hasParamsParam = implementingMember.HasParamsParameter();

            // Setting this flag to true does not imply that an interface member has been successfully implemented.
            // It just indicates that a corresponding interface member has been found (there may still be errors).
            var foundMatchingMember = false;

            Symbol implementedMember = null;

            foreach (Symbol interfaceMember in explicitInterfaceNamedType.GetMembers(interfaceMemberName))
            {
                // At this point, we know that explicitInterfaceNamedType is an interface, so candidate must be public
                // and, therefore, accessible.  So we don't need to check that.
                // However, metadata interface members can be static - we ignore them, as does Dev10.
                if (interfaceMember.Kind != implementingMember.Kind || interfaceMember.IsStatic)
                {
                    continue;
                }

                if (MemberSignatureComparer.ExplicitImplementationLookupComparer.Equals(implementingMember, interfaceMember))
                {
                    foundMatchingMember = true;
                    // Cannot implement accessor directly unless
                    // the accessor is from an indexed property.
                    if (interfaceMember.IsAccessor() && !((MethodSymbol)interfaceMember).IsIndexedPropertyAccessor())
                    {
                        diagnostics.Add(ErrorCode.ERR_ExplicitMethodImplAccessor, memberLocation, implementingMember, interfaceMember);
                    }
                    else
                    {
                        if (interfaceMember.MustCallMethodsDirectly())
                        {
                            diagnostics.Add(ErrorCode.ERR_BogusExplicitImpl, memberLocation, implementingMember, interfaceMember);
                        }
                        else if (hasParamsParam && !interfaceMember.HasParamsParameter())
                        {
                            // Note: no error for !hasParamsParam && interfaceMethod.HasParamsParameter()
                            // Still counts as an implementation.
                            diagnostics.Add(ErrorCode.ERR_ExplicitImplParams, memberLocation, implementingMember, interfaceMember);
                        }

                        implementedMember = interfaceMember;
                        break;
                    }
                }
            }

            if (!foundMatchingMember)
            {
                // CONSIDER: we may wish to suppress this error in the event that another error
                // has been reported about the signature.
                diagnostics.Add(ErrorCode.ERR_InterfaceMemberNotFound, memberLocation, implementingMember);
            }

            return(implementedMember);
        }
Exemple #56
0
 internal static void Error(DiagnosticBag diagnostics, ErrorCode code, SyntaxToken token, params object[] args)
 {
     diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(code, args), token.GetLocation()));
 }
Exemple #57
0
 internal void Add(SlothDiagnostic diagnostic)
 {
     DiagnosticBag?.Add(diagnostic);
 }
 private static void Error(DiagnosticBag diagnostics, SyntaxNode syntaxOpt, DiagnosticInfo info)
 {
     diagnostics.Add(new CSDiagnostic(info, syntaxOpt == null ? NoLocation.Singleton : syntaxOpt.Location));
 }