Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1797,6 +1797,10 @@ case BuiltinType::UShortAccum: case BuiltinType::ShortFract: case BuiltinType::UShortFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatUShortFract: Width = Target->getShortWidth(); Align = Target->getShortAlign(); break; @@ -1806,6 +1810,10 @@ case BuiltinType::UAccum: case BuiltinType::Fract: case BuiltinType::UFract: + case BuiltinType::SatAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatFract: + case BuiltinType::SatUFract: Width = Target->getIntWidth(); Align = Target->getIntAlign(); break; @@ -1815,6 +1823,10 @@ case BuiltinType::ULongAccum: case BuiltinType::LongFract: case BuiltinType::ULongFract: + case BuiltinType::SatLongAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatLongFract: + case BuiltinType::SatULongFract: Width = Target->getLongWidth(); Align = Target->getLongAlign(); break; Index: lib/CodeGen/CGExprScalar.cpp =================================================================== --- lib/CodeGen/CGExprScalar.cpp +++ lib/CodeGen/CGExprScalar.cpp @@ -2214,39 +2214,51 @@ switch (BT->getKind()) { default: llvm_unreachable("Not a fixed point type!"); + case BuiltinType::SatShortAccum: case BuiltinType::ShortAccum: fbits = BUILTIN_SACCUM_FBIT; break; + case BuiltinType::SatAccum: case BuiltinType::Accum: fbits = BUILTIN_ACCUM_FBIT; break; + case BuiltinType::SatLongAccum: case BuiltinType::LongAccum: fbits = BUILTIN_LACCUM_FBIT; break; + case BuiltinType::SatUShortAccum: case BuiltinType::UShortAccum: fbits = BUILTIN_USACCUM_FBIT; break; + case BuiltinType::SatUAccum: case BuiltinType::UAccum: fbits = BUILTIN_UACCUM_FBIT; break; + case BuiltinType::SatULongAccum: case BuiltinType::ULongAccum: fbits = BUILTIN_ULACCUM_FBIT; break; + case BuiltinType::SatShortFract: case BuiltinType::ShortFract: fbits = BUILTIN_SFRACT_FBIT; break; + case BuiltinType::SatFract: case BuiltinType::Fract: fbits = BUILTIN_FRACT_FBIT; break; + case BuiltinType::SatLongFract: case BuiltinType::LongFract: fbits = BUILTIN_LFRACT_FBIT; break; + case BuiltinType::SatUShortFract: case BuiltinType::UShortFract: fbits = BUILTIN_USFRACT_FBIT; break; + case BuiltinType::SatUFract: case BuiltinType::UFract: fbits = BUILTIN_UFRACT_FBIT; break; + case BuiltinType::SatULongFract: case BuiltinType::ULongFract: fbits = BUILTIN_ULFRACT_FBIT; break; Index: test/Frontend/fixed_point_all_builtin_operations.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point_all_builtin_operations.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -Werror %s + +// Check that we can use all supported binary and unary operations according to +// clause 4.1.6 in N1169. + +#define ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \ + TYPE unary_add##ID(TYPE a) { return +a; } \ + TYPE unary_sub##ID(TYPE a) { return -a; } \ + int logical_not##ID(TYPE a) { return !a; } \ + TYPE add##ID(TYPE a, TYPE b) { return a + b; } \ + TYPE sub##ID(TYPE a, TYPE b) { return a - b; } \ + TYPE mul##ID(TYPE a, TYPE b) { return a * b; } \ + TYPE div##ID(TYPE a, TYPE b) { return a / b; } \ + TYPE shl##ID(TYPE a, int b) { return a << b; } \ + TYPE shr##ID(TYPE a, int b) { return a >> b; } \ + TYPE augmented_add##ID(TYPE a, TYPE b) { \ + a += b; \ + return a; \ + } \ + TYPE augmented_sub##ID(TYPE a, TYPE b) { \ + a -= b; \ + return a; \ + } \ + TYPE augmented_mul##ID(TYPE a, TYPE b) { \ + a *= b; \ + return a; \ + } \ + TYPE augmented_div##ID(TYPE a, TYPE b) { \ + a /= b; \ + return a; \ + } \ + TYPE augmented_shl##ID(TYPE a, int b) { \ + a <<= b; \ + return a; \ + } \ + TYPE augmented_shr##ID(TYPE a, int b) { \ + a >>= b; \ + return a; \ + } \ + int eq##ID(TYPE a, TYPE b) { return a == b; } \ + int ne##ID(TYPE a, TYPE b) { return a != b; } \ + int lt##ID(TYPE a, TYPE b) { return a < b; } \ + int le##ID(TYPE a, TYPE b) { return a <= b; } \ + int ge##ID(TYPE a, TYPE b) { return a >= b; } \ + int gt##ID(TYPE a, TYPE b) { return a > b; } \ + TYPE pre_inc##ID(TYPE a) { return ++a; } \ + TYPE pre_dec##ID(TYPE a) { return --a; } \ + TYPE post_inc##ID(TYPE a) { return a++; } \ + TYPE post_dec##ID(TYPE a) { return a--; } \ + TYPE deref_pre_inc##ID(TYPE *a) { return ++(*a); } \ + TYPE deref_pre_dec##ID(TYPE *a) { return --(*a); } \ + TYPE deref_post_inc##ID(TYPE *a) { return (*a)++; } \ + TYPE deref_post_dec##ID(TYPE *a) { return (*a)--; } + +#define ALL_OPERATIONS(TYPE, ID) \ + ALL_OPERATIONS_FOR_TYPE(TYPE, ID) \ + ALL_OPERATIONS_FOR_TYPE(signed TYPE, Signed##ID) \ + ALL_OPERATIONS_FOR_TYPE(unsigned TYPE, Unsigned##ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat TYPE, Sat##ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat signed TYPE, SatSigned##ID) \ + ALL_OPERATIONS_FOR_TYPE(_Sat unsigned TYPE, SatUnsigned##ID) + +ALL_OPERATIONS(short _Fract, ShortFract); +ALL_OPERATIONS(_Fract, Fract); +ALL_OPERATIONS(long _Fract, LongFract); +ALL_OPERATIONS(short _Accum, ShortAccum); +ALL_OPERATIONS(_Accum, Accum); +ALL_OPERATIONS(long _Accum, LongAccum);