Esempio n. 1
0
        public override Expression DoResolve(ResolveContext rc)
        {
            if (_resolved)
            {
                return(this);
            }

            left = (FullNamedExpression)left.DoResolve(rc);

            IType t   = left.Type;
            var   nxt = spec;

            while (nxt != null)
            {
                if (nxt.IsNullable)
                {
                    t = NullableType.Create(rc.Compilation, t);
                }

                else if (nxt.IsPointer)
                {
                    t = new PointerTypeSpec(t);
                }
                else
                {
                    t = new ArrayType(rc.Compilation, t, nxt.Dimension);
                }

                nxt = spec.Next;
            }

            ResolvedType = t;
            _resolved    = true;
            return(this);
        }
Esempio n. 2
0
        public override Expression DoResolve(ResolveContext rc)
        {
            if (_resolved)
            {
                return(this);
            }

            count = count.DoResolve(rc);
            if (count == null)
            {
                return(null);
            }

            if (!count.Type.IsKnownType(KnownTypeCode.UInt32))
            {
                count = new CastExpression(KnownTypeReference.UInt32.Resolve(rc), count).DoResolve(rc);
                if (count == null)
                {
                    return(null);
                }
            }

            Constant c = count as Constant;

            if (c != null && c.IsNegative)
            {
                rc.Report.Error(0, loc, "Cannot use a negative size with stackalloc");
            }


            if (rc.HasAny(ResolveContext.Options.CatchScope | ResolveContext.Options.FinallyScope))
            {
                rc.Report.Error(0, loc, "Cannot use stackalloc in finally or catch");
            }


            otype = texpr.ResolveAsType(rc);
            if (otype == null)
            {
                return(null);
            }

            ResolvedType = new PointerTypeSpec(otype);
            _resolved    = true;
            eclass       = ExprClass.Value;

            return(this);
        }
Esempio n. 3
0
        public Expression ResolveUnaryOperator(ResolveContext rc, UnaryOperatorType op, Expression expression)
        {
            // V# 4.0 spec: §7.3.3 Unary operator overload resolution
            string overloadableOperatorName = GetOverloadableOperatorName(op);

            if (overloadableOperatorName == null)
            {
                switch (op)
                {
                case UnaryOperatorType.Dereference:
                    PointerTypeSpec p = expression.Type as PointerTypeSpec;
                    if (p != null)
                    {
                        return(SetOperationInformations(rc, p.ElementType, op, expression));
                    }
                    else
                    {
                        return(ErrorResult);
                    }

                case UnaryOperatorType.AddressOf:
                    return(SetOperationInformations(rc, new PointerTypeSpec(expression.Type), op, expression));


                default:
                    return(ErrorExpression.UnknownError);
                }
            }
            // If the type is nullable, get the underlying type:
            IType type       = NullableType.GetUnderlyingType(expression.Type);
            bool  isNullable = NullableType.IsNullable(expression.Type);

            // the operator is overloadable:
            OverloadResolution userDefinedOperatorOR = rc.CreateOverloadResolution(new[] { expression });

            foreach (var candidate in rc.GetUserDefinedOperatorCandidates(type, overloadableOperatorName))
            {
                userDefinedOperatorOR.AddCandidate(candidate);
            }
            if (userDefinedOperatorOR.FoundApplicableCandidate)
            {
                return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR));
            }

            expression = UnaryNumericPromotion(rc, op, ref type, isNullable, expression);
            VSharpOperators.OperatorMethod[] methodGroup;
            VSharpOperators operators = VSharpOperators.Get(rc.compilation);

            switch (op)
            {
            case UnaryOperatorType.PreIncrement:
            case UnaryOperatorType.Decrement:
            case UnaryOperatorType.PostIncrement:
            case UnaryOperatorType.PostDecrement:
                // V# 4.0 spec: §7.6.9 Postfix increment and decrement operators
                // V# 4.0 spec: §7.7.5 Prefix increment and decrement operators
                TypeCode code = ReflectionHelper.GetTypeCode(type);
                if ((code >= TypeCode.Char && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer)
                {
                    return(SetOperationInformations(rc, expression.Type, op, expression, isNullable));
                }
                else
                {
                    return(new ErrorExpression(expression.Type));
                }

            case UnaryOperatorType.UnaryPlus:
                methodGroup = operators.UnaryPlusOperators;
                break;

            case UnaryOperatorType.UnaryNegation:
                methodGroup = rc.checkForOverflow ? operators.CheckedUnaryMinusOperators : operators.UncheckedUnaryMinusOperators;
                break;

            case UnaryOperatorType.LogicalNot:
                methodGroup = operators.LogicalNegationOperators;
                break;

            case UnaryOperatorType.OnesComplement:
                if (type.Kind == TypeKind.Enum)
                {
                    if (expression.IsCompileTimeConstant && !isNullable && expression.ConstantValue != null)
                    {
                        // evaluate as (E)(~(U)x);
                        var            U            = rc.compilation.FindType(expression.ConstantValue.GetType());
                        var            unpackedEnum = Constant.CreateConstantFromValue(rc, U, expression.ConstantValue, loc);
                        var            rr           = ResolveUnaryOperator(rc, op, unpackedEnum);
                        ResolveContext ovfrc        = rc.WithCheckForOverflow(false);
                        rr = new CastExpression(type, rr).DoResolve(ovfrc);
                        if (rr.IsCompileTimeConstant)
                        {
                            return(rr);
                        }
                    }
                    return(SetOperationInformations(rc, expression.Type, op, expression, isNullable));
                }
                else
                {
                    methodGroup = operators.BitwiseComplementOperators;
                    break;
                }

            default:
                throw new InvalidOperationException();
            }
            OverloadResolution builtinOperatorOR = rc.CreateOverloadResolution(new[] { expression });

            foreach (var candidate in methodGroup)
            {
                builtinOperatorOR.AddCandidate(candidate);
            }
            VSharpOperators.UnaryOperatorMethod m = (VSharpOperators.UnaryOperatorMethod)builtinOperatorOR.BestCandidate;
            IType resultType = m.ReturnType;

            if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None)
            {
                if (userDefinedOperatorOR.BestCandidate != null)
                {
                    // If there are any user-defined operators, prefer those over the built-in operators.
                    // It'll be a more informative error.
                    return(SetUserDefinedOperationInformations(rc, userDefinedOperatorOR));
                }
                else if (builtinOperatorOR.BestCandidateAmbiguousWith != null)
                {
                    // If the best candidate is ambiguous, just use the input type instead
                    // of picking one of the ambiguous overloads.
                    return(new ErrorExpression(expression.Type));
                }
                else
                {
                    return(new ErrorExpression(resultType));
                }
            }
            else if (expression.IsCompileTimeConstant && m.CanEvaluateAtCompileTime)
            {
                object val;
                try
                {
                    val = m.Invoke(rc, expression.ConstantValue);
                }
                catch (ArithmeticException)
                {
                    return(new ErrorExpression(resultType));
                }
                return(Constant.CreateConstantFromValue(rc, resultType, val, loc));
            }
            else
            {
                expression = rc.Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]);
                return(SetOperationInformations(rc, resultType, op, expression,
                                                builtinOperatorOR.BestCandidate is OverloadResolution.ILiftedOperator));
            }
        }