Exemple #1
0
        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));
        }
Exemple #2
0
 internal TypedConstant(ITypeSymbol type, TypedConstantKind kind, object value)
 {
     Debug.Assert(kind == TypedConstantKind.Array || !(value is ImmutableArray <TypedConstant>));
     _kind  = kind;
     _type  = type;
     _value = value;
 }
Exemple #3
0
 public TypedConstant(ITypeSymbol type, TypedConstantKind kind, object value)
 {
     Debug.Assert(kind == TypedConstantKind.Array || !(value is TypedConstant[]));
     _kind  = kind;
     _type  = type;
     _value = value;
 }
        internal TypedConstant(ITypeSymbolInternal?type, TypedConstantKind kind, object?value)
        {
            Debug.Assert(kind == TypedConstantKind.Array || !(value is ImmutableArray <TypedConstant>));
            Debug.Assert(!(value is ISymbol) || value is ISymbolInternal);
            Debug.Assert(type is object || kind == TypedConstantKind.Error);

            _kind  = kind;
            _type  = type;
            _value = value;
        }
Exemple #5
0
        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));
        }
Exemple #6
0
            private TypedConstant VisitExpression(BoundExpression node, TypedConstantKind typedConstantKind, DiagnosticBag diagnostics, ref bool attrHasErrors, bool curArgumentHasErrors)
            {
                // Validate Statement 2) of the spec comment above.

                ConstantValue constantValue = node.ConstantValue;
                if (constantValue != null)
                {
                    if (constantValue.IsBad)
                    {
                        typedConstantKind = TypedConstantKind.Error;
                    }

                    return CreateTypedConstant(node, typedConstantKind, diagnostics, ref attrHasErrors, curArgumentHasErrors, simpleValue: node.ConstantValue.Value);
                }

                switch (node.Kind)
                {
                    case BoundKind.Conversion:
                        return VisitConversion((BoundConversion)node, diagnostics, ref attrHasErrors, curArgumentHasErrors);
                    case BoundKind.TypeOfOperator:
                        return VisitTypeOfExpression((BoundTypeOfOperator)node, diagnostics, ref attrHasErrors, curArgumentHasErrors);
                    case BoundKind.ArrayCreation:
                        return VisitArrayCreation((BoundArrayCreation)node, diagnostics, ref attrHasErrors, curArgumentHasErrors);
                    default:
                        return CreateTypedConstant(node, TypedConstantKind.Error, diagnostics, ref attrHasErrors, curArgumentHasErrors);
                }
            }
Exemple #7
0
            private static TypedConstant CreateTypedConstant(BoundExpression node, TypedConstantKind typedConstantKind, DiagnosticBag diagnostics, ref bool attrHasErrors, bool curArgumentHasErrors,
                object simpleValue = null, ImmutableArray<TypedConstant> arrayValue = default(ImmutableArray<TypedConstant>))
            {
                var type = node.Type;

                if (typedConstantKind != TypedConstantKind.Error && type.ContainsTypeParameter())
                {
                    // Devdiv Bug #12636: Constant values of open types should not be allowed in attributes

                    // SPEC ERROR:  C# language specification does not explicitly disallow constant values of open types. For e.g.

                    //  public class C<T>
                    //  {
                    //      public enum E { V }
                    //  }
                    //
                    //  [SomeAttr(C<T>.E.V)]        // case (a): Constant value of open type.
                    //  [SomeAttr(C<int>.E.V)]      // case (b): Constant value of constructed type.

                    // Both expressions 'C<T>.E.V' and 'C<int>.E.V' satisfy the requirements for a valid attribute-argument-expression:
                    //  (a) Its type is a valid attribute parameter type as per section 17.1.3 of the specification.
                    //  (b) It has a compile time constant value.

                    // However, native compiler disallows both the above cases.
                    // We disallow case (a) as it cannot be serialized correctly, but allow case (b) to compile.

                    typedConstantKind = TypedConstantKind.Error;
                }

                if (typedConstantKind == TypedConstantKind.Error)
                {
                    if (!curArgumentHasErrors)
                    {
                        Binder.Error(diagnostics, ErrorCode.ERR_BadAttributeArgument, node.Syntax);
                        attrHasErrors = true;
                    }

                    return new TypedConstant(type, TypedConstantKind.Error, null);
                }
                else if (typedConstantKind == TypedConstantKind.Array)
                {
                    return new TypedConstant(type, arrayValue);
                }
                else
                {
                    return new TypedConstant(type, typedConstantKind, simpleValue);
                }
            }
Exemple #8
0
 public static TypedConstant CreateTypedConstant(ITypeSymbol typeSymbol, TypedConstantKind kind, object?value) => createTypeConstant(typeSymbol, kind, value);
        /// <summary>
        /// Gets the typed constant kind for the given attribute parameter type.
        /// </summary>
        /// <param name="type">Type to validated</param>
        /// <param name="compilation">compilation</param>
        /// <returns>TypedConstantKind for the attribute parameter type.</returns>
        public static TypedConstantKind GetAttributeParameterTypedConstantKind(this TypeSymbol type, CSharpCompilation compilation)
        {
            // Spec (17.1.3)
            // The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:
            //  1) One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
            //     2) The type object.
            //     3) The type System.Type.
            //     4) An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility.
            //     5) Single-dimensional arrays of the above types.
            // A constructor argument or public field which does not have one of these types, cannot be used as a positional
            // or named parameter in an attribute specification.

            TypedConstantKind kind = TypedConstantKind.Error;

            if ((object)type == null)
            {
                return(TypedConstantKind.Error);
            }

            if (type.Kind == SymbolKind.ArrayType)
            {
                var arrayType = (ArrayTypeSymbol)type;
                if (arrayType.Rank != 1)
                {
                    return(TypedConstantKind.Error);
                }

                kind = TypedConstantKind.Array;
                type = arrayType.ElementType;
            }

            // enum or enum[]
            if (type.IsEnumType())
            {
                // SPEC VIOLATION: Dev11 doesn't enforce either the Enum type or its enclosing types (if any) to have public accessibility.
                // We will be consistent with Dev11 behavior.

                if (kind == TypedConstantKind.Error)
                {
                    // set only if kind is not already set (i.e. its not an array of enum)
                    kind = TypedConstantKind.Enum;
                }

                type = type.GetEnumUnderlyingType();
            }

            var typedConstantKind = TypedConstant.GetTypedConstantKind(type, compilation);

            switch (typedConstantKind)
            {
            case TypedConstantKind.Array:
            case TypedConstantKind.Enum:
            case TypedConstantKind.Error:
                return(TypedConstantKind.Error);

            default:
                if (kind == TypedConstantKind.Array || kind == TypedConstantKind.Enum)
                {
                    // Array/Enum type with valid element/underlying type
                    return(kind);
                }

                return(typedConstantKind);
            }
        }