Index: include/clang/AST/OperationKinds.def =================================================================== --- include/clang/AST/OperationKinds.def +++ include/clang/AST/OperationKinds.def @@ -210,6 +210,11 @@ /// (float) 2.5hk CAST_OPERATION(FixedPointToFloating) +/// CK_FloatingToFixedPoint - Floating point to fixed point. Rounds +/// towards zero, discarding any fractional component. +/// (short _Accum) f +CAST_OPERATION(FloatingToFixedPoint) + /// CK_FloatingToIntegral - Floating point to integral. Rounds /// towards zero, discarding any fractional component. /// (int) f Index: lib/AST/Expr.cpp =================================================================== --- lib/AST/Expr.cpp +++ lib/AST/Expr.cpp @@ -1656,6 +1656,7 @@ case CK_IntegralToFixedPoint: case CK_FixedPointCast: case CK_FixedPointToFloating: + case CK_FloatingToFixedPoint: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -9160,13 +9160,15 @@ QualType SrcType = SubExpr->getType(); switch (E->getCastKind()) { + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_IntegralToFixedPoint: llvm_unreachable( "IntExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO case CK_FixedPointToFloating: - llvm_unreachable("CK_FixedPointCast"); // TODO + llvm_unreachable("CK_FixedPointToFloating"); // TODO case CK_BaseToDerived: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: @@ -9759,11 +9761,13 @@ switch (E->getCastKind()) { case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_IntegralToFixedPoint: llvm_unreachable( "ComplexExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO case CK_FixedPointToFloating: - llvm_unreachable("CK_FixedPointCast"); // TODO + llvm_unreachable("CK_FixedPointToFloating"); // TODO case CK_BitCast: case CK_BaseToDerived: case CK_DerivedToBase: Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4046,6 +4046,8 @@ switch (E->getCastKind()) { case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_IntegralToFixedPoint: llvm_unreachable( "CodeGenFunction::EmitCastLValue CK_IntegralToFixedPoint"); // TODO Index: lib/CodeGen/CGExprAgg.cpp =================================================================== --- lib/CodeGen/CGExprAgg.cpp +++ lib/CodeGen/CGExprAgg.cpp @@ -671,6 +671,8 @@ if (const auto *ECE = dyn_cast(E)) CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); switch (E->getCastKind()) { + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_IntegralToFixedPoint: Index: lib/CodeGen/CGExprComplex.cpp =================================================================== --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -451,6 +451,8 @@ case CK_IntegralToFixedPoint: llvm_unreachable( "ComplexExprEmitter::EmitCast CK_IntegralToFixedPoint"); // TODO + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointToFloating: llvm_unreachable("CK_FixedPointToFloating"); // TODO case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!"); Index: lib/CodeGen/CGExprConstant.cpp =================================================================== --- lib/CodeGen/CGExprConstant.cpp +++ lib/CodeGen/CGExprConstant.cpp @@ -688,6 +688,8 @@ switch (E->getCastKind()) { case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_IntegralToFixedPoint: Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1697,6 +1697,8 @@ // a default case, so the compiler will warn on a missing case. The cases // are in the same order as in the CastKind enum. switch (Kind) { + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!"); case CK_BuiltinFnToFnPtr: llvm_unreachable("builtin functions are handled elsewhere"); Index: lib/Edit/RewriteObjCFoundationAPI.cpp =================================================================== --- lib/Edit/RewriteObjCFoundationAPI.cpp +++ lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1011,6 +1011,8 @@ case CK_FixedPointToFloating: llvm_unreachable( "Unimplemented logic for CK_FixedPointToFloating"); + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_LValueToRValue: case CK_NoOp: case CK_UserDefinedConversion: Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -6071,8 +6071,7 @@ default: llvm_unreachable("Unable to convert from fixed point type"); case Type::STK_Integral: - llvm_unreachable( - "Unimplemented scalar cast from fixed point to int"); // TODO + return CK_IntegralToFixedPoint; case Type::STK_Floating: return CK_FixedPointToFloating; case Type::STK_FixedPoint: @@ -6084,8 +6083,7 @@ case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { case Type::STK_FixedPoint: - llvm_unreachable( - "Sema::PrepareScalarCast from STK_Integral to STK_FixedPoint"); // TODO + return CK_IntegralToFixedPoint; case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: case Type::STK_BlockPointer: @@ -6117,8 +6115,7 @@ case Type::STK_Floating: switch (DestTy->getScalarTypeKind()) { case Type::STK_FixedPoint: - llvm_unreachable( - "Sema::PrepareScalarCast from STK_Floating to STK_FixedPoint"); // TODO + return CK_FloatingToFixedPoint; case Type::STK_Floating: return CK_FloatingCast; case Type::STK_Bool: Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -323,6 +323,8 @@ switch (CastE->getCastKind()) { case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO + case CK_FloatingToFixedPoint: + llvm_unreachable("CK_FloatingToFixedPoint"); case CK_IntegralToFixedPoint: llvm_unreachable( "ExprEngine::VisitCast CK_IntegralToFixedPoint"); // TODO Index: test/Frontend/fixed_point_all_conversions.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point_all_conversions.c @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -Werror %s + +// Test for conversions between fixed point types and all other valid types. + +// Conversion from one type to another type +#define CONVERT(FROM_TYPE, FROM_ID, TO_TYPE, TO_ID) \ + TO_TYPE FROM_ID##_to_##TO_ID(FROM_TYPE x) { return x; } + +// Conversion between 2 types +#define CONVERT_COMBINATION(TYPE1, ID1, TYPE2, ID2) \ + CONVERT(TYPE1, ID1, TYPE2, ID2) \ + CONVERT(TYPE2, ID2, TYPE1, ID1) + +// Conversion between one type and floating point types +#define CONVERT_BETWEEN_FLOATS(TYPE, ID) \ + CONVERT_COMBINATION(TYPE, ID, float, Float) \ + CONVERT_COMBINATION(TYPE, ID, double, Double) + +// Conversion between one type and an integral type with differant signage +#define CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, INT_TYPE, INT_ID) \ + CONVERT_COMBINATION(TYPE, ID, INT_TYPE, INT_ID) \ + CONVERT_COMBINATION(TYPE, ID, signed INT_TYPE, Signed##INT_ID) \ + CONVERT_COMBINATION(TYPE, ID, unsigned INT_TYPE, Unsigned##INT_ID) + +// Conversion between one type and all integral types +#define CONVERT_BETWEEN_INTEGRALS(TYPE, ID) \ + CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, char, Char) \ + CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, short, Short) \ + CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, int, Int) \ + CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long, Long) \ + CONVERT_BETWEEN_INTEGRALS_WITH_SIGN(TYPE, ID, long long, LongLong) + +// Conversion between one type and a fixed point type with different saturation +#define CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID) \ + CONVERT_COMBINATION(TYPE, ID, FIXED_TYPE, FIXED_ID) \ + CONVERT_COMBINATION(TYPE, ID, _Sat FIXED_TYPE, Sat##FIXED_ID) + +// Conversion between one type and a fixed point type with different signage +#define CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, FIXED_TYPE, FIXED_ID) \ + CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, FIXED_TYPE, FIXED_ID) \ + CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, signed FIXED_TYPE, \ + Signed##FIXED_ID) \ + CONVERT_BETWEEN_FIXED_POINT_WITH_SAT(TYPE, ID, unsigned FIXED_TYPE, \ + Unsigned##FIXED_ID) + +// Convert between one type and all fixed point types. +// Add "Type" to the end of the ID to avoid multiple definitions of a function +// if the Type is a fixed point type. +#define CONVERT_BETWEEN_FIXED_POINT(TYPE, ID) \ + CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Fract, FractType) \ + CONVERT_BETWEEN_FIXED_POINT_WITH_SIGN(TYPE, ID, _Accum, AccumType) + +// Convert between one type and all other types +#define CONVERT_BETWEEN_ALL_TYPES(TYPE, ID) \ + CONVERT_BETWEEN_FLOATS(TYPE, ID) \ + CONVERT_BETWEEN_INTEGRALS(TYPE, ID) \ + CONVERT_BETWEEN_FIXED_POINT(TYPE, ID) + +#define CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID) \ + CONVERT_BETWEEN_ALL_TYPES(TYPE, ID) \ + CONVERT_BETWEEN_ALL_TYPES(_Sat TYPE, Sat##ID) + +#define CONVERT_FIXED_POINT_TYPE(TYPE, ID) \ + CONVERT_FIXED_POINT_TYPE_WITH_SAT(TYPE, ID) \ + CONVERT_FIXED_POINT_TYPE_WITH_SAT(signed TYPE, Signed##ID) \ + CONVERT_FIXED_POINT_TYPE_WITH_SAT(unsigned TYPE, Unsigned##ID) + +CONVERT_FIXED_POINT_TYPE(short _Fract, ShortFract); +CONVERT_FIXED_POINT_TYPE(_Fract, Fract); +CONVERT_FIXED_POINT_TYPE(long _Fract, LongFract); + +CONVERT_FIXED_POINT_TYPE(short _Accum, ShortAccum); +CONVERT_FIXED_POINT_TYPE(_Accum, Accum); +CONVERT_FIXED_POINT_TYPE(long _Accum, LongAccum);