diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -201,6 +201,14 @@ /// float f = i; CAST_OPERATION(IntegralToFloating) +/// CK_FloatingToFixedPoint - Floating to fixed point. +/// _Accum a = f; +CAST_OPERATION(FloatingToFixedPoint) + +/// CK_FixedPointToFloating - Fixed point to floating. +/// (float) 2.5k +CAST_OPERATION(FixedPointToFloating) + /// CK_FixedPointCast - Fixed point to fixed point. /// (_Accum) 0.5r CAST_OPERATION(FixedPointCast) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1763,6 +1763,8 @@ case CK_ARCExtendBlockObject: case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12782,6 +12782,8 @@ case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_IntegralToFixedPoint: llvm_unreachable("invalid cast kind for integral value"); @@ -13026,6 +13028,26 @@ return Success(IntResult, E); } + case CK_FloatingToFixedPoint: { + APFloat Src(0.0); + if (!EvaluateFloat(SubExpr, Src, Info)) + return false; + + bool Overflowed; + APFixedPoint Result = APFixedPoint::getFromFloatValue( + Src, Info.Ctx.getFixedPointSemantics(DestType), &Overflowed); + + if (Overflowed) { + if (Info.checkingForUndefinedBehavior()) + Info.Ctx.getDiagnostics().Report(E->getExprLoc(), + diag::warn_fixedpoint_constant_overflow) + << Result.toString() << E->getType(); + else if (!HandleOverflow(Info, E, Result, E->getType())) + return false; + } + + return Success(Result, E); + } case CK_NoOp: case CK_LValueToRValue: return ExprEvaluatorBaseTy::VisitCastExpr(E); @@ -13332,6 +13354,15 @@ E->getType(), Result); } + case CK_FixedPointToFloating: { + APFixedPoint FixResult(Info.Ctx.getFixedPointSemantics(SubExpr->getType())); + if (!EvaluateFixedPoint(SubExpr, FixResult, Info)) + return false; + Result = + FixResult.convertToFloat(Info.Ctx.getFloatTypeSemantics(E->getType())); + return true; + } + case CK_FloatingCast: { if (!Visit(SubExpr)) return false; @@ -13477,6 +13508,8 @@ case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4564,6 +4564,8 @@ case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -903,6 +903,8 @@ case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -527,6 +527,8 @@ case CK_ZeroToOCLOpaqueType: case CK_AddressSpaceConversion: case CK_IntToOCLSampler: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1163,6 +1163,8 @@ case CK_FloatingToIntegral: case CK_FloatingToBoolean: case CK_FloatingCast: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2212,6 +2212,8 @@ case CK_IntegralToFloating: case CK_FloatingToIntegral: case CK_FloatingCast: + case CK_FixedPointToFloating: + case CK_FloatingToFixedPoint: return EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()); case CK_BooleanToSignedIntegral: { diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1085,6 +1085,8 @@ case CK_BooleanToSignedIntegral: llvm_unreachable("OpenCL-specific cast in Objective-C?"); + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -1124,11 +1124,17 @@ bool LHSFloat = LHSType->isRealFloatingType(); bool RHSFloat = RHSType->isRealFloatingType(); - // FIXME: Implement floating to fixed point conversion.(Bug 46268) - // Reference N1169 4.1.4 (Type conversion, usual arithmetic conversions). - if ((LHSType->isFixedPointType() && RHSFloat) || - (LHSFloat && RHSType->isFixedPointType())) - return QualType(); + // N1169 4.1.4: If one of the operands has a floating type and the other + // operand has a fixed-point type, the fixed-point operand + // is converted to the floating type [...] + if (LHSType->isFixedPointType() || RHSType->isFixedPointType()) { + if (LHSFloat) + RHS = S.ImpCastExprToType(RHS.get(), LHSType, CK_FixedPointToFloating); + else if (!IsCompAssign) + LHS = S.ImpCastExprToType(LHS.get(), RHSType, CK_FixedPointToFloating); + return LHSFloat ? LHSType : RHSType; + } + // If we have two real floating types, convert the smaller operand // to the bigger result. if (LHSFloat && RHSFloat) { @@ -7044,6 +7050,7 @@ case Type::STK_Integral: return CK_FixedPointToIntegral; case Type::STK_Floating: + return CK_FixedPointToFloating; case Type::STK_IntegralComplex: case Type::STK_FloatingComplex: Diag(Src.get()->getExprLoc(), @@ -7116,10 +7123,7 @@ case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); case Type::STK_FixedPoint: - Diag(Src.get()->getExprLoc(), - diag::err_unimplemented_conversion_with_fixed_point_type) - << SrcTy; - return CK_IntegralCast; + return CK_FloatingToFixedPoint; } llvm_unreachable("Should have returned before this"); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -418,6 +418,8 @@ case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: case CK_LValueBitCast: + case CK_FloatingToFixedPoint: + case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: diff --git a/clang/test/Frontend/fixed_point_conversions_const.c b/clang/test/Frontend/fixed_point_conversions_const.c --- a/clang/test/Frontend/fixed_point_conversions_const.c +++ b/clang/test/Frontend/fixed_point_conversions_const.c @@ -43,6 +43,37 @@ short _Accum sa_const7 = -256; // CHECK-DAG: @sa_const7 = {{.*}}global i16 -32768, align 2 +// Fixed point to floating point +float fl_const = 1.0hk; +// CHECK-DAG: @fl_const = {{.*}}global float 1.000000e+00, align 4 +float fl_const2 = -128.0k; +// CHECK-DAG: @fl_const2 = {{.*}}global float -1.280000e+02, align 4 +float fl_const3 = 0.0872802734375k; +// CHECK-DAG: @fl_const3 = {{.*}}global float 0x3FB6580000000000, align 4 +float fl_const4 = 192.5k; +// CHECK-DAG: @fl_const4 = {{.*}}global float 1.925000e+02, align 4 +float fl_const5 = -192.5k; +// CHECK-DAG: @fl_const5 = {{.*}}global float -1.925000e+02, align 4 + +// Floating point to fixed point +_Accum a_fl_const = 1.0f; +// CHECK-DAG: @a_fl_const = {{.*}}global i32 32768, align 4 +_Accum a_fl_const2 = -128.0f; +// CHECK-DAG: @a_fl_const2 = {{.*}}global i32 -4194304, align 4 +_Accum a_fl_const3 = 0.0872802734375f; +// CHECK-DAG: @a_fl_const3 = {{.*}}global i32 2860, align 4 +_Accum a_fl_const4 = 0.0872802734375; +// CHECK-DAG: @a_fl_const4 = {{.*}}global i32 2860, align 4 +_Accum a_fl_const5 = -0.0872802734375f; +// CHECK-DAG: @a_fl_const5 = {{.*}}global i32 -2860, align 4 +_Fract f_fl_const = 0.5f; +// CHECK-DAG: @f_fl_const = {{.*}}global i16 16384, align 2 +_Fract f_fl_const2 = -0.75; +// CHECK-DAG: @f_fl_const2 = {{.*}}global i16 -24576, align 2 +unsigned short _Accum usa_fl_const = 48.75f; +// SIGNED-DAG: @usa_fl_const = {{.*}}global i16 12480, align 2 +// UNSIGNED-DAG: @usa_fl_const = {{.*}}global i16 6240, align 2 + // Signedness unsigned short _Accum usa_const2 = 2.5hk; // SIGNED-DAG: @usa_const2 = {{.*}}global i16 640, align 2 diff --git a/clang/test/Frontend/fixed_point_errors.c b/clang/test/Frontend/fixed_point_errors.c --- a/clang/test/Frontend/fixed_point_errors.c +++ b/clang/test/Frontend/fixed_point_errors.c @@ -286,8 +286,3 @@ // Division by zero short _Accum div_zero = 4.5k / 0.0lr; // expected-error {{initializer element is not a compile-time constant}} - -void foo(void) { - _Accum x = 0.5k; - if (x == 0.5) {} // expected-error{{invalid operands to binary expression ('_Accum' and 'double')}} -} diff --git a/clang/test/Frontend/fixed_point_unknown_conversions.c b/clang/test/Frontend/fixed_point_unknown_conversions.c --- a/clang/test/Frontend/fixed_point_unknown_conversions.c +++ b/clang/test/Frontend/fixed_point_unknown_conversions.c @@ -22,16 +22,12 @@ _Fract fract = accum; // ok _Accum *accum_ptr; - accum = f; // expected-error{{conversion between fixed point and 'float' is not yet supported}} - accum = d; // expected-error{{conversion between fixed point and 'double' is not yet supported}} accum = dc; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}} accum = ic; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}} accum = s; // expected-error{{assigning to '_Accum' from incompatible type 'struct S'}} accum = ptr; // expected-error{{assigning to '_Accum' from incompatible type 'int *'}} accum_ptr = ptr; // expected-warning{{incompatible pointer types assigning to '_Accum *' from 'int *'}} - f = accum; // expected-error{{conversion between fixed point and 'float' is not yet supported}} - d = accum; // expected-error{{conversion between fixed point and 'double' is not yet supported}} dc = accum; // expected-error{{conversion between fixed point and '_Complex double' is not yet supported}} ic = accum; // expected-error{{conversion between fixed point and '_Complex int' is not yet supported}} s = accum; // expected-error{{assigning to 'struct S' from incompatible type '_Accum'}}