internal override CSharpAttributeData EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments <EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments)
        {
            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.DefaultParameterValueAttribute))
            {
                return(EarlyDecodeAttributeForDefaultParameterValue(AttributeDescription.DefaultParameterValueAttribute, ref arguments));
            }
            else if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.DecimalConstantAttribute))
            {
                return(EarlyDecodeAttributeForDefaultParameterValue(AttributeDescription.DecimalConstantAttribute, ref arguments));
            }
            else if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.DateTimeConstantAttribute))
            {
                return(EarlyDecodeAttributeForDefaultParameterValue(AttributeDescription.DateTimeConstantAttribute, ref arguments));
            }
            else if (!IsOnPartialImplementation(arguments.AttributeSyntax))
            {
                if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.CallerLineNumberAttribute))
                {
                    arguments.GetOrCreateData <ParameterEarlyWellKnownAttributeData>().HasCallerLineNumberAttribute = true;
                }
                else if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.CallerFilePathAttribute))
                {
                    arguments.GetOrCreateData <ParameterEarlyWellKnownAttributeData>().HasCallerFilePathAttribute = true;
                }
                else if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.CallerMemberNameAttribute))
                {
                    arguments.GetOrCreateData <ParameterEarlyWellKnownAttributeData>().HasCallerMemberNameAttribute = true;
                }
            }

            return(base.EarlyDecodeWellKnownAttribute(ref arguments));
        }
Пример #2
0
        internal override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments <AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
        {
            Debug.Assert((object)arguments.AttributeSyntaxOpt != null);

            var attribute = arguments.Attribute;

            Debug.Assert(!attribute.HasErrors);
            Debug.Assert(arguments.SymbolPart == AttributeLocation.None);

            if (attribute.IsTargetAttribute(this, AttributeDescription.DefaultCharSetAttribute))
            {
                CharSet charSet = attribute.GetConstructorArgument <CharSet>(0, SpecialType.System_Enum);
                if (!ModuleWellKnownAttributeData.IsValidCharSet(charSet))
                {
                    CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, arguments.AttributeSyntaxOpt);
                    arguments.Diagnostics.Add(ErrorCode.ERR_InvalidAttributeArgument, attributeArgumentSyntax.Location, arguments.AttributeSyntaxOpt.GetErrorDisplayName());
                }
                else
                {
                    arguments.GetOrCreateData <ModuleWellKnownAttributeData>().DefaultCharacterSet = charSet;
                }
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableContextAttribute))
            {
                ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullableContextAttribute);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.NullablePublicOnlyAttribute))
            {
                ReportExplicitUseOfNullabilityAttribute(in arguments, AttributeDescription.NullablePublicOnlyAttribute);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
            {
                CSharpAttributeData.DecodeSkipLocalsInitAttribute <ModuleWellKnownAttributeData>(DeclaringCompilation, ref arguments);
            }
        }
Пример #3
0
        internal sealed override void DecodeWellKnownAttribute(ref DecodeWellKnownAttributeArguments <AttributeSyntax, CSharpAttributeData, AttributeLocation> arguments)
        {
            var attribute = arguments.Attribute;

            Debug.Assert(!attribute.HasErrors);
            Debug.Assert(arguments.SymbolPart == AttributeLocation.None);

            if (attribute.IsTargetAttribute(this, AttributeDescription.SpecialNameAttribute))
            {
                arguments.GetOrCreateData <CommonEventWellKnownAttributeData>().HasSpecialNameAttribute = true;
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.NullableAttribute))
            {
                // NullableAttribute should not be set explicitly.
                RoslynDebug.AssertNotNull(arguments.AttributeSyntaxOpt);
                arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitNullableAttribute, arguments.AttributeSyntaxOpt.Location);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.ExcludeFromCodeCoverageAttribute))
            {
                arguments.GetOrCreateData <CommonEventWellKnownAttributeData>().HasExcludeFromCodeCoverageAttribute = true;
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.TupleElementNamesAttribute))
            {
                RoslynDebug.AssertNotNull(arguments.AttributeSyntaxOpt);
                arguments.Diagnostics.Add(ErrorCode.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location);
            }
            else if (attribute.IsTargetAttribute(this, AttributeDescription.SkipLocalsInitAttribute))
            {
                CSharpAttributeData.DecodeSkipLocalsInitAttribute <CommonEventWellKnownAttributeData>(DeclaringCompilation, ref arguments);
            }
        }
        internal override void EarlyDecodeWellKnownAttributeType(NamedTypeSymbol attributeType, AttributeSyntax attributeSyntax)
        {
            Debug.Assert(!attributeType.IsErrorType());

            // NOTE: OptionalAttribute is decoded specially before any of the other attributes and stored in the parameter
            // symbol (rather than in the EarlyWellKnownAttributeData) because it is needed during overload resolution.
            if (CSharpAttributeData.IsTargetEarlyAttribute(attributeType, attributeSyntax, AttributeDescription.OptionalAttribute))
            {
                lazyHasOptionalAttribute = ThreeState.True;
            }
        }
Пример #5
0
        internal bool EarlyDecodeDeprecatedOrObsoleteAttribute(
            ref EarlyDecodeWellKnownAttributeArguments<EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments,
            out CSharpAttributeData attributeData,
            out ObsoleteAttributeData obsoleteData)
        {
            bool hasAnyDiagnostics;

            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.ObsoleteAttribute))
            {
                attributeData = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
                if (!attributeData.HasErrors)
                {
                    obsoleteData = attributeData.DecodeObsoleteAttribute();
                    if (hasAnyDiagnostics)
                    {
                        attributeData = null;
                    }
                }
                else
                {
                    obsoleteData = null;
                    attributeData = null;
                }

                return true;
            }

            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.DeprecatedAttribute))
            {
                attributeData = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
                if (!attributeData.HasErrors)
                {
                    obsoleteData = attributeData.DecodeDeprecatedAttribute();
                    if (hasAnyDiagnostics)
                    {
                        attributeData = null;
                    }
                }
                else
                {
                    obsoleteData = null;
                    attributeData = null;
                }

                return true;
            }

            obsoleteData = null;
            attributeData = null;
            return false;
        }
Пример #6
0
        // Method to bind all attributes (attribute arguments and constructor)
        internal static void GetAttributes(
            ImmutableArray<Binder> binders,
            ImmutableArray<AttributeSyntax> attributesToBind,
            ImmutableArray<NamedTypeSymbol> boundAttributeTypes,
            CSharpAttributeData[] attributesBuilder,
            DiagnosticBag diagnostics)
        {
            Debug.Assert(binders.Any());
            Debug.Assert(attributesToBind.Any());
            Debug.Assert(boundAttributeTypes.Any());
            Debug.Assert(binders.Length == attributesToBind.Length);
            Debug.Assert(boundAttributeTypes.Length == attributesToBind.Length);
            Debug.Assert(attributesBuilder != null);

            for (int i = 0; i < attributesToBind.Length; i++)
            {
                AttributeSyntax attributeSyntax = attributesToBind[i];
                NamedTypeSymbol boundAttributeType = boundAttributeTypes[i];
                Binder binder = binders[i];

                var attribute = (SourceAttributeData)attributesBuilder[i];
                if (attribute == null)
                {
                    attributesBuilder[i] = binder.GetAttribute(attributeSyntax, boundAttributeType, diagnostics);
                }
                else
                {
                    // attributesBuilder might contain some early bound well-known attributes, which had no errors.
                    // We don't rebind the early bound attributes, but need to compute isConditionallyOmitted.
                    // Note that AttributeData.IsConditionallyOmitted is required only during emit, but must be computed here as
                    // its value depends on the values of conditional symbols, which in turn depends on the source file where the attribute is applied.

                    Debug.Assert(!attribute.HasErrors);
                    HashSet<DiagnosticInfo> useSiteDiagnostics = null;
                    bool isConditionallyOmitted = binder.IsAttributeConditionallyOmitted(attribute.AttributeClass, attributeSyntax.SyntaxTree, ref useSiteDiagnostics);
                    diagnostics.Add(attributeSyntax, useSiteDiagnostics);
                    attributesBuilder[i] = attribute.WithOmittedCondition(isConditionallyOmitted);
                }
            }
        }
Пример #7
0
        private void ValidateConditionalAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
        {
            Debug.Assert(this.IsConditional);
            Debug.Assert(!attribute.HasErrors);

            if (!this.DeclaringCompilation.IsAttributeType(this))
            {
                // CS1689: Attribute '{0}' is only valid on methods or attribute classes
                diagnostics.Add(ErrorCode.ERR_ConditionalOnNonAttributeClass, node.Location, node.GetErrorDisplayName());
            }
            else
            {
                string name = attribute.GetConstructorArgument <string>(0, SpecialType.System_String);

                if (name == null || !SyntaxFacts.IsValidIdentifier(name))
                {
                    // CS0633: The argument to the '{0}' attribute must be a valid identifier
                    CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node);
                    diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, attributeArgumentSyntax.Location, node.GetErrorDisplayName());
                }
            }
        }
Пример #8
0
        // Process the specified AttributeUsage attribute on the given ownerSymbol
        private AttributeUsageInfo DecodeAttributeUsageAttribute(CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt = null)
        {
            Debug.Assert(diagnose == (diagnosticsOpt != null));
            Debug.Assert(!attribute.HasErrors);

            Debug.Assert(!this.IsErrorType());

            // AttributeUsage can only be specified for attribute classes
            if (!this.DeclaringCompilation.IsAttributeType(this))
            {
                if (diagnose)
                {
                    diagnosticsOpt.Add(ErrorCode.ERR_AttributeUsageOnNonAttributeClass, node.Name.Location, node.GetErrorDisplayName());
                }

                return(AttributeUsageInfo.Null);
            }
            else
            {
                AttributeUsageInfo info = attribute.DecodeAttributeUsageAttribute();

                // Validate first ctor argument for AtributeUsage specification is a valid AttributeTargets enum member
                if (!info.HasValidAttributeTargets)
                {
                    if (diagnose)
                    {
                        // invalid attribute target
                        CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node);
                        diagnosticsOpt.Add(ErrorCode.ERR_InvalidAttributeArgument, attributeArgumentSyntax.Location, node.GetErrorDisplayName());
                    }

                    return(AttributeUsageInfo.Null);
                }

                return(info);
            }
        }
Пример #9
0
 private void ValidateIndexerNameAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
 {
     if (!this.IsIndexer || this.IsExplicitInterfaceImplementation)
     {
         diagnostics.Add(ErrorCode.ERR_BadIndexerNameAttr, node.Name.Location, node.GetErrorDisplayName());
     }
     else
     {
         string indexerName = attribute.CommonConstructorArguments[0].DecodeValue<string>(SpecialType.System_String);
         if (indexerName == null || !SyntaxFacts.IsValidIdentifier(indexerName))
         {
             diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, node.ArgumentList.Arguments[0].Location, node.GetErrorDisplayName());
         }
     }
 }
Пример #10
0
        /// <summary>
        /// Validate attribute usage target and duplicate attributes.
        /// </summary>
        /// <param name="attribute">Bound attribute</param>
        /// <param name="node">Syntax node for attribute specification</param>
        /// <param name="compilation">Compilation</param>
        /// <param name="symbolPart">Symbol part to which the attribute has been applied.</param>
        /// <param name="diagnostics">Diagnostics</param>
        /// <param name="uniqueAttributeTypes">Set of unique attribute types applied to the symbol</param>
        private bool ValidateAttributeUsage(
            CSharpAttributeData attribute,
            AttributeSyntax node,
            CSharpCompilation compilation,
            AttributeLocation symbolPart,
            DiagnosticBag diagnostics,
            HashSet<NamedTypeSymbol> uniqueAttributeTypes)
        {
            Debug.Assert(!attribute.HasErrors);

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

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

            // Verify if the attribute type can be applied to given owner symbol.
            AttributeTargets attributeTarget;
            if (symbolPart == AttributeLocation.Return)
            {
                // attribute on return type
                Debug.Assert(this.Kind == SymbolKind.Method);
                attributeTarget = AttributeTargets.ReturnValue;
            }
            else
            {
                attributeTarget = this.GetAttributeTarget();
            }

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

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

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

            return true;
        }
Пример #11
0
        /// <summary>
        /// Method to early decode certain well-known attributes which can be queried by the binder.
        /// This method is called during attribute binding after we have bound the attribute types for all attributes,
        /// but haven't yet bound the attribute arguments/attribute constructor.
        /// Early decoding certain well-known attributes enables the binder to use this decoded information on this symbol
        /// when binding the attribute arguments/attribute constructor without causing attribute binding cycle.
        /// </summary>
        internal EarlyWellKnownAttributeData EarlyDecodeWellKnownAttributes(
            ImmutableArray<Binder> binders,
            ImmutableArray<NamedTypeSymbol> boundAttributeTypes,
            ImmutableArray<AttributeSyntax> attributesToBind,
            AttributeLocation symbolPart,
            CSharpAttributeData[] boundAttributesBuilder)
        {
            Debug.Assert(boundAttributeTypes.Any());
            Debug.Assert(attributesToBind.Any());
            Debug.Assert(binders.Any());
            Debug.Assert(boundAttributesBuilder != null);
            Debug.Assert(!boundAttributesBuilder.Contains((attr) => attr != null));

            var earlyBinder = new EarlyWellKnownAttributeBinder(binders[0]);
            var arguments = new EarlyDecodeWellKnownAttributeArguments<EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation>();
            arguments.SymbolPart = symbolPart;

            for (int i = 0; i < boundAttributeTypes.Length; i++)
            {
                NamedTypeSymbol boundAttributeType = boundAttributeTypes[i];
                if (!boundAttributeType.IsErrorType())
                {
                    if (binders[i] != earlyBinder.Next)
                    {
                        earlyBinder = new EarlyWellKnownAttributeBinder(binders[i]);
                    }

                    arguments.Binder = earlyBinder;
                    arguments.AttributeType = boundAttributeType;
                    arguments.AttributeSyntax = attributesToBind[i];

                    // Early bind some well-known attributes
                    CSharpAttributeData earlyBoundAttributeOpt = this.EarlyDecodeWellKnownAttribute(ref arguments);
                    Debug.Assert(earlyBoundAttributeOpt == null || !earlyBoundAttributeOpt.HasErrors);

                    boundAttributesBuilder[i] = earlyBoundAttributeOpt;
                }
            }

            return arguments.HasDecodedData ? arguments.DecodedData : null;
        }
Пример #12
0
        /// <summary>
        /// This method does the following set of operations in the specified order:
        /// (1) GetAttributesToBind: Merge attributes from the given attributesSyntaxLists and filter out attributes by attribute target.
        /// (2) BindAttributeTypes: Bind all the attribute types to enable early decode of certain well-known attributes by type.
        /// (3) EarlyDecodeWellKnownAttributes: Perform early decoding of certain well-known attributes that could be queried by the binder in subsequent steps.
        ///     (NOTE: This step has the side effect of updating the symbol state based on the data extracted from well known attributes).
        /// (4) GetAttributes: Bind the attributes (attribute arguments and constructor) using bound attribute types.
        /// (5) DecodeWellKnownAttributes: Decode and validate bound well known attributes.
        ///     (NOTE: This step has the side effect of updating the symbol state based on the data extracted from well known attributes).
        /// (6) StoreBoundAttributesAndDoPostValidation:
        ///     (a) Store the bound attributes in lazyCustomAttributes in a thread safe manner.
        ///     (b) Perform some additional post attribute validations, such as
        ///         1) Duplicate attributes, attribute usage target validation, etc.
        ///         2) Post validation for attributes dependant on other attributes
        ///         These validations cannot be performed prior to step 6(a) as we might need to
        ///         perform a GetAttributes() call on a symbol which can introduce a cycle in attribute binding.
        ///         We avoid this cycle by performing such validations in PostDecodeWellKnownAttributes after lazyCustomAttributes have been set.
        ///     NOTE: PostDecodeWellKnownAttributes SHOULD NOT change the symbol state.
        /// </summary>
        /// <remarks>
        /// Current design of early decoding well-known attributes doesn't permit decoding attribute arguments/constructor as this can lead to binding cycles.
        /// For well-known attributes used by the binder, where we need the decoded arguments, we must handle them specially in one of the following possible ways:
        ///   (a) Avoid decoding the attribute arguments during binding and delay the corresponding binder tasks to a separate post-pass executed after binding.
        ///   (b) As the cycles can be caused only when we are binding attribute arguments/constructor, special case the corresponding binder tasks based on the current BinderFlags.
        /// </remarks>
        /// <param name="attributesSyntaxLists"></param>
        /// <param name="lazyCustomAttributesBag"></param>
        /// <param name="symbolPart">Specific part of the symbol to which the attributes apply, or <see cref="AttributeLocation.None"/> if the attributes apply to the symbol itself.</param>
        /// <param name="earlyDecodingOnly">Indicates that only early decoding should be performed.  WARNING: the resulting bag will not be sealed.</param>
        /// <returns>Flag indicating whether lazyCustomAttributes were stored on this thread. Caller should check for this flag and perform NotePartComplete if true.</returns>
        internal bool LoadAndValidateAttributes(
            OneOrMany<SyntaxList<AttributeListSyntax>> attributesSyntaxLists,
            ref CustomAttributesBag<CSharpAttributeData> lazyCustomAttributesBag,
            AttributeLocation symbolPart = AttributeLocation.None,
            bool earlyDecodingOnly = false)
        {
            var diagnostics = DiagnosticBag.GetInstance();
            var compilation = this.DeclaringCompilation;

            ImmutableArray<Binder> binders;
            ImmutableArray<AttributeSyntax> attributesToBind = this.GetAttributesToBind(attributesSyntaxLists, symbolPart, diagnostics, compilation, out binders);
            Debug.Assert(!attributesToBind.IsDefault);

            ImmutableArray<CSharpAttributeData> boundAttributes;
            WellKnownAttributeData wellKnownAttributeData;

            if (attributesToBind.Any())
            {
                Debug.Assert(!binders.IsDefault);
                Debug.Assert(binders.Length == attributesToBind.Length);

                // Initialize the bag so that data decoded from early attributes can be stored onto it.
                if (lazyCustomAttributesBag == null)
                {
                    Interlocked.CompareExchange(ref lazyCustomAttributesBag, new CustomAttributesBag<CSharpAttributeData>(), null);
                }

                // Bind the attribute types and then early decode them.
                int totalAttributesCount = attributesToBind.Length;
                var attributeTypesBuilder = new NamedTypeSymbol[totalAttributesCount];

                Binder.BindAttributeTypes(binders, attributesToBind, this, attributeTypesBuilder, diagnostics);
                ImmutableArray<NamedTypeSymbol> boundAttributeTypes = attributeTypesBuilder.AsImmutableOrNull();

                this.EarlyDecodeWellKnownAttributeTypes(boundAttributeTypes, attributesToBind);
                this.PostEarlyDecodeWellKnownAttributeTypes();

                // Bind the attribute in two stages - early and normal.
                var attributesBuilder = new CSharpAttributeData[totalAttributesCount];

                // Early bind and decode some well-known attributes.
                EarlyWellKnownAttributeData earlyData = this.EarlyDecodeWellKnownAttributes(binders, boundAttributeTypes, attributesToBind, symbolPart, attributesBuilder);
                Debug.Assert(!attributesBuilder.Contains((attr) => attr != null && attr.HasErrors));

                // Store data decoded from early bound well-known attributes.
                // TODO: what if this succeeds on another thread, not ours?
                lazyCustomAttributesBag.SetEarlyDecodedWellKnownAttributeData(earlyData);

                if (earlyDecodingOnly)
                {
                    diagnostics.Free(); //NOTE: dropped.
                    return false;
                }

                // Bind attributes.
                Binder.GetAttributes(binders, attributesToBind, boundAttributeTypes, attributesBuilder, diagnostics);
                boundAttributes = attributesBuilder.AsImmutableOrNull();

                // All attributes must be bound by now.
                Debug.Assert(!boundAttributes.Any((attr) => attr == null));

                // Validate attribute usage and Decode remaining well-known attributes.
                wellKnownAttributeData = this.ValidateAttributeUsageAndDecodeWellKnownAttributes(binders, attributesToBind, boundAttributes, diagnostics, symbolPart);

                // Store data decoded from remaining well-known attributes.
                // TODO: what if this succeeds on another thread but not this thread?
                lazyCustomAttributesBag.SetDecodedWellKnownAttributeData(wellKnownAttributeData);
            }
            else if (earlyDecodingOnly)
            {
                diagnostics.Free(); //NOTE: dropped.
                return false;
            }
            else
            {
                boundAttributes = ImmutableArray<CSharpAttributeData>.Empty;
                wellKnownAttributeData = null;
                Interlocked.CompareExchange(ref lazyCustomAttributesBag, CustomAttributesBag<CSharpAttributeData>.WithEmptyData(), null);
                this.PostEarlyDecodeWellKnownAttributeTypes();
            }

            this.PostDecodeWellKnownAttributes(boundAttributes, attributesToBind, diagnostics, symbolPart, wellKnownAttributeData);

            // Store attributes into the bag.
            bool lazyAttributesStoredOnThisThread = false;
            if (lazyCustomAttributesBag.SetAttributes(boundAttributes))
            {
                this.RecordPresenceOfBadAttributes(boundAttributes);
                this.AddDeclarationDiagnostics(diagnostics);
                lazyAttributesStoredOnThisThread = true;
                if (lazyCustomAttributesBag.IsEmpty) lazyCustomAttributesBag = CustomAttributesBag<CSharpAttributeData>.Empty;
            }

            Debug.Assert(lazyCustomAttributesBag.IsSealed);
            diagnostics.Free();
            return lazyAttributesStoredOnThisThread;
        }
Пример #13
0
        internal static string?DecodeNotNullIfNotNullAttribute(this CSharpAttributeData attribute)
        {
            var arguments = attribute.CommonConstructorArguments;

            return(arguments.Length == 1 && arguments[0].TryDecodeValue(SpecialType.System_String, out string?value) ? value : null);
        }
        private void VerifySynthesizedDebuggableAttribute(CSharpAttributeData attribute, SourceAssemblySymbol sourceAssembly, OptimizationLevel optimizations)
        {
            var expectedDebuggingMode = DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints;

            if (optimizations == OptimizationLevel.Debug)
            {
                expectedDebuggingMode |=
                    DebuggableAttribute.DebuggingModes.Default |
                    DebuggableAttribute.DebuggingModes.DisableOptimizations |
                    DebuggableAttribute.DebuggingModes.EnableEditAndContinue;
            }

            VerifyDebuggableAttribute(attribute, sourceAssembly, expectedDebuggingMode);
        }
        private void VerifyRuntimeCompatibilityAttribute(CSharpAttributeData attribute, SourceAssemblySymbol sourceAssembly, bool isSynthesized)
        {
            ModuleSymbol module = sourceAssembly.Modules[0];
            NamespaceSymbol compilerServicesNS = Get_System_Runtime_CompilerServices_NamespaceSymbol(module);

            NamedTypeSymbol runtimeCompatibilityAttrType = compilerServicesNS.GetTypeMember("RuntimeCompatibilityAttribute");
            var runtimeCompatibilityCtor = (MethodSymbol)sourceAssembly.DeclaringCompilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute__ctor);

            Assert.Equal(runtimeCompatibilityAttrType, attribute.AttributeClass);
            Assert.Equal(runtimeCompatibilityCtor, attribute.AttributeConstructor);

            Assert.Equal(0, attribute.CommonConstructorArguments.Length);

            if (isSynthesized)
            {
                Assert.Equal(1, attribute.CommonNamedArguments.Length);
                attribute.VerifyNamedArgumentValue<bool>(0, "WrapNonExceptionThrows", TypedConstantKind.Primitive, true);
            }
            else
            {
                Assert.Equal(0, attribute.CommonNamedArguments.Length);
            }
        }
        private ConstantValue DecodeDefaultParameterValueAttribute(AttributeDescription description, CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt)
        {
            Debug.Assert(!attribute.HasErrors);

            if (description.Equals(AttributeDescription.DefaultParameterValueAttribute))
            {
                return DecodeDefaultParameterValueAttribute(attribute, node, diagnose, diagnosticsOpt);
            }
            else if (description.Equals(AttributeDescription.DecimalConstantAttribute))
            {
                return attribute.DecodeDecimalConstantValue();
            }
            else
            {
                Debug.Assert(description.Equals(AttributeDescription.DateTimeConstantAttribute));
                return attribute.DecodeDateTimeConstantValue();
            }
        }
Пример #17
0
        internal override CSharpAttributeData EarlyDecodeWellKnownAttribute(ref EarlyDecodeWellKnownAttributeArguments <EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments)
        {
            bool hasAnyDiagnostics;
            CSharpAttributeData boundAttribute;

            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.ComImportAttribute))
            {
                boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
                if (!boundAttribute.HasErrors)
                {
                    arguments.GetOrCreateData <CommonTypeEarlyWellKnownAttributeData>().HasComImportAttribute = true;
                    if (!hasAnyDiagnostics)
                    {
                        return(boundAttribute);
                    }
                }

                return(null);
            }

            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.ConditionalAttribute))
            {
                boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
                if (!boundAttribute.HasErrors)
                {
                    string name = boundAttribute.GetConstructorArgument <string>(0, SpecialType.System_String);
                    arguments.GetOrCreateData <CommonTypeEarlyWellKnownAttributeData>().AddConditionalSymbol(name);
                    if (!hasAnyDiagnostics)
                    {
                        return(boundAttribute);
                    }
                }

                return(null);
            }

            ObsoleteAttributeData obsoleteData;

            if (EarlyDecodeDeprecatedOrObsoleteAttribute(ref arguments, out boundAttribute, out obsoleteData))
            {
                if (obsoleteData != null)
                {
                    arguments.GetOrCreateData <CommonTypeEarlyWellKnownAttributeData>().ObsoleteAttributeData = obsoleteData;
                }

                return(boundAttribute);
            }

            if (CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.AttributeUsageAttribute))
            {
                boundAttribute = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, out hasAnyDiagnostics);
                if (!boundAttribute.HasErrors)
                {
                    AttributeUsageInfo info = this.DecodeAttributeUsageAttribute(boundAttribute, arguments.AttributeSyntax, diagnose: false);
                    if (!info.IsNull)
                    {
                        var typeData = arguments.GetOrCreateData <CommonTypeEarlyWellKnownAttributeData>();
                        if (typeData.AttributeUsageInfo.IsNull)
                        {
                            typeData.AttributeUsageInfo = info;
                        }

                        if (!hasAnyDiagnostics)
                        {
                            return(boundAttribute);
                        }
                    }
                }

                return(null);
            }

            return(base.EarlyDecodeWellKnownAttribute(ref arguments));
        }
Пример #18
0
        private void ValidateConditionalAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
        {
            Debug.Assert(this.IsConditional);
            Debug.Assert(!attribute.HasErrors);

            if (!this.DeclaringCompilation.IsAttributeType(this))
            {
                // CS1689: Attribute '{0}' is only valid on methods or attribute classes
                diagnostics.Add(ErrorCode.ERR_ConditionalOnNonAttributeClass, node.Location, node.GetErrorDisplayName());
            }
            else
            {
                string name = attribute.GetConstructorArgument<string>(0, SpecialType.System_String);

                if (name == null || !SyntaxFacts.IsValidIdentifier(name))
                {
                    // CS0633: The argument to the '{0}' attribute must be a valid identifier
                    CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node);
                    diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, attributeArgumentSyntax.Location, node.GetErrorDisplayName());
                }
            }
        }
Пример #19
0
        // Process the specified AttributeUsage attribute on the given ownerSymbol
        private AttributeUsageInfo DecodeAttributeUsageAttribute(CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt = null)
        {
            Debug.Assert(diagnose == (diagnosticsOpt != null));
            Debug.Assert(!attribute.HasErrors);

            Debug.Assert(!this.IsErrorType());

            // AttributeUsage can only be specified for attribute classes
            if (!this.DeclaringCompilation.IsAttributeType(this))
            {
                if (diagnose)
                {
                    diagnosticsOpt.Add(ErrorCode.ERR_AttributeUsageOnNonAttributeClass, node.Name.Location, node.GetErrorDisplayName());
                }

                return AttributeUsageInfo.Null;
            }
            else
            {
                AttributeUsageInfo info = attribute.DecodeAttributeUsageAttribute();

                // Validate first ctor argument for AtributeUsage specification is a valid AttributeTargets enum member
                if (!info.HasValidAttributeTargets)
                {
                    if (diagnose)
                    {
                        // invalid attribute target
                        CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node);
                        diagnosticsOpt.Add(ErrorCode.ERR_InvalidAttributeArgument, attributeArgumentSyntax.Location, node.GetErrorDisplayName());
                    }

                    return AttributeUsageInfo.Null;
                }

                return info;
            }
        }
Пример #20
0
        private void ValidateConditionalAttribute(CSharpAttributeData attribute, AttributeSyntax node, DiagnosticBag diagnostics)
        {
            Debug.Assert(this.IsConditional);

            if (this.IsAccessor())
            {
                // CS1667: Attribute '{0}' is not valid on property or event accessors. It is only valid on '{1}' declarations.
                AttributeUsageInfo attributeUsage = attribute.AttributeClass.GetAttributeUsageInfo();
                diagnostics.Add(ErrorCode.ERR_AttributeNotOnAccessor, node.Name.Location, node.GetErrorDisplayName(), attributeUsage.GetValidTargetsString());
            }
            else if (this.ContainingType.IsInterfaceType())
            {
                // CS0582: The Conditional attribute is not valid on interface members
                diagnostics.Add(ErrorCode.ERR_ConditionalOnInterfaceMethod, node.Location);
            }
            else if (this.IsOverride)
            {
                // CS0243: The Conditional attribute is not valid on '{0}' because it is an override method
                diagnostics.Add(ErrorCode.ERR_ConditionalOnOverride, node.Location, this);
            }
            else if (!this.CanBeReferencedByName || this.MethodKind == MethodKind.Destructor)
            {
                // CS0577: The Conditional attribute is not valid on '{0}' because it is a constructor, destructor, operator, or explicit interface implementation
                diagnostics.Add(ErrorCode.ERR_ConditionalOnSpecialMethod, node.Location, this);
            }
            else if (!this.ReturnsVoid)
            {
                // CS0578: The Conditional attribute is not valid on '{0}' because its return type is not void
                diagnostics.Add(ErrorCode.ERR_ConditionalMustReturnVoid, node.Location, this);
            }
            else if (this.HasAnyOutParameter())
            {
                // CS0685: Conditional member '{0}' cannot have an out parameter
                diagnostics.Add(ErrorCode.ERR_ConditionalWithOutParam, node.Location, this);
            }
            else
            {
                string name = attribute.GetConstructorArgument<string>(0, SpecialType.System_String);

                if (name == null || !SyntaxFacts.IsValidIdentifier(name))
                {
                    // CS0633: The argument to the '{0}' attribute must be a valid identifier
                    CSharpSyntaxNode attributeArgumentSyntax = attribute.GetAttributeArgumentSyntax(0, node);
                    diagnostics.Add(ErrorCode.ERR_BadArgumentToAttribute, attributeArgumentSyntax.Location, node.GetErrorDisplayName());
                }
            }
        }
        internal static void VerifyUnverifiableCodeAttribute(CSharpAttributeData moduleAttribute, CSharpCompilation compilation)
        {
            Assert.Equal(compilation.GetWellKnownType(WellKnownType.System_Security_UnverifiableCodeAttribute), moduleAttribute.AttributeClass);
            Assert.Equal(compilation.GetWellKnownTypeMember(WellKnownMember.System_Security_UnverifiableCodeAttribute__ctor), moduleAttribute.AttributeConstructor);

            Assert.Equal(0, moduleAttribute.CommonConstructorArguments.Length);
            Assert.Equal(0, moduleAttribute.CommonNamedArguments.Length);
        }
Пример #22
0
        private bool TryGetAttributeWarningLocation(CSharpAttributeData attribute, out Location location)
        {
            SyntaxReference syntaxRef = attribute.ApplicationSyntaxReference;
            if (syntaxRef == null && _filterTree == null)
            {
                location = NoLocation.Singleton;
                return true;
            }
            else if (_filterTree == null || (syntaxRef != null && syntaxRef.SyntaxTree == _filterTree))
            {
                System.Diagnostics.Debug.Assert(syntaxRef.SyntaxTree.HasCompilationUnitRoot);
                location = new SourceLocation(syntaxRef);
                return true;
            }

            location = null;
            return false;
        }
        private void VerifyCompilationRelaxationsAttribute(CSharpAttributeData attribute, SourceAssemblySymbol sourceAssembly, bool isSynthesized)
        {
            ModuleSymbol module = sourceAssembly.Modules[0];
            NamespaceSymbol compilerServicesNS = Get_System_Runtime_CompilerServices_NamespaceSymbol(module);

            NamedTypeSymbol compilationRelaxationsAttrType = compilerServicesNS.GetTypeMember("CompilationRelaxationsAttribute");
            var compilationRelaxationsCtor = (MethodSymbol)sourceAssembly.DeclaringCompilation.GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_CompilationRelaxationsAttribute__ctorInt32);

            Assert.Equal(compilationRelaxationsAttrType, attribute.AttributeClass);
            Assert.Equal(compilationRelaxationsCtor, attribute.AttributeConstructor);

            int expectedArgValue = isSynthesized ? (int)CompilationRelaxations.NoStringInterning : 0;
            Assert.Equal(1, attribute.CommonConstructorArguments.Length);
            attribute.VerifyValue<int>(0, TypedConstantKind.Primitive, expectedArgValue);

            Assert.Equal(0, attribute.CommonNamedArguments.Length);
        }
Пример #24
0
        private ConstantValue DecodeDefaultParameterValueAttribute(AttributeDescription description, CSharpAttributeData attribute, AttributeSyntax node, bool diagnose, DiagnosticBag diagnosticsOpt)
        {
            Debug.Assert(!attribute.HasErrors);

            if (description.Equals(AttributeDescription.DefaultParameterValueAttribute))
            {
                return(DecodeDefaultParameterValueAttribute(attribute, node, diagnose, diagnosticsOpt));
            }
            else if (description.Equals(AttributeDescription.DecimalConstantAttribute))
            {
                return(attribute.DecodeDecimalConstantValue());
            }
            else
            {
                Debug.Assert(description.Equals(AttributeDescription.DateTimeConstantAttribute));
                return(attribute.DecodeDateTimeConstantValue());
            }
        }
        // NYI: /addmodule support
        // TODO: Add tests for assembly attributes emitted into netmodules which suppress synthesized CompilationRelaxationsAttribute/RuntimeCompatibilityAttribute

        #endregion

        #region DebuggableAttribute

        private void VerifyDebuggableAttribute(CSharpAttributeData attribute, SourceAssemblySymbol sourceAssembly, DebuggableAttribute.DebuggingModes expectedDebuggingMode)
        {
            ModuleSymbol module = sourceAssembly.Modules[0];
            NamespaceSymbol diagnosticsNS = Get_System_Diagnostics_NamespaceSymbol(module);

            NamedTypeSymbol debuggableAttributeType = diagnosticsNS.GetTypeMember("DebuggableAttribute");
            var debuggableAttributeCtor = (MethodSymbol)sourceAssembly.DeclaringCompilation.GetWellKnownTypeMember(WellKnownMember.System_Diagnostics_DebuggableAttribute__ctorDebuggingModes);

            Assert.Equal(debuggableAttributeType, attribute.AttributeClass);
            Assert.Equal(debuggableAttributeCtor, attribute.AttributeConstructor);

            Assert.Equal(1, attribute.CommonConstructorArguments.Length);
            attribute.VerifyValue(0, TypedConstantKind.Enum, (int)expectedDebuggingMode);

            Assert.Equal(0, attribute.CommonNamedArguments.Length);
        }
Пример #26
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));
        }
Пример #27
0
        private void VerifySynthesizedDebuggableAttribute(CSharpAttributeData attribute, SourceAssemblySymbol sourceAssembly, DebugInformationKind emitDebugInfoKind, bool optimizationsEnabled)
        {
            Assert.NotEqual(DebugInformationKind.None, emitDebugInfoKind);

            var expectedDebuggingMode = DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints;

            bool emittingFullDebugInfo = emitDebugInfoKind == DebugInformationKind.Full;
            if (emittingFullDebugInfo)
            {
                expectedDebuggingMode |= DebuggableAttribute.DebuggingModes.Default;
            }

            if (!optimizationsEnabled)
            {
                expectedDebuggingMode |= DebuggableAttribute.DebuggingModes.DisableOptimizations;

                if (emittingFullDebugInfo)
                {
                    expectedDebuggingMode |= DebuggableAttribute.DebuggingModes.EnableEditAndContinue;
                }
            }

            VerifyDebuggableAttribute(attribute, sourceAssembly, expectedDebuggingMode);
        }
        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);
        }