Index: include/clang/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -1008,6 +1008,14 @@ CanQualType ShortAccumTy, AccumTy, LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy; + CanQualType ShortFractTy, FractTy, LongFractTy; + CanQualType UnsignedShortFractTy, UnsignedFractTy, UnsignedLongFractTy; + CanQualType SatShortAccumTy, SatAccumTy, SatLongAccumTy; + CanQualType SatUnsignedShortAccumTy, SatUnsignedAccumTy, + SatUnsignedLongAccumTy; + CanQualType SatShortFractTy, SatFractTy, SatLongFractTy; + CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy, + SatUnsignedLongFractTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; Index: include/clang/AST/BuiltinTypes.def =================================================================== --- include/clang/AST/BuiltinTypes.def +++ include/clang/AST/BuiltinTypes.def @@ -139,6 +139,60 @@ // 'unsigned long _Accum' UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy) +// 'short _Fract' +SIGNED_TYPE(ShortFract, ShortFractTy) + +// '_Fract' +SIGNED_TYPE(Fract, FractTy) + +// 'long _Fract' +SIGNED_TYPE(LongFract, LongFractTy) + +// 'unsigned short _Fract' +UNSIGNED_TYPE(UShortFract, UnsignedShortFractTy) + +// 'unsigned _Fract' +UNSIGNED_TYPE(UFract, UnsignedFractTy) + +// 'unsigned long _Fract' +UNSIGNED_TYPE(ULongFract, UnsignedLongFractTy) + +// '_Sat short _Accum' +SIGNED_TYPE(SatShortAccum, SatShortAccumTy) + +// '_Sat _Accum' +SIGNED_TYPE(SatAccum, SatAccumTy) + +// '_Sat long _Accum' +SIGNED_TYPE(SatLongAccum, SatLongAccumTy) + +// '_Sat unsigned short _Accum' +UNSIGNED_TYPE(SatUShortAccum, SatUnsignedShortAccumTy) + +// '_Sat unsigned _Accum' +UNSIGNED_TYPE(SatUAccum, SatUnsignedAccumTy) + +// '_Sat unsigned long _Accum' +UNSIGNED_TYPE(SatULongAccum, SatUnsignedLongAccumTy) + +// '_Sat short _Fract' +SIGNED_TYPE(SatShortFract, SatShortFractTy) + +// '_Sat _Fract' +SIGNED_TYPE(SatFract, SatFractTy) + +// '_Sat long _Fract' +SIGNED_TYPE(SatLongFract, SatLongFractTy) + +// '_Sat unsigned short _Fract' +UNSIGNED_TYPE(SatUShortFract, SatUnsignedShortFractTy) + +// '_Sat unsigned _Fract' +UNSIGNED_TYPE(SatUFract, SatUnsignedFractTy) + +// '_Sat unsigned long _Fract' +UNSIGNED_TYPE(SatULongFract, SatUnsignedLongFractTy) + //===- Floating point types -----------------------------------------------===// // 'half' in OpenCL, '__fp16' in ARM NEON. Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -203,6 +203,7 @@ def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup; +def err_invalid_saturation_spec : Error<"'%0' cannot be saturated. Only _Fract and _Accum can.">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_width_spec : Error< "'%select{|short|long|long long}0 %1' is invalid">; Index: include/clang/Basic/Specifiers.h =================================================================== --- include/clang/Basic/Specifiers.h +++ include/clang/Basic/Specifiers.h @@ -54,6 +54,7 @@ TST_half, // OpenCL half, ARM NEON __fp16 TST_Float16, // C11 extension ISO/IEC TS 18661-3 TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension + TST_Fract, TST_float, TST_double, TST_float128, Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -385,6 +385,8 @@ // ISO/IEC JTC1 SC22 WG14 N1169 Extension KEYWORD(_Accum , KEYALL) +KEYWORD(_Fract , KEYALL) +KEYWORD(_Sat , KEYALL) // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -282,6 +282,7 @@ static const TST TST_double = clang::TST_double; static const TST TST_float16 = clang::TST_Float16; static const TST TST_accum = clang::TST_Accum; + static const TST TST_fract = clang::TST_Fract; static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; @@ -346,6 +347,7 @@ unsigned TypeAltiVecBool : 1; unsigned TypeSpecOwned : 1; unsigned TypeSpecPipe : 1; + unsigned TypeSpecSat : 1; // type-qualifiers unsigned TypeQualifiers : 5; // Bitwise OR of TQ. @@ -381,7 +383,7 @@ SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc; SourceRange TSWRange; - SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; + SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc; /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union, /// typename, then this is the location of the named type (if present); /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and @@ -430,6 +432,7 @@ TypeAltiVecBool(false), TypeSpecOwned(false), TypeSpecPipe(false), + TypeSpecSat(false), TypeQualifiers(TQ_unspecified), FS_inline_specified(false), FS_forceinline_specified(false), @@ -483,6 +486,7 @@ bool isTypeSpecOwned() const { return TypeSpecOwned; } bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); } bool isTypeSpecPipe() const { return TypeSpecPipe; } + bool isTypeSpecSat() const { return TypeSpecSat; } ParsedType getRepAsType() const { assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type"); @@ -661,6 +665,8 @@ bool SetTypePipe(bool isPipe, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy); + bool SetTypeSpecSat(bool isSat, SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); bool SetTypeSpecError(); void UpdateDeclRep(Decl *Rep) { assert(isDeclRep((TST) TypeSpecType)); Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -954,6 +954,60 @@ /// \brief The 'unsigned long _Accum' type PREDEF_TYPE_ULONG_ACCUM_ID = 50, + /// \brief The 'short _Fract' type + PREDEF_TYPE_SHORT_FRACT_ID = 51, + + /// \brief The '_Fract' type + PREDEF_TYPE_FRACT_ID = 52, + + /// \brief The 'long _Fract' type + PREDEF_TYPE_LONG_FRACT_ID = 53, + + /// \brief The 'unsigned short _Fract' type + PREDEF_TYPE_USHORT_FRACT_ID = 54, + + /// \brief The 'unsigned _Fract' type + PREDEF_TYPE_UFRACT_ID = 55, + + /// \brief The 'unsigned long _Fract' type + PREDEF_TYPE_ULONG_FRACT_ID = 56, + + /// \brief The '_Sat short _Accum' type + PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 57, + + /// \brief The '_Sat _Accum' type + PREDEF_TYPE_SAT_ACCUM_ID = 58, + + /// \brief The '_Sat long _Accum' type + PREDEF_TYPE_SAT_LONG_ACCUM_ID = 59, + + /// \brief The '_Sat unsigned short _Accum' type + PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 60, + + /// \brief The '_Sat unsigned _Accum' type + PREDEF_TYPE_SAT_UACCUM_ID = 61, + + /// \brief The '_Sat unsigned long _Accum' type + PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 62, + + /// \brief The '_Sat short _Fract' type + PREDEF_TYPE_SAT_SHORT_FRACT_ID = 63, + + /// \brief The '_Sat _Fract' type + PREDEF_TYPE_SAT_FRACT_ID = 64, + + /// \brief The '_Sat long _Fract' type + PREDEF_TYPE_SAT_LONG_FRACT_ID = 65, + + /// \brief The '_Sat unsigned short _Fract' type + PREDEF_TYPE_SAT_USHORT_FRACT_ID = 66, + + /// \brief The '_Sat unsigned _Fract' type + PREDEF_TYPE_SAT_UFRACT_ID = 67, + + /// \brief The '_Sat unsigned long _Fract' type + PREDEF_TYPE_SAT_ULONG_FRACT_ID = 68, + /// \brief OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, @@ -965,7 +1019,7 @@ /// /// Type IDs for non-predefined types will start at /// NUM_PREDEF_TYPE_IDs. - const unsigned NUM_PREDEF_TYPE_IDS = 100; + const unsigned NUM_PREDEF_TYPE_IDS = 200; /// \brief Record codes for each kind of type. /// Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1134,12 +1134,30 @@ InitBuiltinType(Float16Ty, BuiltinType::Float16); // ISO/IEC JTC1 SC22 WG14 N1169 Extension - InitBuiltinType(ShortAccumTy, BuiltinType::ShortAccum); - InitBuiltinType(AccumTy, BuiltinType::Accum); - InitBuiltinType(LongAccumTy, BuiltinType::LongAccum); - InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum); - InitBuiltinType(UnsignedAccumTy, BuiltinType::UAccum); - InitBuiltinType(UnsignedLongAccumTy, BuiltinType::ULongAccum); + InitBuiltinType(ShortAccumTy, BuiltinType::ShortAccum); + InitBuiltinType(AccumTy, BuiltinType::Accum); + InitBuiltinType(LongAccumTy, BuiltinType::LongAccum); + InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum); + InitBuiltinType(UnsignedAccumTy, BuiltinType::UAccum); + InitBuiltinType(UnsignedLongAccumTy, BuiltinType::ULongAccum); + InitBuiltinType(ShortFractTy, BuiltinType::ShortFract); + InitBuiltinType(FractTy, BuiltinType::Fract); + InitBuiltinType(LongFractTy, BuiltinType::LongFract); + InitBuiltinType(UnsignedShortFractTy, BuiltinType::UShortFract); + InitBuiltinType(UnsignedFractTy, BuiltinType::UFract); + InitBuiltinType(UnsignedLongFractTy, BuiltinType::ULongFract); + InitBuiltinType(SatShortAccumTy, BuiltinType::SatShortAccum); + InitBuiltinType(SatAccumTy, BuiltinType::SatAccum); + InitBuiltinType(SatLongAccumTy, BuiltinType::SatLongAccum); + InitBuiltinType(SatUnsignedShortAccumTy, BuiltinType::SatUShortAccum); + InitBuiltinType(SatUnsignedAccumTy, BuiltinType::SatUAccum); + InitBuiltinType(SatUnsignedLongAccumTy, BuiltinType::SatULongAccum); + InitBuiltinType(SatShortFractTy, BuiltinType::SatShortFract); + InitBuiltinType(SatFractTy, BuiltinType::SatFract); + InitBuiltinType(SatLongFractTy, BuiltinType::SatLongFract); + InitBuiltinType(SatUnsignedShortFractTy, BuiltinType::SatUShortFract); + InitBuiltinType(SatUnsignedFractTy, BuiltinType::SatUFract); + InitBuiltinType(SatUnsignedLongFractTy, BuiltinType::SatULongFract); // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); @@ -6258,6 +6276,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: llvm_unreachable("No ObjC encoding for fixed point types"); // OpenCL and placeholder types don't need @encodings. Index: lib/AST/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -7323,6 +7323,15 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: return integer_type_class; case BuiltinType::NullPtr: Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2549,6 +2549,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: llvm_unreachable("Fixed point types are disabled for c++"); case BuiltinType::Half: Out << "Dh"; Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1928,6 +1928,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: case BuiltinType::Float128: case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp +++ lib/AST/NSAPI.cpp @@ -446,6 +446,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: case BuiltinType::UInt128: case BuiltinType::Float16: case BuiltinType::Float128: Index: lib/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -2660,6 +2660,42 @@ return "unsigned _Accum"; case ULongAccum: return "unsigned long _Accum"; + case BuiltinType::ShortFract: + return "short _Fract"; + case BuiltinType::Fract: + return "_Fract"; + case BuiltinType::LongFract: + return "long _Fract"; + case BuiltinType::UShortFract: + return "unsigned short _Fract"; + case BuiltinType::UFract: + return "unsigned _Fract"; + case BuiltinType::ULongFract: + return "unsigned long _Fract"; + case BuiltinType::SatShortAccum: + return "_Sat short _Accum"; + case BuiltinType::SatAccum: + return "_Sat _Accum"; + case BuiltinType::SatLongAccum: + return "_Sat long _Accum"; + case BuiltinType::SatUShortAccum: + return "_Sat unsigned short _Accum"; + case BuiltinType::SatUAccum: + return "_Sat unsigned _Accum"; + case BuiltinType::SatULongAccum: + return "_Sat unsigned long _Accum"; + case BuiltinType::SatShortFract: + return "_Sat short _Fract"; + case BuiltinType::SatFract: + return "_Sat _Fract"; + case BuiltinType::SatLongFract: + return "_Sat long _Fract"; + case BuiltinType::SatUShortFract: + return "_Sat unsigned short _Fract"; + case BuiltinType::SatUFract: + return "_Sat unsigned _Fract"; + case BuiltinType::SatULongFract: + return "_Sat unsigned long _Fract"; case Float16: return "_Float16"; case Float128: Index: lib/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -348,6 +348,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: llvm_unreachable("Builtin type needs extra local data!"); // Fall through, if the impossible happens. Index: lib/Analysis/PrintfFormatString.cpp =================================================================== --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -660,6 +660,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: // Various types which are non-trivial to correct. return false; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -678,6 +678,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: Encoding = llvm::dwarf::DW_ATE_unsigned; break; case BuiltinType::Short: Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.cpp @@ -445,6 +445,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: ResultType = llvm::IntegerType::get(getLLVMContext(), static_cast(Context.getTypeSize(T))); break; Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2716,6 +2716,24 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: return true; #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -688,9 +688,27 @@ case BuiltinType::UShortAccum: case BuiltinType::UAccum: case BuiltinType::ULongAccum: - c = '~'; // Special character to indicate we have a fixed point type and - // will be followed by further characters to indicate the - // type. + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: + c = '~'; // Special character to indicate we have a fixed point type + // and will be followed by further characters to indicate + // the type. break; case BuiltinType::Float16: case BuiltinType::Half: @@ -730,19 +748,80 @@ if (c == '~') { switch (BT->getKind()) { - default: llvm_unreachable("Unknown fixed point type"); + default: + llvm_unreachable("Unknown fixed point type"); case BuiltinType::ShortAccum: - Out << "sA"; break; + Out << "sA"; + break; case BuiltinType::Accum: - Out << "A"; break; + Out << "A"; + break; case BuiltinType::LongAccum: - Out << "lA"; break; + Out << "lA"; + break; case BuiltinType::UShortAccum: - Out << "UsA"; break; + Out << "UsA"; + break; case BuiltinType::UAccum: - Out << "UA"; break; + Out << "UA"; + break; case BuiltinType::ULongAccum: - Out << "UlA"; break; + Out << "UlA"; + break; + case BuiltinType::ShortFract: + Out << "sF"; + break; + case BuiltinType::Fract: + Out << "F"; + break; + case BuiltinType::LongFract: + Out << "lF"; + break; + case BuiltinType::UShortFract: + Out << "UsF"; + break; + case BuiltinType::UFract: + Out << "UF"; + break; + case BuiltinType::ULongFract: + Out << "UlF"; + break; + case BuiltinType::SatShortAccum: + Out << "SsA"; + break; + case BuiltinType::SatAccum: + Out << "SA"; + break; + case BuiltinType::SatLongAccum: + Out << "SlA"; + break; + case BuiltinType::SatUShortAccum: + Out << "SUsA"; + break; + case BuiltinType::SatUAccum: + Out << "SUA"; + break; + case BuiltinType::SatULongAccum: + Out << "SUlA"; + break; + case BuiltinType::SatShortFract: + Out << "SsF"; + break; + case BuiltinType::SatFract: + Out << "SF"; + break; + case BuiltinType::SatLongFract: + Out << "SlF"; + break; + case BuiltinType::SatUShortFract: + Out << "SUsF"; + break; + case BuiltinType::SatUFract: + Out << "SUF"; + break; + case BuiltinType::SatULongFract: + Out << "SUlF"; + break; } } Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3583,6 +3583,13 @@ isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Fract: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, DiagID, + Policy); + break; + case tok::kw__Sat: + isInvalid = DS.SetTypeSpecSat(true, Loc, PrevSpec, DiagID); + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -4596,6 +4603,7 @@ case tok::kw_float: case tok::kw_double: case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4673,6 +4681,7 @@ case tok::kw_float: case tok::kw_double: case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4811,6 +4820,9 @@ // Debugger support case tok::kw___unknown_anytype: + case tok::kw__Sat: + return true; + // type-specifiers case tok::kw_short: case tok::kw_long: @@ -4831,6 +4843,7 @@ case tok::kw_float: case tok::kw_double: case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -337,6 +337,7 @@ case TST_decimal64: case TST_double: case TST_Accum: + case TST_Fract: case TST_Float16: case TST_float128: case TST_enum: @@ -508,6 +509,7 @@ case DeclSpec::TST_float: return "float"; case DeclSpec::TST_double: return "double"; case DeclSpec::TST_accum: return "_Accum"; + case DeclSpec::TST_fract: return "_Fract"; case DeclSpec::TST_float16: return "_Float16"; case DeclSpec::TST_float128: return "__float128"; case DeclSpec::TST_bool: return Policy.Bool ? "bool" : "_Bool"; @@ -763,6 +765,19 @@ return false; } +bool DeclSpec::SetTypeSpecSat(bool isSat, SourceLocation Loc, + const char *&PrevSpec, unsigned &DiagID) { + // Cannot set twice + if (TypeSpecSat) { + DiagID = diag::warn_duplicate_declspec; + PrevSpec = "_Sat"; + return true; + } + TypeSpecSat = isSat; + TSSatLoc = Loc; + return false; +} + bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy) { @@ -1098,13 +1113,22 @@ } } + // Only fixed point types can be saturated + if (TypeSpecSat) { + if (!(TypeSpecType == TST_accum || TypeSpecType == TST_fract)) { + S.Diag(TSSatLoc, diag::err_invalid_saturation_spec) + << getSpecifierName((TST)TypeSpecType, Policy); + TypeSpecSat = false; + } + } + // signed/unsigned are only valid with int/char/wchar_t/_Accum. if (TypeSpecSign != TSS_unspecified) { if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // unsigned -> unsigned int, signed -> signed int. else if (TypeSpecType != TST_int && TypeSpecType != TST_int128 && TypeSpecType != TST_char && TypeSpecType != TST_wchar && - TypeSpecType != TST_accum) { + TypeSpecType != TST_accum && TypeSpecType != TST_fract) { S.Diag(TSSLoc, diag::err_invalid_sign_spec) << getSpecifierName((TST)TypeSpecType, Policy); // signed double -> double. @@ -1112,6 +1136,9 @@ } } + bool is_fixed_point_type = + (TypeSpecType == TST_accum || TypeSpecType == TST_fract); + // Validate the width of the type. switch (TypeSpecWidth) { case TSW_unspecified: break; @@ -1120,7 +1147,7 @@ if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // short -> short int, long long -> long long int. else if (!(TypeSpecType == TST_int || - (TypeSpecType == TST_accum && TypeSpecWidth != TSW_longlong))) { + (is_fixed_point_type && TypeSpecWidth != TSW_longlong))) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; @@ -1131,7 +1158,7 @@ if (TypeSpecType == TST_unspecified) TypeSpecType = TST_int; // long -> long int. else if (TypeSpecType != TST_int && TypeSpecType != TST_double && - TypeSpecType != TST_accum) { + TypeSpecType != TST_accum && TypeSpecType != TST_fract) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -830,6 +830,7 @@ case TST_float: case TST_double: case TST_Accum: + case TST_Fract: case TST_Float16: case TST_float128: case TST_bool: Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1393,37 +1393,150 @@ break; } - if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { - switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_short: - Result = Context.ShortAccumTy; - break; - case DeclSpec::TSW_unspecified: - Result = Context.AccumTy; - break; - case DeclSpec::TSW_long: - Result = Context.LongAccumTy; - break; - case DeclSpec::TSW_longlong: - // Unreachable b/c this is caught in final analysis of the DeclSpec. - llvm_unreachable("Unable to specify long long as _Accum width"); - break; + if (!DS.isTypeSpecSat()) { + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.ShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.AccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.LongAccumTy; + break; + case DeclSpec::TSW_longlong: + // Unreachable b/c this is caught in final analysis of the DeclSpec. + llvm_unreachable("Unable to specify long long as _Accum width"); + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.UnsignedShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.UnsignedAccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.UnsignedLongAccumTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable("Unable to specify long long as _Accum width"); + break; + } } } else { - switch (DS.getTypeSpecWidth()) { - case DeclSpec::TSW_short: - Result = Context.UnsignedShortAccumTy; - break; - case DeclSpec::TSW_unspecified: - Result = Context.UnsignedAccumTy; - break; - case DeclSpec::TSW_long: - Result = Context.UnsignedLongAccumTy; - break; - case DeclSpec::TSW_longlong: - // TODO: Replace with diag - llvm_unreachable("Unable to specify long long as _Accum width"); - break; + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.SatShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.SatAccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.SatLongAccumTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable( + "Unable to specify long long as saturated _Accum width"); + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.SatUnsignedShortAccumTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.SatUnsignedAccumTy; + break; + case DeclSpec::TSW_long: + Result = Context.SatUnsignedLongAccumTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable( + "Unable to specify long long as saturated _Accum width"); + break; + } + } + } + break; + } + case DeclSpec::TST_fract: { + if (S.getLangOpts().CPlusPlus) { + S.Diag(DS.getTypeSpecTypeLoc(), diag::err_fixed_point_only_allowed_in_c); + Result = Context.ShortFractTy; + break; + } + + if (!DS.isTypeSpecSat()) { + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.ShortFractTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.FractTy; + break; + case DeclSpec::TSW_long: + Result = Context.LongFractTy; + break; + case DeclSpec::TSW_longlong: + // Unreachable b/c this is caught in final analysis of the DeclSpec. + llvm_unreachable("Unable to specify long long as _Fract width"); + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.UnsignedShortFractTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.UnsignedFractTy; + break; + case DeclSpec::TSW_long: + Result = Context.UnsignedLongFractTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable("Unable to specify long long as _Fract width"); + break; + } + } + } else { + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.SatShortFractTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.SatFractTy; + break; + case DeclSpec::TSW_long: + Result = Context.SatLongFractTy; + break; + case DeclSpec::TSW_longlong: + // Unreachable b/c this is caught in final analysis of the DeclSpec. + llvm_unreachable( + "Unable to specify long long as saturated _Fract width"); + break; + } + } else { + switch (DS.getTypeSpecWidth()) { + case DeclSpec::TSW_short: + Result = Context.SatUnsignedShortFractTy; + break; + case DeclSpec::TSW_unspecified: + Result = Context.SatUnsignedFractTy; + break; + case DeclSpec::TSW_long: + Result = Context.SatUnsignedLongFractTy; + break; + case DeclSpec::TSW_longlong: + llvm_unreachable( + "Unable to specify long long as saturated _Fract width"); + break; + } } } break; Index: lib/Serialization/ASTCommon.cpp =================================================================== --- lib/Serialization/ASTCommon.cpp +++ lib/Serialization/ASTCommon.cpp @@ -109,6 +109,60 @@ case BuiltinType::ULongAccum: ID = PREDEF_TYPE_ULONG_ACCUM_ID; break; + case BuiltinType::ShortFract: + ID = PREDEF_TYPE_SHORT_FRACT_ID; + break; + case BuiltinType::Fract: + ID = PREDEF_TYPE_FRACT_ID; + break; + case BuiltinType::LongFract: + ID = PREDEF_TYPE_LONG_FRACT_ID; + break; + case BuiltinType::UShortFract: + ID = PREDEF_TYPE_USHORT_FRACT_ID; + break; + case BuiltinType::UFract: + ID = PREDEF_TYPE_UFRACT_ID; + break; + case BuiltinType::ULongFract: + ID = PREDEF_TYPE_ULONG_FRACT_ID; + break; + case BuiltinType::SatShortAccum: + ID = PREDEF_TYPE_SAT_SHORT_ACCUM_ID; + break; + case BuiltinType::SatAccum: + ID = PREDEF_TYPE_SAT_ACCUM_ID; + break; + case BuiltinType::SatLongAccum: + ID = PREDEF_TYPE_SAT_LONG_ACCUM_ID; + break; + case BuiltinType::SatUShortAccum: + ID = PREDEF_TYPE_SAT_USHORT_ACCUM_ID; + break; + case BuiltinType::SatUAccum: + ID = PREDEF_TYPE_SAT_UACCUM_ID; + break; + case BuiltinType::SatULongAccum: + ID = PREDEF_TYPE_SAT_ULONG_ACCUM_ID; + break; + case BuiltinType::SatShortFract: + ID = PREDEF_TYPE_SAT_SHORT_FRACT_ID; + break; + case BuiltinType::SatFract: + ID = PREDEF_TYPE_SAT_FRACT_ID; + break; + case BuiltinType::SatLongFract: + ID = PREDEF_TYPE_SAT_LONG_FRACT_ID; + break; + case BuiltinType::SatUShortFract: + ID = PREDEF_TYPE_SAT_USHORT_FRACT_ID; + break; + case BuiltinType::SatUFract: + ID = PREDEF_TYPE_SAT_UFRACT_ID; + break; + case BuiltinType::SatULongFract: + ID = PREDEF_TYPE_SAT_ULONG_FRACT_ID; + break; case BuiltinType::Float16: ID = PREDEF_TYPE_FLOAT16_ID; break; Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6834,6 +6834,60 @@ case PREDEF_TYPE_ULONG_ACCUM_ID: T = Context.UnsignedLongAccumTy; break; + case PREDEF_TYPE_SHORT_FRACT_ID: + T = Context.ShortFractTy; + break; + case PREDEF_TYPE_FRACT_ID: + T = Context.FractTy; + break; + case PREDEF_TYPE_LONG_FRACT_ID: + T = Context.LongFractTy; + break; + case PREDEF_TYPE_USHORT_FRACT_ID: + T = Context.UnsignedShortFractTy; + break; + case PREDEF_TYPE_UFRACT_ID: + T = Context.UnsignedFractTy; + break; + case PREDEF_TYPE_ULONG_FRACT_ID: + T = Context.UnsignedLongFractTy; + break; + case PREDEF_TYPE_SAT_SHORT_ACCUM_ID: + T = Context.SatShortAccumTy; + break; + case PREDEF_TYPE_SAT_ACCUM_ID: + T = Context.SatAccumTy; + break; + case PREDEF_TYPE_SAT_LONG_ACCUM_ID: + T = Context.SatLongAccumTy; + break; + case PREDEF_TYPE_SAT_USHORT_ACCUM_ID: + T = Context.SatUnsignedShortAccumTy; + break; + case PREDEF_TYPE_SAT_UACCUM_ID: + T = Context.SatUnsignedAccumTy; + break; + case PREDEF_TYPE_SAT_ULONG_ACCUM_ID: + T = Context.SatUnsignedLongAccumTy; + break; + case PREDEF_TYPE_SAT_SHORT_FRACT_ID: + T = Context.SatShortFractTy; + break; + case PREDEF_TYPE_SAT_FRACT_ID: + T = Context.SatFractTy; + break; + case PREDEF_TYPE_SAT_LONG_FRACT_ID: + T = Context.SatLongFractTy; + break; + case PREDEF_TYPE_SAT_USHORT_FRACT_ID: + T = Context.SatUnsignedShortFractTy; + break; + case PREDEF_TYPE_SAT_UFRACT_ID: + T = Context.SatUnsignedFractTy; + break; + case PREDEF_TYPE_SAT_ULONG_FRACT_ID: + T = Context.SatUnsignedLongFractTy; + break; case PREDEF_TYPE_FLOAT16_ID: T = Context.Float16Ty; break; Index: test/Frontend/accum.c =================================================================== --- test/Frontend/accum.c +++ /dev/null @@ -1,26 +0,0 @@ -// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace - -/* Various contexts where type _Accum can appear. */ - -// Primary fixed point types -signed short _Accum s_short_accum; -signed _Accum s_accum; -signed long _Accum s_long_accum; -unsigned short _Accum u_short_accum; -unsigned _Accum u_accum; -unsigned long _Accum u_long_accum; - -// Aliased fixed point types -short _Accum short_accum; -_Accum accum; -long _Accum long_accum; - -// CHECK: |-VarDecl {{.*}} s_short_accum 'short _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum' -// CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum' -// CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum' -// CHECK-NEXT: `-VarDecl {{.*}} long_accum 'long _Accum' Index: test/Frontend/accum_errors.c =================================================================== --- test/Frontend/accum_errors.c +++ /dev/null @@ -1,4 +0,0 @@ -// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s - -long long _Accum longlong_accum; // expected-error{{'long long _Accum' is invalid}} -unsigned long long _Accum u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} Index: test/Frontend/accum_errors.cpp =================================================================== --- test/Frontend/accum_errors.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 -x c++ %s -verify - -// Name namgling is not provided for fixed point types in c++ - -signed short _Accum s_short_accum; // expected-error{{Fixed point types are only allowed in C}} -signed _Accum s_accum; // expected-error{{Fixed point types are only allowed in C}} -signed long _Accum s_long_accum; // expected-error{{Fixed point types are only allowed in C}} -unsigned short _Accum u_short_accum; // expected-error{{Fixed point types are only allowed in C}} -unsigned _Accum u_accum; // expected-error{{Fixed point types are only allowed in C}} -unsigned long _Accum u_long_accum; // expected-error{{Fixed point types are only allowed in C}} - -short _Accum short_accum; // expected-error{{Fixed point types are only allowed in C}} -_Accum accum; // expected-error{{Fixed point types are only allowed in C}} -long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}} Index: test/Frontend/fixed_point.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point.c @@ -0,0 +1,82 @@ +// RUN: %clang -cc1 -x c -ast-dump %s | FileCheck %s --strict-whitespace + +// Primary fixed point types +signed short _Accum s_short_accum; +signed _Accum s_accum; +signed long _Accum s_long_accum; +unsigned short _Accum u_short_accum; +unsigned _Accum u_accum; +unsigned long _Accum u_long_accum; +signed short _Fract s_short_fract; +signed _Fract s_fract; +signed long _Fract s_long_fract; +unsigned short _Fract u_short_fract; +unsigned _Fract u_fract; +unsigned long _Fract u_long_fract; + +// Aliased fixed point types +short _Accum short_accum; +_Accum accum; +long _Accum long_accum; +short _Fract short_fract; +_Fract fract; +long _Fract long_fract; + +// Saturated fixed point types +_Sat signed short _Accum sat_s_short_accum; +_Sat signed _Accum sat_s_accum; +_Sat signed long _Accum sat_s_long_accum; +_Sat unsigned short _Accum sat_u_short_accum; +_Sat unsigned _Accum sat_u_accum; +_Sat unsigned long _Accum sat_u_long_accum; +_Sat signed short _Fract sat_s_short_fract; +_Sat signed _Fract sat_s_fract; +_Sat signed long _Fract sat_s_long_fract; +_Sat unsigned short _Fract sat_u_short_fract; +_Sat unsigned _Fract sat_u_fract; +_Sat unsigned long _Fract sat_u_long_fract; + +// Aliased saturated fixed point types +_Sat short _Accum sat_short_accum; +_Sat _Accum sat_accum; +_Sat long _Accum sat_long_accum; +_Sat short _Fract sat_short_fract; +_Sat _Fract sat_fract; +_Sat long _Fract sat_long_fract; + +//CHECK: |-VarDecl {{.*}} s_short_accum 'short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} s_accum '_Accum' +//CHECK-NEXT: |-VarDecl {{.*}} s_long_accum 'long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} u_short_accum 'unsigned short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} u_accum 'unsigned _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} u_long_accum 'unsigned long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} s_short_fract 'short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} s_fract '_Fract' +//CHECK-NEXT: |-VarDecl {{.*}} s_long_fract 'long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} u_short_fract 'unsigned short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} u_fract 'unsigned _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} u_long_fract 'unsigned long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} short_accum 'short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} accum '_Accum' +//CHECK-NEXT: |-VarDecl {{.*}} long_accum 'long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} short_fract 'short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} fract '_Fract' +//CHECK-NEXT: |-VarDecl {{.*}} long_fract 'long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_short_accum '_Sat short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_accum '_Sat _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_long_accum '_Sat long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_short_accum '_Sat unsigned short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_accum '_Sat unsigned _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_long_accum '_Sat unsigned long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_short_fract '_Sat short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_fract '_Sat _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_s_long_fract '_Sat long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_short_fract '_Sat unsigned short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_fract '_Sat unsigned _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_u_long_fract '_Sat unsigned long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_short_accum '_Sat short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_accum '_Sat _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_long_accum '_Sat long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sat_short_fract '_Sat short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sat_fract '_Sat _Fract' +//CHECK-NEXT: `-VarDecl {{.*}} sat_long_fract '_Sat long _Fract' Index: test/Frontend/fixed_point_errors.c =================================================================== --- /dev/null +++ test/Frontend/fixed_point_errors.c @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -x c -fsyntax-only -verify -pedantic %s + +long long _Accum longlong_accum; // expected-error{{'long long _Accum' is invalid}} +unsigned long long _Accum u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +long long _Fract longlong_fract; // expected-error{{'long long _Fract' is invalid}} +unsigned long long _Fract u_longlong_fract; // expected-error{{'long long _Fract' is invalid}} + +_Sat int i; // expected-error{{'int' cannot be saturated. Only _Fract and _Accum can.}} +_Sat _Sat _Fract fract; // expected-warning{{duplicate '_Sat' declaration specifier}} + +_Sat long long _Accum sat_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +_Sat unsigned long long _Accum sat_u_longlong_accum; // expected-error{{'long long _Accum' is invalid}} +_Sat long long _Fract sat_longlong_fract; // expected-error{{'long long _Fract' is invalid}} +_Sat unsigned long long _Fract sat_u_longlong_fract; // expected-error{{'long long _Fract' is invalid}} Index: test/Frontend/fixed_point_errors.cpp =================================================================== --- /dev/null +++ test/Frontend/fixed_point_errors.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -x c++ %s -verify + +// Name namgling is not provided for fixed point types in c++ + +signed short _Accum s_short_accum; // expected-error{{Fixed point types are only allowed in C}} +signed _Accum s_accum; // expected-error{{Fixed point types are only allowed in C}} +signed long _Accum s_long_accum; // expected-error{{Fixed point types are only allowed in C}} +unsigned short _Accum u_short_accum; // expected-error{{Fixed point types are only allowed in C}} +unsigned _Accum u_accum; // expected-error{{Fixed point types are only allowed in C}} +unsigned long _Accum u_long_accum; // expected-error{{Fixed point types are only allowed in C}} + +short _Accum short_accum; // expected-error{{Fixed point types are only allowed in C}} +_Accum accum; // expected-error{{Fixed point types are only allowed in C}} +long _Accum long_accum; // expected-error{{Fixed point types are only allowed in C}}