コード例 #1
0
        protected static string ReportAttribute(CSharpAttributeData attribute)
        {
            var builder = new StringBuilder();

            builder.Append('[');

            Assert.NotNull(attribute.AttributeClass);
            var name = attribute.AttributeClass !.Name;

            if (name.EndsWith("Attribute"))
            {
                name = name.Substring(0, name.Length - 9);
            }
            builder.Append(name);

            var arguments = attribute.ConstructorArguments.ToImmutableArray();

            if (arguments.Length > 0)
            {
                builder.Append('(');
                printValues(builder, arguments);
                builder.Append(')');
            }

            builder.Append(']');
            return(builder.ToString());
コード例 #2
0
ファイル: Extensions.cs プロジェクト: zuckerthoben/roslyn
        public static void VerifyValue <T>(this CSharpAttributeData attr, int i, TypedConstantKind kind, T v)
        {
            var arg = attr.CommonConstructorArguments[i];

            Assert.Equal(kind, arg.Kind);
            Assert.True(IsEqual(arg, v));
        }
コード例 #3
0
        private static string ReportAttribute(CSharpAttributeData attribute)
        {
            var builder = new StringBuilder();

            builder.Append("[");

            var name = attribute.AttributeClass.Name;

            if (name.EndsWith("Attribute"))
            {
                name = name.Substring(0, name.Length - 9);
            }
            builder.Append(name);

            var arguments = attribute.ConstructorArguments.ToImmutableArray();

            if (arguments.Length > 0)
            {
                builder.Append("(");
                printValues(builder, arguments);
                builder.Append(")");
            }

            builder.Append("]");
            return(builder.ToString());
コード例 #4
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.GetErrorDisplayName());
                return(false);
            }

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

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

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

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

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

            return(true);
        }
コード例 #5
0
ファイル: Symbol_Attributes.cs プロジェクト: belav/roslyn
        private WellKnownAttributeData ValidateAttributeUsageAndDecodeWellKnownAttributes(
            ImmutableArray <Binder> binders,
            ImmutableArray <AttributeSyntax> attributeSyntaxList,
            ImmutableArray <CSharpAttributeData> boundAttributes,
            BindingDiagnosticBag diagnostics,
            AttributeLocation symbolPart
            )
        {
            Debug.Assert(binders.Any());
            Debug.Assert(attributeSyntaxList.Any());
            Debug.Assert(boundAttributes.Any());
            Debug.Assert(binders.Length == boundAttributes.Length);
            Debug.Assert(attributeSyntaxList.Length == boundAttributes.Length);

            int totalAttributesCount = boundAttributes.Length;
            HashSet <NamedTypeSymbol> uniqueAttributeTypes = new HashSet <NamedTypeSymbol>();
            var arguments =
                new DecodeWellKnownAttributeArguments <
                    AttributeSyntax,
                    CSharpAttributeData,
                    AttributeLocation
                    >();

            arguments.Diagnostics     = diagnostics;
            arguments.AttributesCount = totalAttributesCount;
            arguments.SymbolPart      = symbolPart;

            for (int i = 0; i < totalAttributesCount; i++)
            {
                CSharpAttributeData boundAttribute  = boundAttributes[i];
                AttributeSyntax     attributeSyntax = attributeSyntaxList[i];
                Binder binder = binders[i];

                // Decode attribute as a possible well-known attribute only if it has no binding errors and has valid AttributeUsage.
                if (
                    !boundAttribute.HasErrors &&
                    ValidateAttributeUsage(
                        boundAttribute,
                        attributeSyntax,
                        binder.Compilation,
                        symbolPart,
                        diagnostics,
                        uniqueAttributeTypes
                        )
                    )
                {
                    arguments.Attribute          = boundAttribute;
                    arguments.AttributeSyntaxOpt = attributeSyntax;
                    arguments.Index = i;

                    this.DecodeWellKnownAttribute(ref arguments);
                }
            }

            return(arguments.HasDecodedData ? arguments.DecodedData : null);
        }
コード例 #6
0
ファイル: Extensions.cs プロジェクト: zuckerthoben/roslyn
        public static void VerifyNamedArgumentValue <T>(this CSharpAttributeData attr, int i, string name, TypedConstantKind kind, T v)
        {
            var namedArg = attr.CommonNamedArguments[i];

            Assert.Equal(namedArg.Key, name);
            var arg = namedArg.Value;

            Assert.Equal(arg.Kind, kind);
            Assert.True(IsEqual(arg, v));
        }
コード例 #7
0
ファイル: SymbolAdapter.cs プロジェクト: belav/roslyn
        private IEnumerable <CSharpAttributeData> GetCustomAttributesToEmitIterator(
            ImmutableArray <CSharpAttributeData> userDefined,
            ArrayBuilder <SynthesizedAttributeData> synthesized,
            bool isReturnType,
            bool emittingAssemblyAttributesInNetModule
            )
        {
            CheckDefinitionInvariant();

            if (synthesized != null)
            {
                foreach (var attribute in synthesized)
                {
                    // only synthesize attributes that are emitted:
                    Debug.Assert(
                        attribute.ShouldEmitAttribute(
                            this,
                            isReturnType,
                            emittingAssemblyAttributesInNetModule
                            )
                        );
                    yield return(attribute);
                }

                synthesized.Free();
            }

            for (int i = 0; i < userDefined.Length; i++)
            {
                CSharpAttributeData attribute = userDefined[i];
                if (this.Kind == SymbolKind.Assembly)
                {
                    // We need to filter out duplicate assembly attributes (i.e. attributes that
                    // bind to the same constructor and have identical arguments) and invalid
                    // InternalsVisibleTo attributes.
                    if (((SourceAssemblySymbol)this).IsIndexOfOmittedAssemblyAttribute(i))
                    {
                        continue;
                    }
                }

                if (
                    attribute.ShouldEmitAttribute(
                        this,
                        isReturnType,
                        emittingAssemblyAttributesInNetModule
                        )
                    )
                {
                    yield return(attribute);
                }
            }
        }
コード例 #8
0
ファイル: Symbol_Attributes.cs プロジェクト: belav/roslyn
        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);
        }
コード例 #9
0
        public override void VisitMethod(MethodSymbol method)
        {
            var previousContext = _nullableContext;

            _nullableContext = GetNullableContextAttribute(method.GetAttributes()) ?? _nullableContext;

            ReportSymbol(method);
            VisitList(method.TypeParameters);
            VisitList(method.Parameters);

            _nullableContext = previousContext;
        }
コード例 #10
0
ファイル: Symbol_Attributes.cs プロジェクト: zlphoenix/roslyn
        internal static 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);
        }
コード例 #11
0
        internal static bool EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute(
            ref EarlyDecodeWellKnownAttributeArguments <EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation> arguments,
            out CSharpAttributeData attributeData,
            out ObsoleteAttributeData obsoleteData)
        {
            var type   = arguments.AttributeType;
            var syntax = arguments.AttributeSyntax;

            ObsoleteAttributeKind kind;

            if (CSharpAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.ObsoleteAttribute))
            {
                kind = ObsoleteAttributeKind.Obsolete;
            }
            else if (CSharpAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.DeprecatedAttribute))
            {
                kind = ObsoleteAttributeKind.Deprecated;
            }
            else if (CSharpAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.ExperimentalAttribute))
            {
                kind = ObsoleteAttributeKind.Experimental;
            }
            else
            {
                obsoleteData  = null;
                attributeData = null;
                return(false);
            }

            bool hasAnyDiagnostics;

            attributeData = arguments.Binder.GetAttribute(syntax, type, out hasAnyDiagnostics);
            if (!attributeData.HasErrors)
            {
                obsoleteData = attributeData.DecodeObsoleteAttribute(kind);
                if (hasAnyDiagnostics)
                {
                    attributeData = null;
                }
            }
            else
            {
                obsoleteData  = null;
                attributeData = null;
            }
            return(true);
        }
コード例 #12
0
        public override void VisitNamedType(NamedTypeSymbol type)
        {
            var previousContext = _nullableContext;

            _nullableContext = GetNullableContextAttribute(type.GetAttributes()) ?? _nullableContext;

            ReportSymbol(type);
            VisitList(type.TypeParameters);

            foreach (var member in type.GetMembers())
            {
                // Skip accessors since those are covered by associated symbol.
                if (member.IsAccessor())
                {
                    continue;
                }
                Visit(member);
            }

            _nullableContext = previousContext;
        }
コード例 #13
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 dependent 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>
        /// <param name="binderOpt">Binder to use. If null, <see cref="DeclaringCompilation"/> GetBinderFactory will be used.</param>
        /// <param name="attributeMatchesOpt">If specified, only load attributes that match this predicate, and any diagnostics produced will be dropped.</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 <AttributeSyntax> > attributesSyntaxLists,
            ref CustomAttributesBag <CSharpAttributeData> lazyCustomAttributesBag,
            AttributeLocation symbolPart = AttributeLocation.None,
            bool earlyDecodingOnly       = false,
            Binder binderOpt             = null,
            Func <AttributeSyntax, bool> attributeMatchesOpt = null,
            Func <Binder, Binder> contextualBinder           = null
            )
        {
            var diagnostics = DiagnosticBag.GetInstance();
            var compilation = this.DeclaringCompilation;

            ImmutableArray <Binder>          binders;
            ImmutableArray <AttributeSyntax> attributesToBind = this.GetAttributesToBind(attributesSyntaxLists, symbolPart, diagnostics, compilation, attributeMatchesOpt, binderOpt, out binders, contextualBinder);

            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))
            {
                if (attributeMatchesOpt is null)
                {
                    this.RecordPresenceOfBadAttributes(boundAttributes);
                    AddDeclarationDiagnostics(diagnostics);
                }
                lazyAttributesStoredOnThisThread = true;
                if (lazyCustomAttributesBag.IsEmpty)
                {
                    lazyCustomAttributesBag = CustomAttributesBag <CSharpAttributeData> .Empty;
                }
            }

            Debug.Assert(lazyCustomAttributesBag.IsSealed);
            diagnostics.Free();
            return(lazyAttributesStoredOnThisThread);
        }
コード例 #14
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.GetErrorDisplayName());
                return(false);
            }

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

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

            if ((attributeTarget & attributeUsageInfo.ValidTargets) == 0)
            {
#if XSHARP
                // The ClipperCallingConvention Attribute in VulcanRT has incorrect Targets (Method, but should also be allowed on Constructors)
                if (node.Name.ToString().ToLower().IndexOf(OurTypeNames.ClipperCallingConventionAttribute, XSharpString.Comparison) == -1)
                {
#endif
                // generate error
                diagnostics.Add(ErrorCode.ERR_AttributeOnBadSymbolType, node.Name.Location, node.GetErrorDisplayName(), attributeUsageInfo.GetValidTargetsErrorArgument());
                return(false);

#if XSHARP
            }
#endif
            }

            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);
        }