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