private static bool DoSignaturesMatch( PEModuleSymbol moduleSymbol, TypeSymbol eventType, PEMethodSymbol addMethod, PEMethodSymbol removeMethod) { return ((eventType.IsDelegateType() || eventType.IsErrorType()) && DoesSignatureMatch(moduleSymbol, eventType, addMethod) && DoesSignatureMatch(moduleSymbol, eventType, removeMethod) && DoModifiersMatch(addMethod, removeMethod)); }
// If the type is a delegate type, it returns it. If the type is an // expression tree type associated with a delegate type, it returns // the delegate type. Otherwise, null. public static NamedTypeSymbol GetDelegateType(this TypeSymbol type) { if ((object)type == null) { return(null); } if (type.IsExpressionTree()) { type = ((NamedTypeSymbol)type).TypeArgumentsNoUseSiteDiagnostics[0]; } return(type.IsDelegateType() ? (NamedTypeSymbol)type : null); }
public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); if (type.IsDelegateType()) { return(IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type)); } else if (type.IsExpressionTree()) { return(IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type)); } return(LambdaConversionResult.BadTargetType); }
public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { // Must be a bona fide delegate type, not an expression tree type. if (!destination.IsDelegateType()) { return Conversion.NoConversion; } var methodSymbol = GetDelegateInvokeMethodIfAvailable(destination); if ((object)methodSymbol == null) { return Conversion.NoConversion; } var resolution = ResolveDelegateMethodGroup(_binder, source, methodSymbol, ref useSiteDiagnostics); var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ? Conversion.NoConversion : ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, (NamedTypeSymbol)destination); resolution.Free(); return conversion; }
public override Conversion GetMethodGroupDelegateConversion(BoundMethodGroup source, TypeSymbol destination, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo) { // Must be a bona fide delegate type, not an expression tree type. if (!destination.IsDelegateType()) { return(Conversion.NoConversion); } var(methodSymbol, isFunctionPointer, callingConventionInfo) = GetDelegateInvokeOrFunctionPointerMethodIfAvailable(destination); if ((object)methodSymbol == null) { return(Conversion.NoConversion); } var resolution = ResolveDelegateOrFunctionPointerMethodGroup(_binder, source, methodSymbol, isFunctionPointer, callingConventionInfo, ref useSiteInfo); var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ? Conversion.NoConversion : ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, ((NamedTypeSymbol)destination).DelegateInvokeMethod.ParameterCount); resolution.Free(); return(conversion); }
public override Conversion GetMethodGroupConversion(BoundMethodGroup source, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { // Must be a bona fide delegate type, not an expression tree type. if (!destination.IsDelegateType()) { return(Conversion.NoConversion); } var methodSymbol = GetDelegateInvokeMethodIfAvailable(destination); if ((object)methodSymbol == null) { return(Conversion.NoConversion); } var resolution = ResolveDelegateMethodGroup(_binder, source, methodSymbol, ref useSiteDiagnostics); var conversion = (resolution.IsEmpty || resolution.HasAnyErrors) ? Conversion.NoConversion : ToConversion(resolution.OverloadResolutionResult, resolution.MethodGroup, (NamedTypeSymbol)destination); resolution.Free(); return(conversion); }
private static bool DoSignaturesMatch( PEModuleSymbol moduleSymbol, TypeSymbol eventType, PEMethodSymbol addMethod, PEMethodSymbol removeMethod) { return (eventType.IsDelegateType() || eventType.IsErrorType()) && DoesSignatureMatch(moduleSymbol, eventType, addMethod) && DoesSignatureMatch(moduleSymbol, eventType, removeMethod) && DoModifiersMatch(addMethod, removeMethod); }
public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(UnboundLambda anonymousFunction, TypeSymbol type) { Debug.Assert((object)anonymousFunction != null); Debug.Assert((object)type != null); if (type.IsDelegateType()) { return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type); } else if (type.IsExpressionTree()) { return IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type); } return LambdaConversionResult.BadTargetType; }
// Although III.1.8.1.3 seems to imply that verifier understands variance casts. // It appears that verifier/JIT gets easily confused. // So to not rely on whether that should work or not we will flag potentially // "complicated" casts and make them static casts to ensure we are all on // the same page with what type should be tracked. private static bool IsVarianceCast(TypeSymbol to, TypeSymbol from) { if (to == from) { return false; } if ((object)from == null) { // from unknown type - this could be a variance conversion. return true; } // while technically variance casts, array conversions do not seem to be a problem // unless the element types are converted via variance. if (to.IsArray()) { return IsVarianceCast(((ArrayTypeSymbol)to).ElementType, ((ArrayTypeSymbol)from).ElementType); } return (to.IsDelegateType() && to != from) || (to.IsInterfaceType() && from.IsInterfaceType() && !from.InterfacesAndTheirBaseInterfacesNoUseSiteDiagnostics.Contains((NamedTypeSymbol)to)); }
/// <summary> /// Emits conversion to an object of given type. /// </summary> /// <param name="from">Type of value on top of the evaluation stack.</param> /// <param name="fromHint">Hint in case of multitype value.</param> /// <param name="to">Target type.</param> private void EmitConvertToClass(TypeSymbol from, TypeRefMask fromHint, TypeSymbol to) { Contract.ThrowIfNull(from); Contract.ThrowIfNull(to); Debug.Assert(to.IsReferenceType); Debug.Assert(to != CoreTypes.PhpAlias); Debug.Assert(!to.IsErrorType(), "Trying to convert to an ErrorType"); // -> IPhpCallable if (to == CoreTypes.IPhpCallable) { EmitConvertToIPhpCallable(from, fromHint); return; } // -> System.Array if (to.IsArray()) { var arrt = (ArrayTypeSymbol)to; if (arrt.IsSZArray) { // byte[] if (arrt.ElementType.SpecialType == SpecialType.System_Byte) { // Template: (PhpString).ToBytes(Context) EmitConvertToPhpString(from, fromHint); // PhpString EmitPhpStringAddr(); this.EmitLoadContext(); // Context EmitCall(ILOpCode.Call, CoreMethods.PhpString.ToBytes_Context) .Expect(to); // ToBytes() return; } throw this.NotImplementedException($"Conversion from {from.Name} to {arrt.ElementType.Name}[] is not implemented."); } throw this.NotImplementedException($"Conversion from {from.Name} to array {to.Name} is not implemented."); } // dereference if (from == CoreTypes.PhpAlias) { // <alias>.Value : PhpValue from = Emit_PhpAlias_GetValue(); } if (from.IsReferenceType && from.IsOfType(to)) { return; } // -> Delegate if (to.IsDelegateType()) { // PhpCallableToDelegate<to>.Get( IPhpCallable, Context ) : to EmitConvertToIPhpCallable(from, fromHint); EmitLoadContext(); var get_callable_ctx = (MethodSymbol)CoreTypes.PhpCallableToDelegate.Symbol.Construct(to).GetMembers("Get").SingleOrDefault(); EmitCall(ILOpCode.Callvirt, get_callable_ctx).Expect(to); return; } Debug.Assert(to != CoreTypes.PhpArray && to != CoreTypes.PhpString && to != CoreTypes.PhpAlias); switch (from.SpecialType) { case SpecialType.System_Void: case SpecialType.System_Int32: case SpecialType.System_Int64: case SpecialType.System_Boolean: case SpecialType.System_Double: case SpecialType.System_String: // Template: null EmitPop(from); _il.EmitNullConstant(); return; default: Debug.Assert(from != CoreTypes.PhpAlias); if (from.IsValueType) { if (from == CoreTypes.PhpValue) { if (IsClassOnly(fromHint)) { // <STACK>.Object EmitPhpValueAddr(); from = EmitCall(ILOpCode.Call, CoreMethods.PhpValue.Object.Getter) .Expect(SpecialType.System_Object); } else { // Convert.AsObject( <STACK> ) from = EmitCall(ILOpCode.Call, CoreMethods.Operators.AsObject_PhpValue) .Expect(SpecialType.System_Object); } } else { // null EmitPop(from); _il.EmitNullConstant(); return; } } // break; } // Template: (T)object EmitCastClass(from, to); }
protected void GenerateImplicitConversionError(DiagnosticBag diagnostics, CSharpSyntaxNode syntax, Conversion conversion, BoundExpression expression, TypeSymbol targetType) { Debug.Assert(expression != null); Debug.Assert((object)targetType != null); if (targetType.TypeKind == TypeKind.Error) { return; } if (expression.Kind == BoundKind.BadExpression) { return; } if (expression.Kind == BoundKind.UnboundLambda) { GenerateAnonymousFunctionConversionError(diagnostics, syntax, (UnboundLambda)expression, targetType); return; } var sourceType = expression.Type; if ((object)sourceType != null) { GenerateImplicitConversionError(diagnostics, this.Compilation, syntax, conversion, sourceType, targetType, expression.ConstantValue); return; } if (expression.IsLiteralNull()) { if (targetType.TypeKind == TypeKind.TypeParameter) { Error(diagnostics, ErrorCode.ERR_TypeVarCantBeNull, syntax, targetType); return; } if (targetType.IsValueType) { Error(diagnostics, ErrorCode.ERR_ValueCantBeNull, syntax, targetType); return; } } if (expression.Kind == BoundKind.MethodGroup) { var methodGroup = (BoundMethodGroup)expression; if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, methodGroup, targetType, diagnostics)) { var nodeForSquiggle = syntax; while (nodeForSquiggle.Kind() == SyntaxKind.ParenthesizedExpression) { nodeForSquiggle = ((ParenthesizedExpressionSyntax)nodeForSquiggle).Expression; } if (nodeForSquiggle.Kind() == SyntaxKind.SimpleMemberAccessExpression || nodeForSquiggle.Kind() == SyntaxKind.PointerMemberAccessExpression) { nodeForSquiggle = ((MemberAccessExpressionSyntax)nodeForSquiggle).Name; } var location = nodeForSquiggle.Location; if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, targetType, location)) { return; } Error(diagnostics, targetType.IsDelegateType() ? ErrorCode.ERR_MethDelegateMismatch : ErrorCode.ERR_MethGrpToNonDel, location, methodGroup.Name, targetType); } return; } Debug.Assert(expression.HasAnyErrors && expression.Kind != BoundKind.UnboundLambda, "Missing a case in implicit conversion error reporting"); }
protected void GenerateImplicitConversionError( DiagnosticBag diagnostics, CSharpSyntaxNode syntax, Conversion conversion, BoundExpression operand, TypeSymbol targetType) { Debug.Assert(operand != null); Debug.Assert((object)targetType != null); if (targetType.TypeKind == TypeKind.Error) { return; } if (operand.Kind == BoundKind.BadExpression) { return; } if (operand.Kind == BoundKind.UnboundLambda) { GenerateAnonymousFunctionConversionError(diagnostics, syntax, (UnboundLambda)operand, targetType); return; } if (operand.Kind == BoundKind.TupleLiteral) { var tuple = (BoundTupleLiteral)operand; var targetElementTypes = default(ImmutableArray<TypeSymbol>); // If target is a tuple or compatible type with the same number of elements, // report errors for tuple arguments that failed to convert, which would be more useful. if (targetType.TryGetElementTypesIfTupleOrCompatible(out targetElementTypes) && targetElementTypes.Length == tuple.Arguments.Length) { GenerateImplicitConversionErrorsForTupleLiteralArguments(diagnostics, tuple.Arguments, targetElementTypes); return; } // target is not compatible with source and source does not have a type if ((object)tuple.Type == null) { Error(diagnostics, ErrorCode.ERR_ConversionNotTupleCompatible, syntax, tuple.Arguments.Length, targetType); return; } // Otherwise it is just a regular conversion failure from T1 to T2. } var sourceType = operand.Type; if ((object)sourceType != null) { GenerateImplicitConversionError(diagnostics, this.Compilation, syntax, conversion, sourceType, targetType, operand.ConstantValue); return; } if (operand.IsLiteralNull()) { if (targetType.TypeKind == TypeKind.TypeParameter) { Error(diagnostics, ErrorCode.ERR_TypeVarCantBeNull, syntax, targetType); return; } if (targetType.IsValueType) { Error(diagnostics, ErrorCode.ERR_ValueCantBeNull, syntax, targetType); return; } } if (operand.Kind == BoundKind.MethodGroup) { var methodGroup = (BoundMethodGroup)operand; if (!Conversions.ReportDelegateMethodGroupDiagnostics(this, methodGroup, targetType, diagnostics)) { var nodeForSquiggle = syntax; while (nodeForSquiggle.Kind() == SyntaxKind.ParenthesizedExpression) { nodeForSquiggle = ((ParenthesizedExpressionSyntax)nodeForSquiggle).Expression; } if (nodeForSquiggle.Kind() == SyntaxKind.SimpleMemberAccessExpression || nodeForSquiggle.Kind() == SyntaxKind.PointerMemberAccessExpression) { nodeForSquiggle = ((MemberAccessExpressionSyntax)nodeForSquiggle).Name; } var location = nodeForSquiggle.Location; if (ReportDelegateInvokeUseSiteDiagnostic(diagnostics, targetType, location)) { return; } Error(diagnostics, targetType.IsDelegateType() ? ErrorCode.ERR_MethDelegateMismatch : ErrorCode.ERR_MethGrpToNonDel, location, methodGroup.Name, targetType); } return; } Debug.Assert(operand.HasAnyErrors && operand.Kind != BoundKind.UnboundLambda, "Missing a case in implicit conversion error reporting"); }
public static MethodSymbol DelegateInvokeMethod(this TypeSymbol type) { Debug.Assert((object)type != null); Debug.Assert(type.IsDelegateType() || type.IsExpressionTree()); return(type.GetDelegateType().DelegateInvokeMethod); }
private void TestBinaryIntrinsicSymbol( BinaryOperatorKind op, TypeSymbol leftType, TypeSymbol rightType, CSharpCompilation compilation, SemanticModel semanticModel, ExpressionSyntax node1, ExpressionSyntax node2, ExpressionSyntax node3, ExpressionSyntax node4, ExpressionSyntax node5, ExpressionSyntax node6, ExpressionSyntax node7, ExpressionSyntax node8 ) { SymbolInfo info1 = semanticModel.GetSymbolInfo(node1); HashSet<DiagnosticInfo> useSiteDiagnostics = null; if (info1.Symbol == null) { if (info1.CandidateSymbols.Length == 0) { if (leftType.IsDynamic() || rightType.IsDynamic()) { Assert.True(CandidateReason.LateBound == info1.CandidateReason || CandidateReason.None == info1.CandidateReason); } else { Assert.Equal(CandidateReason.None, info1.CandidateReason); } } else { Assert.Equal(CandidateReason.OverloadResolutionFailure, info1.CandidateReason); foreach (MethodSymbol s in info1.CandidateSymbols) { Assert.Equal(MethodKind.UserDefinedOperator, s.MethodKind); } } } else { Assert.Equal(leftType.IsDynamic() || rightType.IsDynamic() ? CandidateReason.LateBound : CandidateReason.None, info1.CandidateReason); Assert.Equal(0, info1.CandidateSymbols.Length); } var symbol1 = (MethodSymbol)info1.Symbol; var symbol2 = semanticModel.GetSymbolInfo(node2).Symbol; var symbol3 = semanticModel.GetSymbolInfo(node3).Symbol; var symbol4 = semanticModel.GetSymbolInfo(node4).Symbol; var symbol5 = (MethodSymbol)semanticModel.GetSymbolInfo(node5).Symbol; var symbol6 = semanticModel.GetSymbolInfo(node6).Symbol; var symbol7 = semanticModel.GetSymbolInfo(node7).Symbol; var symbol8 = semanticModel.GetSymbolInfo(node8).Symbol; Assert.Equal(symbol1, symbol5); Assert.Equal(symbol2, symbol6); Assert.Equal(symbol3, symbol7); Assert.Equal(symbol4, symbol8); if ((object)symbol1 != null && symbol1.IsImplicitlyDeclared) { Assert.NotSame(symbol1, symbol5); Assert.Equal(symbol1.GetHashCode(), symbol5.GetHashCode()); for (int i = 0; i < 2; i++) { Assert.Equal(symbol1.Parameters[i], symbol5.Parameters[i]); Assert.Equal(symbol1.Parameters[i].GetHashCode(), symbol5.Parameters[i].GetHashCode()); } Assert.NotEqual(symbol1.Parameters[0], symbol5.Parameters[1]); } switch (op) { case BinaryOperatorKind.LogicalAnd: case BinaryOperatorKind.LogicalOr: Assert.Null(symbol1); Assert.Null(symbol2); Assert.Null(symbol3); Assert.Null(symbol4); return; } BinaryOperatorKind result = OverloadResolution.BinopEasyOut.OpKind(op, leftType, rightType); BinaryOperatorSignature signature; bool isDynamic = (leftType.IsDynamic() || rightType.IsDynamic()); if (result == BinaryOperatorKind.Error) { if (leftType.IsDynamic() && !rightType.IsPointerType() && !rightType.IsRestrictedType()) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Dynamic, leftType, rightType, leftType); } else if (rightType.IsDynamic() && !leftType.IsPointerType() && !leftType.IsRestrictedType()) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Dynamic, leftType, rightType, rightType); } else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual) && leftType.IsReferenceType && rightType.IsReferenceType && (leftType == rightType || compilation.Conversions.ClassifyConversion(leftType, rightType, ref useSiteDiagnostics).IsReference)) { if (leftType.IsDelegateType() && rightType.IsDelegateType()) { Assert.Equal(leftType, rightType); signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate, leftType, // TODO: this feels like a spec violation leftType, // TODO: this feels like a spec violation compilation.GetSpecialType(SpecialType.System_Boolean)); } else if (leftType.SpecialType == SpecialType.System_Delegate && rightType.SpecialType == SpecialType.System_Delegate) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate, compilation.GetSpecialType(SpecialType.System_Delegate), compilation.GetSpecialType(SpecialType.System_Delegate), compilation.GetSpecialType(SpecialType.System_Boolean)); } else { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Object, compilation.ObjectType, compilation.ObjectType, compilation.GetSpecialType(SpecialType.System_Boolean)); } } else if (op == BinaryOperatorKind.Addition && ((leftType.IsStringType() && !rightType.IsPointerType()) || (!leftType.IsPointerType() && rightType.IsStringType()))) { Assert.False(leftType.IsStringType() && rightType.IsStringType()); if (leftType.IsStringType()) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, leftType, compilation.ObjectType, leftType); } else { Assert.True(rightType.IsStringType()); signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, compilation.ObjectType, rightType, rightType); } } else if (op == BinaryOperatorKind.Addition && (((leftType.IsIntegralType() || leftType.IsCharType()) && rightType.IsPointerType()) || (leftType.IsPointerType() && (rightType.IsIntegralType() || rightType.IsCharType())))) { if (leftType.IsPointerType()) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, leftType, symbol1.Parameters[1].Type, leftType); Assert.True(symbol1.Parameters[1].Type.IsIntegralType()); } else { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, symbol1.Parameters[0].Type, rightType, rightType); Assert.True(symbol1.Parameters[0].Type.IsIntegralType()); } } else if (op == BinaryOperatorKind.Subtraction && (leftType.IsPointerType() && (rightType.IsIntegralType() || rightType.IsCharType()))) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.String, leftType, symbol1.Parameters[1].Type, leftType); Assert.True(symbol1.Parameters[1].Type.IsIntegralType()); } else if (op == BinaryOperatorKind.Subtraction && leftType.IsPointerType() && leftType == rightType) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, leftType, rightType, compilation.GetSpecialType(SpecialType.System_Int64)); } else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) && leftType.IsEnumType() && (rightType.IsIntegralType() || rightType.IsCharType()) && (result = OverloadResolution.BinopEasyOut.OpKind(op, leftType.EnumUnderlyingType(), rightType)) != BinaryOperatorKind.Error && (signature = compilation.builtInOperators.GetSignature(result)).RightType == leftType.EnumUnderlyingType()) { signature = new BinaryOperatorSignature(signature.Kind | BinaryOperatorKind.EnumAndUnderlying, leftType, signature.RightType, leftType); } else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) && rightType.IsEnumType() && (leftType.IsIntegralType() || leftType.IsCharType()) && (result = OverloadResolution.BinopEasyOut.OpKind(op, leftType, rightType.EnumUnderlyingType())) != BinaryOperatorKind.Error && (signature = compilation.builtInOperators.GetSignature(result)).LeftType == rightType.EnumUnderlyingType()) { signature = new BinaryOperatorSignature(signature.Kind | BinaryOperatorKind.EnumAndUnderlying, signature.LeftType, rightType, rightType); } else if (op == BinaryOperatorKind.Subtraction && leftType.IsEnumType() && leftType == rightType) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, leftType.EnumUnderlyingType()); } else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual || op == BinaryOperatorKind.LessThan || op == BinaryOperatorKind.LessThanOrEqual || op == BinaryOperatorKind.GreaterThan || op == BinaryOperatorKind.GreaterThanOrEqual) && leftType.IsEnumType() && leftType == rightType) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, compilation.GetSpecialType(SpecialType.System_Boolean)); } else if ((op == BinaryOperatorKind.Xor || op == BinaryOperatorKind.And || op == BinaryOperatorKind.Or) && leftType.IsEnumType() && leftType == rightType) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Enum, leftType, rightType, leftType); } else if ((op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) && leftType.IsDelegateType() && leftType == rightType) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Delegate, leftType, leftType, leftType); } else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual || op == BinaryOperatorKind.LessThan || op == BinaryOperatorKind.LessThanOrEqual || op == BinaryOperatorKind.GreaterThan || op == BinaryOperatorKind.GreaterThanOrEqual) && leftType.IsPointerType() && rightType.IsPointerType()) { signature = new BinaryOperatorSignature(op | BinaryOperatorKind.Pointer, compilation.CreatePointerTypeSymbol(compilation.GetSpecialType(SpecialType.System_Void)), compilation.CreatePointerTypeSymbol(compilation.GetSpecialType(SpecialType.System_Void)), compilation.GetSpecialType(SpecialType.System_Boolean)); } else { if ((object)symbol1 != null) { Assert.False(symbol1.IsImplicitlyDeclared); Assert.Equal(MethodKind.UserDefinedOperator, symbol1.MethodKind); if (leftType.IsValueType && !leftType.IsPointerType()) { if (rightType.IsValueType && !rightType.IsPointerType()) { Assert.Same(symbol1, symbol2); Assert.Same(symbol1, symbol3); Assert.Same(symbol1, symbol4); return; } else { Assert.Null(symbol2); Assert.Same(symbol1, symbol3); Assert.Null(symbol4); return; } } else if (rightType.IsValueType && !rightType.IsPointerType()) { Assert.Null(symbol2); Assert.Null(symbol3); Assert.Same(symbol1, symbol4); return; } else { Assert.Null(symbol2); Assert.Null(symbol3); Assert.Null(symbol4); return; } } Assert.Null(symbol1); Assert.Null(symbol2); if (!rightType.IsDynamic()) { Assert.Null(symbol3); } if (!leftType.IsDynamic()) { Assert.Null(symbol4); } return; } } else if ((op == BinaryOperatorKind.Equal || op == BinaryOperatorKind.NotEqual) && leftType != rightType && (!leftType.IsValueType || !rightType.IsValueType || leftType.SpecialType == SpecialType.System_Boolean || rightType.SpecialType == SpecialType.System_Boolean || (leftType.SpecialType == SpecialType.System_Decimal && (rightType.SpecialType == SpecialType.System_Double || rightType.SpecialType == SpecialType.System_Single)) || (rightType.SpecialType == SpecialType.System_Decimal && (leftType.SpecialType == SpecialType.System_Double || leftType.SpecialType == SpecialType.System_Single))) && (!leftType.IsReferenceType || !rightType.IsReferenceType || !compilation.Conversions.ClassifyConversion(leftType, rightType, ref useSiteDiagnostics).IsReference)) { Assert.Null(symbol1); Assert.Null(symbol2); Assert.Null(symbol3); Assert.Null(symbol4); return; } else { signature = compilation.builtInOperators.GetSignature(result); } Assert.NotNull(symbol1); string containerName = signature.LeftType.ToTestDisplayString(); string leftName = containerName; string rightName = signature.RightType.ToTestDisplayString(); string returnName = signature.ReturnType.ToTestDisplayString(); if (isDynamic) { containerName = compilation.DynamicType.ToTestDisplayString(); } else if (op == BinaryOperatorKind.Addition || op == BinaryOperatorKind.Subtraction) { if (signature.LeftType.IsObjectType() && signature.RightType.IsStringType()) { containerName = rightName; } else if ((leftType.IsEnumType() || leftType.IsPointerType()) && (rightType.IsIntegralType() || rightType.IsCharType())) { containerName = leftType.ToTestDisplayString(); leftName = containerName; returnName = containerName; } else if ((rightType.IsEnumType() || rightType.IsPointerType()) && (leftType.IsIntegralType() || leftType.IsCharType())) { containerName = rightType.ToTestDisplayString(); rightName = containerName; returnName = containerName; } } Assert.Equal(isDynamic, signature.ReturnType.IsDynamic()); string expectedSymbol = String.Format("{4} {0}.{2}({1} left, {3} right)", containerName, leftName, OperatorFacts.BinaryOperatorNameFromOperatorKind(op), rightName, returnName); string actualSymbol = symbol1.ToTestDisplayString(); Assert.Equal(expectedSymbol, actualSymbol); Assert.Equal(MethodKind.BuiltinOperator, symbol1.MethodKind); Assert.True(symbol1.IsImplicitlyDeclared); bool isChecked; switch (op) { case BinaryOperatorKind.Multiplication: case BinaryOperatorKind.Addition: case BinaryOperatorKind.Subtraction: case BinaryOperatorKind.Division: isChecked = isDynamic || symbol1.ContainingSymbol.Kind == SymbolKind.PointerType || symbol1.ContainingType.EnumUnderlyingType().SpecialType.IsIntegralType(); break; default: isChecked = isDynamic; break; } Assert.Equal(isChecked, symbol1.IsCheckedBuiltin); Assert.False(symbol1.IsGenericMethod); Assert.False(symbol1.IsExtensionMethod); Assert.False(symbol1.IsExtern); Assert.False(symbol1.CanBeReferencedByName); Assert.Null(symbol1.DeclaringCompilation); Assert.Equal(symbol1.Name, symbol1.MetadataName); Assert.True(symbol1.ContainingSymbol == symbol1.Parameters[0].Type || symbol1.ContainingSymbol == symbol1.Parameters[1].Type); int match = 0; if (symbol1.ContainingSymbol == symbol1.ReturnType) { match++; } if (symbol1.ContainingSymbol == symbol1.Parameters[0].Type) { match++; } if (symbol1.ContainingSymbol == symbol1.Parameters[1].Type) { match++; } Assert.True(match >= 2); Assert.Equal(0, symbol1.Locations.Length); Assert.Null(symbol1.GetDocumentationCommentId()); Assert.Equal("", symbol1.GetDocumentationCommentXml()); Assert.True(symbol1.HasSpecialName); Assert.True(symbol1.IsStatic); Assert.Equal(Accessibility.Public, symbol1.DeclaredAccessibility); Assert.False(symbol1.HidesBaseMethodsByName); Assert.False(symbol1.IsOverride); Assert.False(symbol1.IsVirtual); Assert.False(symbol1.IsAbstract); Assert.False(symbol1.IsSealed); Assert.Equal(2, symbol1.ParameterCount); Assert.Equal(0, symbol1.Parameters[0].Ordinal); Assert.Equal(1, symbol1.Parameters[1].Ordinal); var otherSymbol = (MethodSymbol)semanticModel.GetSymbolInfo(node1).Symbol; Assert.Equal(symbol1, otherSymbol); if (leftType.IsValueType && !leftType.IsPointerType()) { if (rightType.IsValueType && !rightType.IsPointerType()) { Assert.Equal(symbol1, symbol2); Assert.Equal(symbol1, symbol3); Assert.Equal(symbol1, symbol4); return; } else { Assert.Null(symbol2); if (rightType.IsDynamic()) { Assert.NotEqual(symbol1, symbol3); } else { Assert.Equal(rightType.IsPointerType() ? null : symbol1, symbol3); } Assert.Null(symbol4); return; } } else if (rightType.IsValueType && !rightType.IsPointerType()) { Assert.Null(symbol2); Assert.Null(symbol3); if (leftType.IsDynamic()) { Assert.NotEqual(symbol1, symbol4); } else { Assert.Equal(leftType.IsPointerType() ? null : symbol1, symbol4); } return; } Assert.Null(symbol2); if (rightType.IsDynamic()) { Assert.NotEqual(symbol1, symbol3); } else { Assert.Null(symbol3); } if (leftType.IsDynamic()) { Assert.NotEqual(symbol1, symbol4); } else { Assert.Null(symbol4); } }
void XsCheckConversionForAssignment(TypeSymbol targetType, BoundExpression expression, DiagnosticBag diagnostics, bool isDefaultParameter = false, bool isRefAssignment = false) { if (expression.Kind == BoundKind.UnboundLambda) { if (targetType.IsDelegateType()) { if (expression.Syntax.XIsCodeBlock && !Compilation.Options.MacroScript) { Error(diagnostics, ErrorCode.ERR_LamdaWithCodeblockSyntax, expression.Syntax, targetType); } } } if (Compilation.Options.HasOption(CompilerOption.SignedUnsignedConversion, expression.Syntax)) { return; } var rhsType = expression.Type; if (targetType != rhsType && targetType.SpecialType.IsIntegralType() && rhsType.SpecialType.IsIntegralType() ) { bool ok = false; if (expression.ConstantValue != null) { if (rhsType.SpecialType.IsSignedIntegralType()) { var value = expression.ConstantValue.Int64Value; switch (targetType.SpecialType) { case SpecialType.System_SByte: ok = value >= sbyte.MinValue && value <= sbyte.MaxValue; break; case SpecialType.System_Int16: ok = value >= short.MinValue && value <= short.MaxValue; break; case SpecialType.System_Int32: ok = value >= int.MinValue && value <= int.MaxValue; break; case SpecialType.System_Int64: ok = true; break; case SpecialType.System_Byte: ok = value >= 0 && value <= byte.MaxValue; break; case SpecialType.System_UInt16: ok = value >= 0 && value <= ushort.MaxValue; break; case SpecialType.System_UInt32: ok = value >= 0 && value <= uint.MaxValue; break; case SpecialType.System_UInt64: ok = value >= 0; break; default: ok = false; break; } if (ok) { return; } } else { var value = expression.ConstantValue.UInt64Value; switch (targetType.SpecialType) { case SpecialType.System_SByte: ok = value <= (ulong)sbyte.MaxValue; break; case SpecialType.System_Int16: ok = value <= (ulong)short.MaxValue; break; case SpecialType.System_Int32: ok = value <= int.MaxValue; break; case SpecialType.System_Byte: ok = value <= byte.MaxValue; break; case SpecialType.System_UInt16: ok = value <= ushort.MaxValue; break; case SpecialType.System_UInt32: ok = value <= uint.MaxValue; break; case SpecialType.System_UInt64: ok = true; break; case SpecialType.System_Int64: ok = value < (ulong)long.MaxValue; break; default: ok = false; break; } } } if (!ok) { var sourceType = expression.Type; var sourceSize = sourceType.SpecialType.SizeInBytes(); var targetSize = targetType.SpecialType.SizeInBytes(); // Find sources that do not fit in the target if (sourceSize > targetSize) { // Narrowing conversion from '{0}' to '{1}' may lead to loss of data or overflow errors Error(diagnostics, ErrorCode.WRN_ConversionMayLeadToLossOfData, expression.Syntax, expression.Type, targetType); } else if (sourceSize == targetSize && expression.Type != targetType) { //Signed/unsigned conversions from '{0}' to '{1}' may lead to loss of data or overflow errors Error(diagnostics, ErrorCode.WRN_SignedUnSignedConversion, expression.Syntax, expression.Type, targetType); } // lhs.Size < rhs.Size, only a problem when lhs is Signed and rhs is Unsiged else if (sourceSize < targetSize && sourceType.SpecialType.IsSignedIntegralType() && !targetType.SpecialType.IsSignedIntegralType()) { // Signed / unsigned conversions from '{0}' to '{1}' may lead to loss of data or overflow errors Error(diagnostics, ErrorCode.WRN_SignedUnSignedConversion, expression.Syntax, expression.Type, targetType); } } } }
private BoundExpression BindCodeblock(SyntaxNode syntax, UnboundLambda unboundLambda, Conversion conversion, bool isCast, TypeSymbol destination, DiagnosticBag diagnostics) { if (!Compilation.Options.HasRuntime) { return(null); } var isCodeblock = syntax.XIsCodeBlock; if (!isCodeblock) { isCodeblock = !destination.IsDelegateType() && !destination.IsExpressionTree(); } if (!isCodeblock) { return(null); } Conversion conv = Conversion.ImplicitReference; if (destination != Compilation.CodeBlockType() && !destination.IsObjectType()) { HashSet <DiagnosticInfo> useSiteDiagnostics = null; conv = Conversions.ClassifyConversionFromType(Compilation.CodeBlockType(), destination, ref useSiteDiagnostics); diagnostics.Add(syntax, useSiteDiagnostics); } if (Compilation.Options.HasRuntime) { Debug.Assert(destination == Compilation.CodeBlockType() || conv.Exists); } if (!syntax.XIsCodeBlock && !Compilation.Options.MacroScript && !syntax.XNode.IsAliasExpression()) { Error(diagnostics, ErrorCode.ERR_CodeblockWithLambdaSyntax, syntax); } AnonymousTypeManager manager = this.Compilation.AnonymousTypeManager; var delegateSignature = new TypeSymbol[unboundLambda.ParameterCount + 1]; var usualType = this.Compilation.UsualType(); for (int i = 0; i < delegateSignature.Length; i++) { delegateSignature[i] = usualType; } NamedTypeSymbol cbType = manager.ConstructCodeblockTypeSymbol(delegateSignature, syntax.Location); var delType = manager.GetCodeblockDelegateType(cbType); var _boundLambda = unboundLambda.Bind(delType); diagnostics.AddRange(_boundLambda.Diagnostics); var cbDel = new BoundConversion( syntax, _boundLambda, conversion, @checked: false, explicitCastInCode: false, constantValueOpt: ConstantValue.NotAvailable, type: delType) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }; var cbSrc = new BoundLiteral(syntax, ConstantValue.Create(syntax.XCodeBlockSource), Compilation.GetSpecialType(SpecialType.System_String)); BoundExpression cbInst = new BoundAnonymousObjectCreationExpression(syntax, cbType.InstanceConstructors[0], new BoundExpression[] { cbDel, cbSrc }.ToImmutableArrayOrEmpty(), System.Collections.Immutable.ImmutableArray <BoundAnonymousPropertyDeclaration> .Empty, cbType) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated };; if (conv != Conversion.ImplicitReference) { cbInst = new BoundConversion(syntax, cbInst, Conversion.ImplicitReference, false, false, ConstantValue.NotAvailable, Compilation.CodeBlockType()) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated };; } if (!conv.IsValid || (!isCast && conv.IsExplicit)) { GenerateImplicitConversionError(diagnostics, syntax, conv, cbInst, destination); return(new BoundConversion( syntax, cbInst, conv, false, explicitCastInCode: isCast, constantValueOpt: ConstantValue.NotAvailable, type: destination, hasErrors: true) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }); } return(new BoundConversion( syntax, cbInst, conv, false, explicitCastInCode: isCast, constantValueOpt: ConstantValue.NotAvailable, type: destination) { WasCompilerGenerated = unboundLambda.WasCompilerGenerated }); }