public static UnaryOperatorKind WithOverflowChecksIfApplicable(this UnaryOperatorKind kind, bool enabled) { if (enabled) { // If it's dynamic and we're in a checked context then just mark it as checked, // regardless of whether it is +x -x !x ~x ++x --x x++ or x--. Let the lowering // pass sort out what to do with it. if (kind.IsDynamic()) { return(kind | UnaryOperatorKind.Checked); } if (kind.IsIntegral()) { switch (kind.Operator()) { case UnaryOperatorKind.PrefixIncrement: case UnaryOperatorKind.PostfixIncrement: case UnaryOperatorKind.PrefixDecrement: case UnaryOperatorKind.PostfixDecrement: case UnaryOperatorKind.UnaryMinus: return(kind | UnaryOperatorKind.Checked); } } return(kind); } else { return(kind & ~UnaryOperatorKind.Checked); } }
internal LoweredDynamicOperation MakeDynamicUnaryOperator( UnaryOperatorKind operatorKind, BoundExpression loweredOperand, TypeSymbol resultType ) { Debug.Assert(operatorKind.IsDynamic()); _factory.Syntax = loweredOperand.Syntax; CSharpBinderFlags binderFlags = 0; if (operatorKind.IsChecked()) { binderFlags |= CSharpBinderFlags.CheckedContext; } var loweredArguments = ImmutableArray.Create(loweredOperand); MethodSymbol argumentInfoFactory = GetArgumentInfoFactory(); var binderConstruction = ((object)argumentInfoFactory != null) ? MakeBinderConstruction( WellKnownMember.Microsoft_CSharp_RuntimeBinder_Binder__UnaryOperation, new[] { // flags: _factory.Literal((int)binderFlags), // expression type: _factory.Literal((int)operatorKind.ToExpressionType()), // context: _factory.TypeofDynamicOperationContextType(), // argument infos: MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments) } ) : null; return(MakeDynamicOperation( binderConstruction, null, RefKind.None, loweredArguments, default(ImmutableArray <RefKind>), null, resultType )); }
private BoundExpression MakeUnaryOperator( BoundUnaryOperator?oldNode, UnaryOperatorKind kind, SyntaxNode syntax, MethodSymbol?method, BoundExpression loweredOperand, TypeSymbol type) { if (kind.IsDynamic()) { Debug.Assert((kind == UnaryOperatorKind.DynamicTrue || kind == UnaryOperatorKind.DynamicFalse) && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic()); Debug.Assert(method is null); // Logical operators on boxed Boolean constants: var constant = UnboxConstant(loweredOperand); if (constant == ConstantValue.True || constant == ConstantValue.False) { switch (kind) { case UnaryOperatorKind.DynamicTrue: return(_factory.Literal(constant.BooleanValue)); case UnaryOperatorKind.DynamicLogicalNegation: return(MakeConversionNode(_factory.Literal(!constant.BooleanValue), type, @checked: false)); } } return(_dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression()); } else if (kind.IsLifted()) { if (!_inExpressionLambda) { return(LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type)); } } else if (kind.IsUserDefined()) { Debug.Assert(method is { });
private BoundExpression MakeUnaryOperator( BoundUnaryOperator oldNode, UnaryOperatorKind kind, SyntaxNode syntax, MethodSymbol method, BoundExpression loweredOperand, TypeSymbol type) { if (kind.IsDynamic()) { Debug.Assert(kind == UnaryOperatorKind.DynamicTrue && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic()); Debug.Assert((object)method == null); // Logical operators on boxed Boolean constants: var constant = UnboxConstant(loweredOperand); if (constant == ConstantValue.True || constant == ConstantValue.False) { if (kind == UnaryOperatorKind.DynamicTrue) { return(_factory.Literal(constant.BooleanValue)); } else if (kind == UnaryOperatorKind.DynamicLogicalNegation) { return(MakeConversionNode(_factory.Literal(!constant.BooleanValue), type, @checked: false)); } } return(_dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression()); } else if (kind.IsLifted()) { if (!_inExpressionLambda) { return(LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type)); } } else if (kind.IsUserDefined()) { Debug.Assert((object)method != null); Debug.Assert(type == method.ReturnType); if (!_inExpressionLambda || kind == UnaryOperatorKind.UserDefinedTrue || kind == UnaryOperatorKind.UserDefinedFalse) { return(BoundCall.Synthesized(syntax, null, method, loweredOperand)); } } else if (kind.Operator() == UnaryOperatorKind.UnaryPlus) { // We do not call the operator even for decimal; we simply optimize it away entirely. return(loweredOperand); } if (kind == UnaryOperatorKind.EnumBitwiseComplement) { var underlyingType = loweredOperand.Type.GetEnumUnderlyingType(); var upconvertSpecialType = Binder.GetEnumPromotedType(underlyingType.SpecialType); var upconvertType = upconvertSpecialType == underlyingType.SpecialType ? underlyingType : _compilation.GetSpecialType(upconvertSpecialType); var newOperand = MakeConversionNode(loweredOperand, upconvertType, false); UnaryOperatorKind newKind = kind.Operator().WithType(upconvertSpecialType); var newNode = (oldNode != null) ? oldNode.Update( newKind, newOperand, oldNode.ConstantValueOpt, method, newOperand.ResultKind, upconvertType) : new BoundUnaryOperator( syntax, newKind, newOperand, null, method, LookupResultKind.Viable, upconvertType); return(MakeConversionNode(newNode.Syntax, newNode, Conversion.ExplicitEnumeration, type, @checked: false)); } if (kind == UnaryOperatorKind.DecimalUnaryMinus) { method = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_Decimal__op_UnaryNegation); if (!_inExpressionLambda) { return(BoundCall.Synthesized(syntax, null, method, loweredOperand)); } } return((oldNode != null) ? oldNode.Update(kind, loweredOperand, oldNode.ConstantValueOpt, method, oldNode.ResultKind, type) : new BoundUnaryOperator(syntax, kind, loweredOperand, null, method, LookupResultKind.Viable, type)); }
private BoundExpression MakeUnaryOperator( BoundUnaryOperator oldNode, UnaryOperatorKind kind, CSharpSyntaxNode syntax, MethodSymbol method, BoundExpression loweredOperand, TypeSymbol type) { if (kind.IsDynamic()) { Debug.Assert(kind == UnaryOperatorKind.DynamicTrue && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic()); Debug.Assert((object)method == null); // Logical operators on boxed Boolean constants: var constant = UnboxConstant(loweredOperand); if (constant == ConstantValue.True || constant == ConstantValue.False) { if (kind == UnaryOperatorKind.DynamicTrue) { return _factory.Literal(constant.BooleanValue); } else if (kind == UnaryOperatorKind.DynamicLogicalNegation) { return MakeConversionNode(_factory.Literal(!constant.BooleanValue), type, @checked: false); } } return _dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression(); } else if (kind.IsLifted()) { if (!_inExpressionLambda) { return LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type); } } else if (kind.IsUserDefined()) { Debug.Assert((object)method != null); Debug.Assert(type == method.ReturnType); if (!_inExpressionLambda || kind == UnaryOperatorKind.UserDefinedTrue || kind == UnaryOperatorKind.UserDefinedFalse) { return BoundCall.Synthesized(syntax, null, method, loweredOperand); } } else if (kind.Operator() == UnaryOperatorKind.UnaryPlus) { // We do not call the operator even for decimal; we simply optimize it away entirely. return loweredOperand; } if (kind == UnaryOperatorKind.EnumBitwiseComplement) { var underlyingType = loweredOperand.Type.GetEnumUnderlyingType(); var upconvertSpecialType = Binder.GetEnumPromotedType(underlyingType.SpecialType); var upconvertType = upconvertSpecialType == underlyingType.SpecialType ? underlyingType : _compilation.GetSpecialType(upconvertSpecialType); var newOperand = MakeConversionNode(loweredOperand, upconvertType, false); UnaryOperatorKind newKind = kind.Operator().WithType(upconvertSpecialType); var newNode = (oldNode != null) ? oldNode.Update( newKind, newOperand, oldNode.ConstantValueOpt, method, newOperand.ResultKind, upconvertType) : new BoundUnaryOperator( syntax, newKind, newOperand, null, method, LookupResultKind.Viable, upconvertType); return MakeConversionNode(newNode.Syntax, newNode, Conversion.ExplicitEnumeration, type, @checked: false); } if (kind == UnaryOperatorKind.DecimalUnaryMinus) { method = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_Decimal__op_UnaryNegation); if (!_inExpressionLambda) { return BoundCall.Synthesized(syntax, null, method, loweredOperand); } } return (oldNode != null) ? oldNode.Update(kind, loweredOperand, oldNode.ConstantValueOpt, method, oldNode.ResultKind, type) : new BoundUnaryOperator(syntax, kind, loweredOperand, null, method, LookupResultKind.Viable, type); }
internal LoweredDynamicOperation MakeDynamicUnaryOperator( UnaryOperatorKind operatorKind, BoundExpression loweredOperand, TypeSymbol resultType) { Debug.Assert(operatorKind.IsDynamic()); _factory.Syntax = loweredOperand.Syntax; CSharpBinderFlags binderFlags = 0; if (operatorKind.IsChecked()) { binderFlags |= CSharpBinderFlags.CheckedContext; } var loweredArguments = ImmutableArray.Create(loweredOperand); MethodSymbol argumentInfoFactory = GetArgumentInfoFactory(); var binderConstruction = ((object)argumentInfoFactory != null) ? MakeBinderConstruction(WellKnownMember.Microsoft_CSharp_RuntimeBinder_Binder__UnaryOperation, new[] { // flags: _factory.Literal((int)binderFlags), // expression type: _factory.Literal((int)operatorKind.ToExpressionType()), // context: _factory.TypeofDynamicOperationContextType(), // argument infos: MakeCallSiteArgumentInfos(argumentInfoFactory, loweredArguments) }) : null; return MakeDynamicOperation(binderConstruction, null, RefKind.None, loweredArguments, ImmutableArray<RefKind>.Empty, null, resultType); }
private BoundExpression MakeUnaryOperator( BoundUnaryOperator oldNode, UnaryOperatorKind kind, CSharpSyntaxNode syntax, MethodSymbol method, BoundExpression loweredOperand, TypeSymbol type) { if (kind.IsDynamic()) { Debug.Assert(kind == UnaryOperatorKind.DynamicTrue && type.SpecialType == SpecialType.System_Boolean || type.IsDynamic()); Debug.Assert((object)method == null); // Logical operators on boxed Boolean constants: var constant = UnboxConstant(loweredOperand); if (constant == ConstantValue.True || constant == ConstantValue.False) { if (kind == UnaryOperatorKind.DynamicTrue) { return(_factory.Literal(constant.BooleanValue)); } else if (kind == UnaryOperatorKind.DynamicLogicalNegation) { return(MakeConversionNode(_factory.Literal(!constant.BooleanValue), type, @checked: false)); } } return(_dynamicFactory.MakeDynamicUnaryOperator(kind, loweredOperand, type).ToExpression()); } else if (kind.IsLifted()) { if (!_inExpressionLambda) { return(LowerLiftedUnaryOperator(kind, syntax, method, loweredOperand, type)); } } else if (kind.IsUserDefined()) { Debug.Assert((object)method != null); Debug.Assert(type == method.ReturnType); if (!_inExpressionLambda || kind == UnaryOperatorKind.UserDefinedTrue || kind == UnaryOperatorKind.UserDefinedFalse) { // @t-mawind // As usual, concept accesses need to be rewritten down to their // default() form. // Is this correct? It's mostly a copy over from the binary case, // but the unary case is different enough to make me nervous. if (method is SynthesizedWitnessMethodSymbol) { return(BoundCall.Synthesized(syntax, SynthesizeWitnessInvocationReceiver(syntax, ((SynthesizedWitnessMethodSymbol)method).Parent), method, loweredOperand)); } return(BoundCall.Synthesized(syntax, null, method, loweredOperand)); } } else if (kind.Operator() == UnaryOperatorKind.UnaryPlus) { // We do not call the operator even for decimal; we simply optimize it away entirely. return(loweredOperand); } if (kind == UnaryOperatorKind.EnumBitwiseComplement) { var underlyingType = loweredOperand.Type.GetEnumUnderlyingType(); var upconvertSpecialType = Binder.GetEnumPromotedType(underlyingType.SpecialType); var upconvertType = upconvertSpecialType == underlyingType.SpecialType ? underlyingType : _compilation.GetSpecialType(upconvertSpecialType); var newOperand = MakeConversionNode(loweredOperand, upconvertType, false); UnaryOperatorKind newKind = kind.Operator().WithType(upconvertSpecialType); var newNode = (oldNode != null) ? oldNode.Update( newKind, newOperand, oldNode.ConstantValueOpt, method, newOperand.ResultKind, upconvertType) : new BoundUnaryOperator( syntax, newKind, newOperand, null, method, LookupResultKind.Viable, upconvertType); return(MakeConversionNode(newNode.Syntax, newNode, Conversion.ExplicitEnumeration, type, @checked: false)); } if (kind == UnaryOperatorKind.DecimalUnaryMinus) { method = (MethodSymbol)_compilation.Assembly.GetSpecialTypeMember(SpecialMember.System_Decimal__op_UnaryNegation); if (!_inExpressionLambda) { return(BoundCall.Synthesized(syntax, null, method, loweredOperand)); } } return((oldNode != null) ? oldNode.Update(kind, loweredOperand, oldNode.ConstantValueOpt, method, oldNode.ResultKind, type) : new BoundUnaryOperator(syntax, kind, loweredOperand, null, method, LookupResultKind.Viable, type)); }