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 @@ -1654,6 +1654,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 @@ -9163,6 +9163,7 @@ QualType SrcType = SubExpr->getType(); switch (E->getCastKind()) { + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_IntegralToFixedPoint: llvm_unreachable("IntExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO @@ -9760,6 +9761,7 @@ switch (E->getCastKind()) { case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_IntegralToFixedPoint: llvm_unreachable("ComplexExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint"); // TODO case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_BitCast: Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -4045,6 +4045,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { switch (E->getCastKind()) { case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_IntegralToFixedPoint: llvm_unreachable("CodeGenFunction::EmitCastLValue CK_IntegralToFixedPoint"); // TODO case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_ToVoid: Index: lib/CodeGen/CGExprAgg.cpp =================================================================== --- lib/CodeGen/CGExprAgg.cpp +++ lib/CodeGen/CGExprAgg.cpp @@ -671,6 +671,7 @@ if (const auto *ECE = dyn_cast(E)) CGF.CGM.EmitExplicitCastExprType(ECE, &CGF); switch (E->getCastKind()) { + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_IntegralToFixedPoint: llvm_unreachable("AggExprEmitter::VisitCastExpr CK_IntegralToFixedPoint"); // TODO Index: lib/CodeGen/CGExprComplex.cpp =================================================================== --- lib/CodeGen/CGExprComplex.cpp +++ lib/CodeGen/CGExprComplex.cpp @@ -449,6 +449,7 @@ case CK_IntegralToFixedPoint: llvm_unreachable("ComplexExprEmitter::EmitCast CK_IntegralToFixedPoint"); // TODO case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!"); // Atomic to non-atomic casts may be more than a no-op for some platforms and Index: lib/CodeGen/CGExprConstant.cpp =================================================================== --- lib/CodeGen/CGExprConstant.cpp +++ lib/CodeGen/CGExprConstant.cpp @@ -687,6 +687,7 @@ 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: llvm_unreachable("VisitCastExpr CK_IntegralToFixedPoint"); // TODO case CK_ToUnion: { Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -1691,6 +1691,7 @@ // 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 @@ -1005,6 +1005,7 @@ case CK_IntegralToFixedPoint: llvm_unreachable("rewriteToNumericBoxedExpression CK_IntegralToFixedPoint"); // TODO case CK_FixedPointCast: llvm_unreachable("rewriteToNumericBoxedExpression CK_FixedPointCast"); // TODO 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 @@ -6055,7 +6055,7 @@ case Type::STK_FixedPoint: { switch (DestTy->getScalarTypeKind()) { 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 + case Type::STK_Integral: return CK_IntegralToFixedPoint; case Type::STK_Floating: return CK_FixedPointToFloating; case Type::STK_FixedPoint: return CK_FixedPointCast; } @@ -6064,7 +6064,8 @@ case Type::STK_Bool: // casting from bool is like casting from an integer case Type::STK_Integral: switch (DestTy->getScalarTypeKind()) { - case Type::STK_FixedPoint: llvm_unreachable("Sema::PrepareScalarCast from STK_Integral to STK_FixedPoint"); // TODO + case Type::STK_FixedPoint: + return CK_IntegralToFixedPoint; case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: case Type::STK_BlockPointer: @@ -6095,7 +6096,8 @@ case Type::STK_Floating: switch (DestTy->getScalarTypeKind()) { - case Type::STK_FixedPoint: llvm_unreachable("Sema::PrepareScalarCast from STK_Floating to STK_FixedPoint"); // TODO + case Type::STK_FixedPoint: + 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 @@ -321,6 +321,7 @@ const LocationContext *LCtx = Pred->getLocationContext(); switch (CastE->getCastKind()) { + case CK_FloatingToFixedPoint: llvm_unreachable("CK_FloatingToFixedPoint"); case CK_FixedPointToFloating: llvm_unreachable("Unimplemented logic for CK_FixedPointToFloating"); case CK_IntegralToFixedPoint: llvm_unreachable("ExprEngine::VisitCast CK_IntegralToFixedPoint"); // TODO case CK_FixedPointCast: llvm_unreachable("CK_FixedPointCast"); // TODO Index: test/Frontend/fixed_point_all_conversions.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point_all_conversions.c @@ -0,0 +1,72 @@ +// 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);