leonardchan updated this revision to Diff 148918. leonardchan marked 4 inline comments as done.
Repository: rC Clang https://reviews.llvm.org/D46911 Files: include/clang/AST/ASTContext.h include/clang/AST/BuiltinTypes.def include/clang/AST/Type.h include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/Specifiers.h include/clang/Basic/TargetInfo.h include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h include/clang/Serialization/ASTBitCodes.h lib/AST/ASTContext.cpp lib/AST/ExprConstant.cpp lib/AST/ItaniumMangle.cpp lib/AST/MicrosoftMangle.cpp lib/AST/NSAPI.cpp lib/AST/Type.cpp lib/AST/TypeLoc.cpp lib/Analysis/PrintfFormatString.cpp lib/Basic/TargetInfo.cpp lib/CodeGen/CGDebugInfo.cpp lib/CodeGen/CodeGenTypes.cpp lib/CodeGen/ItaniumCXXABI.cpp lib/Index/USRGeneration.cpp lib/Parse/ParseDecl.cpp lib/Sema/DeclSpec.cpp lib/Sema/SemaTemplateVariadic.cpp lib/Sema/SemaType.cpp lib/Serialization/ASTCommon.cpp lib/Serialization/ASTReader.cpp test/Frontend/fixed_point.c test/Frontend/fixed_point_bit_widths.c test/Frontend/fixed_point_errors.c
Index: test/Frontend/fixed_point_errors.c =================================================================== --- test/Frontend/fixed_point_errors.c +++ test/Frontend/fixed_point_errors.c @@ -5,6 +5,14 @@ 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 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}} + /* Although _Complex types work with floating point numbers, the extension * provides no info for complex fixed point types. */ @@ -19,9 +27,53 @@ _Complex _Accum cmplx_s_accum; // expected-error{{'_Complex _Accum' is invalid}} _Complex long _Accum cmplx_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex signed short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned short _Fract cmplx_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned _Fract cmplx_u_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned long _Fract cmplx_u_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex short _Fract cmplx_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex _Fract cmplx_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex long _Fract cmplx_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}} + +_Complex _Sat signed short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat signed _Accum cmplx_sat_s_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat signed long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned short _Accum cmplx_sat_u_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned _Accum cmplx_sat_u_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat unsigned long _Accum cmplx_sat_u_long_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat short _Accum cmplx_sat_s_short_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat _Accum cmplx_sat_s_accum; // expected-error{{'_Complex _Accum' is invalid}} +_Complex _Sat long _Accum cmplx_sat_s_long_accum; // expected-error{{'_Complex _Accum' is invalid}} + +_Complex signed short _Fract cmplx_sat_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed _Fract cmplx_sat_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex signed long _Fract cmplx_sat_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned short _Fract cmplx_sat_u_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned _Fract cmplx_sat_u_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex unsigned long _Fract cmplx_sat_u_long_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex short _Fract cmplx_sat_s_short_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex _Fract cmplx_sat_s_fract; // expected-error{{'_Complex _Fract' is invalid}} +_Complex long _Fract cmplx_sat_s_long_fract; // expected-error{{'_Complex _Fract' is invalid}} + /* Bad combinations */ float _Accum f_accum; // expected-error{{cannot combine with previous 'float' declaration specifier}} double _Accum d_accum; // expected-error{{cannot combine with previous 'double' declaration specifier}} _Bool _Accum b_accum; // expected-error{{cannot combine with previous '_Bool' declaration specifier}} char _Accum c_accum; // expected-error{{cannot combine with previous 'char' declaration specifier}} int _Accum i_accum; // expected-error{{cannot combine with previous 'int' declaration specifier}} + +float _Fract f_fract; // expected-error{{cannot combine with previous 'float' declaration specifier}} +double _Fract d_fract; // expected-error{{cannot combine with previous 'double' declaration specifier}} +_Bool _Fract b_fract; // expected-error{{cannot combine with previous '_Bool' declaration specifier}} +char _Fract c_fract; // expected-error{{cannot combine with previous 'char' declaration specifier}} +int _Fract i_fract; // expected-error{{cannot combine with previous 'int' declaration specifier}} + +/* Bad saturated combinations */ +_Sat float f; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'float'}} +_Sat double d; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'double'}} +_Sat _Bool b; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not '_Bool'}} +_Sat char c; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'char'}} +_Sat int i; // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'int'}} +_Sat _Sat _Fract fract; // expected-warning{{duplicate '_Sat' declaration specifier}} Index: test/Frontend/fixed_point_bit_widths.c =================================================================== --- test/Frontend/fixed_point_bit_widths.c +++ test/Frontend/fixed_point_bit_widths.c @@ -1,43 +1,193 @@ // RUN: %clang -x c -ffixed-point -S -emit-llvm -o - %s | FileCheck %s +/* Primary signed _Accum */ + int size_SsA = sizeof(signed short _Accum); int size_SA = sizeof(signed _Accum); int size_SlA = sizeof(signed long _Accum); int align_SsA = __alignof(signed short _Accum); int align_SA = __alignof(signed _Accum); int align_SlA = __alignof(signed long _Accum); -int size_UsA = sizeof(unsigned short _Accum); -int size_UA = sizeof(unsigned _Accum); -int size_UlA = sizeof(unsigned long _Accum); -int align_UsA = __alignof(unsigned short _Accum); -int align_UA = __alignof(unsigned _Accum); -int align_UlA = __alignof(unsigned long _Accum); - -int size_sA = sizeof(short _Accum); -int size_A = sizeof(_Accum); -int size_lA = sizeof(long _Accum); -int align_sA = __alignof(short _Accum); -int align_A = __alignof(_Accum); -int align_lA = __alignof(long _Accum); - // CHECK: @size_SsA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @size_SA = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @size_SlA = dso_local global i{{[0-9]+}} 8 // CHECK-NEXT: @align_SsA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @align_SA = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @align_SlA = dso_local global i{{[0-9]+}} 8 +/* Primary unsigned _Accum */ + +int size_UsA = sizeof(unsigned short _Accum); +int size_UA = sizeof(unsigned _Accum); +int size_UlA = sizeof(unsigned long _Accum); +int align_UsA = __alignof(unsigned short _Accum); +int align_UA = __alignof(unsigned _Accum); +int align_UlA = __alignof(unsigned long _Accum); + // CHECK-NEXT: @size_UsA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @size_UA = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @size_UlA = dso_local global i{{[0-9]+}} 8 // CHECK-NEXT: @align_UsA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @align_UA = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @align_UlA = dso_local global i{{[0-9]+}} 8 +/* Primary signed _Fract */ + +int size_SsF = sizeof(signed short _Fract); +int size_SF = sizeof(signed _Fract); +int size_SlF = sizeof(signed long _Fract); +int align_SsF = __alignof(signed short _Fract); +int align_SF = __alignof(signed _Fract); +int align_SlF = __alignof(signed long _Fract); + +// CHECK-NEXT: @size_SsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SlF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SlF = dso_local global i{{[0-9]+}} 8 + +/* Primary unsigned _Fract */ + +int size_UsF = sizeof(unsigned short _Fract); +int size_UF = sizeof(unsigned _Fract); +int size_UlF = sizeof(unsigned long _Fract); +int align_UsF = __alignof(unsigned short _Fract); +int align_UF = __alignof(unsigned _Fract); +int align_UlF = __alignof(unsigned long _Fract); + +// CHECK-NEXT: @size_UsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_UF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_UlF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_UsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_UF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_UlF = dso_local global i{{[0-9]+}} 8 + +/* Aliased _Accum */ + +int size_sA = sizeof(short _Accum); +int size_A = sizeof(_Accum); +int size_lA = sizeof(long _Accum); +int align_sA = __alignof(short _Accum); +int align_A = __alignof(_Accum); +int align_lA = __alignof(long _Accum); + // CHECK-NEXT: @size_sA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @size_A = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @size_lA = dso_local global i{{[0-9]+}} 8 // CHECK-NEXT: @align_sA = dso_local global i{{[0-9]+}} 2 // CHECK-NEXT: @align_A = dso_local global i{{[0-9]+}} 4 // CHECK-NEXT: @align_lA = dso_local global i{{[0-9]+}} 8 + +/* Aliased _Fract */ + +int size_sF = sizeof(short _Fract); +int size_F = sizeof(_Fract); +int size_lF = sizeof(long _Fract); +int align_sF = __alignof(short _Fract); +int align_F = __alignof(_Fract); +int align_lF = __alignof(long _Fract); + +// CHECK-NEXT: @size_sF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_F = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_lF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_sF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_F = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_lF = dso_local global i{{[0-9]+}} 8 + +/* Saturated signed _Accum */ + +int size_SatSsA = sizeof(_Sat signed short _Accum); +int size_SatSA = sizeof(_Sat signed _Accum); +int size_SatSlA = sizeof(_Sat signed long _Accum); +int align_SatSsA = __alignof(_Sat signed short _Accum); +int align_SatSA = __alignof(_Sat signed _Accum); +int align_SatSlA = __alignof(_Sat signed long _Accum); + +// CHECK: @size_SatSsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatSA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatSlA = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatSsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatSA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatSlA = dso_local global i{{[0-9]+}} 8 + +/* Saturated unsigned _Accum */ + +int size_SatUsA = sizeof(_Sat unsigned short _Accum); +int size_SatUA = sizeof(_Sat unsigned _Accum); +int size_SatUlA = sizeof(_Sat unsigned long _Accum); +int align_SatUsA = __alignof(_Sat unsigned short _Accum); +int align_SatUA = __alignof(_Sat unsigned _Accum); +int align_SatUlA = __alignof(_Sat unsigned long _Accum); + +// CHECK-NEXT: @size_SatUsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatUA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatUlA = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatUsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatUA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatUlA = dso_local global i{{[0-9]+}} 8 + +/* Saturated signed _Fract */ + +int size_SatSsF = sizeof(_Sat signed short _Fract); +int size_SatSF = sizeof(_Sat signed _Fract); +int size_SatSlF = sizeof(_Sat signed long _Fract); +int align_SatSsF = __alignof(_Sat signed short _Fract); +int align_SatSF = __alignof(_Sat signed _Fract); +int align_SatSlF = __alignof(_Sat signed long _Fract); + +// CHECK-NEXT: @size_SatSsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatSF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatSlF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatSsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatSF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatSlF = dso_local global i{{[0-9]+}} 8 + +/* Saturated unsigned _Fract */ + +int size_SatUsF = sizeof(_Sat unsigned short _Fract); +int size_SatUF = sizeof(_Sat unsigned _Fract); +int size_SatUlF = sizeof(_Sat unsigned long _Fract); +int align_SatUsF = __alignof(_Sat unsigned short _Fract); +int align_SatUF = __alignof(_Sat unsigned _Fract); +int align_SatUlF = __alignof(_Sat unsigned long _Fract); + +// CHECK-NEXT: @size_SatUsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatUF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatUlF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatUsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatUF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatUlF = dso_local global i{{[0-9]+}} 8 + +/* Aliased saturated signed _Accum */ + +int size_SatsA = sizeof(_Sat short _Accum); +int size_SatA = sizeof(_Sat _Accum); +int size_SatlA = sizeof(_Sat long _Accum); +int align_SatsA = __alignof(_Sat short _Accum); +int align_SatA = __alignof(_Sat _Accum); +int align_SatlA = __alignof(_Sat long _Accum); + +// CHECK-NEXT: @size_SatsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatlA = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatsA = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatA = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatlA = dso_local global i{{[0-9]+}} 8 + +/* Aliased saturated _Fract */ + +int size_SatsF = sizeof(_Sat short _Fract); +int size_SatF = sizeof(_Sat _Fract); +int size_SatlF = sizeof(_Sat long _Fract); +int align_SatsF = __alignof(_Sat short _Fract); +int align_SatF = __alignof(_Sat _Fract); +int align_SatlF = __alignof(_Sat long _Fract); + +// CHECK-NEXT: @size_SatsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @size_SatF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @size_SatlF = dso_local global i{{[0-9]+}} 8 +// CHECK-NEXT: @align_SatsF = dso_local global i{{[0-9]+}} 2 +// CHECK-NEXT: @align_SatF = dso_local global i{{[0-9]+}} 4 +// CHECK-NEXT: @align_SatlF = dso_local global i{{[0-9]+}} 8 Index: test/Frontend/fixed_point.c =================================================================== --- test/Frontend/fixed_point.c +++ test/Frontend/fixed_point.c @@ -9,21 +9,79 @@ 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; -// 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' +// 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' #define MIX_TYPE_SPEC(SPEC, SIGN, SIZE, ID) \ SPEC SIGN SIZE _Accum ID; \ @@ -54,4 +112,128 @@ // CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum 'const short _Accum' // CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum2 'const short _Accum' // CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum3 'const short _Accum' -// CHECK-NEXT: `-VarDecl {{.*}} const_s_short_accum4 'const short _Accum' +// CHECK-NEXT: |-VarDecl {{.*}} const_s_short_accum4 'const short _Accum' + +/* Typedefs */ + +// Primary fixed point types +typedef signed short _Accum SsA_t; +typedef signed _Accum SA_t; +typedef signed long _Accum SlA_t; +typedef unsigned short _Accum UsA_t; +typedef unsigned _Accum UA_t; +typedef unsigned long _Accum UlA_t; +typedef signed short _Fract SsF_t; +typedef signed _Fract SF_t; +typedef signed long _Fract SlF_t; +typedef unsigned short _Fract UsF_t; +typedef unsigned _Fract UF_t; +typedef unsigned long _Fract UlF_t; + +// Aliased fixed point types +typedef short _Accum sA_t; +typedef _Accum A_t; +typedef long _Accum lA_t; +typedef short _Fract sF_t; +typedef _Fract F_t; +typedef long _Fract lF_t; + +// Saturated fixed point types +typedef _Sat signed short _Accum SatSsA_t; +typedef _Sat signed _Accum SatSA_t; +typedef _Sat signed long _Accum SatSlA_t; +typedef _Sat unsigned short _Accum SatUsA_t; +typedef _Sat unsigned _Accum SatUA_t; +typedef _Sat unsigned long _Accum SatUlA_t; +typedef _Sat signed short _Fract SatSsF_t; +typedef _Sat signed _Fract SatSF_t; +typedef _Sat signed long _Fract SatSlF_t; +typedef _Sat unsigned short _Fract SatUsF_t; +typedef _Sat unsigned _Fract SatUF_t; +typedef _Sat unsigned long _Fract SatUlF_t; + +// Aliased saturated fixed point types +typedef _Sat short _Accum SatsA_t; +typedef _Sat _Accum SatA_t; +typedef _Sat long _Accum SatlA_t; +typedef _Sat short _Fract SatsF_t; +typedef _Sat _Fract SatF_t; +typedef _Sat long _Fract SatlF_t; + +SsA_t SsA_type; +SA_t SA_type; +SlA_t SlA_type; +UsA_t UsA_type; +UA_t UA_type; +UlA_t UlA_type; +SsF_t SsF_type; +SF_t SF_type; +SlF_t SlF_type; +UsF_t UsF_type; +UF_t UF_type; +UlF_t UlF_type; + +sA_t sA_type; +A_t A_type; +lA_t lA_type; +sF_t sF_type; +F_t F_type; +lF_t lF_type; + +SatSsA_t SatSsA_type; +SatSA_t SatSA_type; +SatSlA_t SatSlA_type; +SatUsA_t SatUsA_type; +SatUA_t SatUA_type; +SatUlA_t SatUlA_type; +SatSsF_t SatSsF_type; +SatSF_t SatSF_type; +SatSlF_t SatSlF_type; +SatUsF_t SatUsF_type; +SatUF_t SatUF_type; +SatUlF_t SatUlF_type; + +SatsA_t SatsA_type; +SatA_t SatA_type; +SatlA_t SatlA_type; +SatsF_t SatsF_type; +SatF_t SatF_type; +SatlF_t SatlF_type; + +//CHECK: |-VarDecl {{.*}} SsA_type 'SsA_t':'short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SA_type 'SA_t':'_Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SlA_type 'SlA_t':'long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} UsA_type 'UsA_t':'unsigned short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} UA_type 'UA_t':'unsigned _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} UlA_type 'UlA_t':'unsigned long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SsF_type 'SsF_t':'short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SF_type 'SF_t':'_Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SlF_type 'SlF_t':'long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} UsF_type 'UsF_t':'unsigned short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} UF_type 'UF_t':'unsigned _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} UlF_type 'UlF_t':'unsigned long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} sA_type 'sA_t':'short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} A_type 'A_t':'_Accum' +//CHECK-NEXT: |-VarDecl {{.*}} lA_type 'lA_t':'long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} sF_type 'sF_t':'short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} F_type 'F_t':'_Fract' +//CHECK-NEXT: |-VarDecl {{.*}} lF_type 'lF_t':'long _Fract' + +//CHECK-NEXT: |-VarDecl {{.*}} SatSsA_type 'SatSsA_t':'_Sat short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatSA_type 'SatSA_t':'_Sat _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatSlA_type 'SatSlA_t':'_Sat long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatUsA_type 'SatUsA_t':'_Sat unsigned short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatUA_type 'SatUA_t':'_Sat unsigned _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatUlA_type 'SatUlA_t':'_Sat unsigned long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatSsF_type 'SatSsF_t':'_Sat short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatSF_type 'SatSF_t':'_Sat _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatSlF_type 'SatSlF_t':'_Sat long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatUsF_type 'SatUsF_t':'_Sat unsigned short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatUF_type 'SatUF_t':'_Sat unsigned _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatUlF_type 'SatUlF_t':'_Sat unsigned long _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatsA_type 'SatsA_t':'_Sat short _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatA_type 'SatA_t':'_Sat _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatlA_type 'SatlA_t':'_Sat long _Accum' +//CHECK-NEXT: |-VarDecl {{.*}} SatsF_type 'SatsF_t':'_Sat short _Fract' +//CHECK-NEXT: |-VarDecl {{.*}} SatF_type 'SatF_t':'_Sat _Fract' +//CHECK-NEXT: `-VarDecl {{.*}} SatlF_type 'SatlF_t':'_Sat long _Fract' Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -6837,6 +6837,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: 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/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1392,38 +1392,51 @@ break; } case DeclSpec::TST_accum: { - 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; - } + 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; + } + + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) + Result = fixedpoint::getCorrespondingSignedType(Context, Result); + + if (DS.isTypeSpecSat()) + Result = fixedpoint::getCorrespondingSaturatedType(Context, Result); + + break; + } + case DeclSpec::TST_fract: { + 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; } + + if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) + Result = fixedpoint::getCorrespondingSignedType(Context, Result); + + if (DS.isTypeSpecSat()) + Result = fixedpoint::getCorrespondingSaturatedType(Context, Result); + break; } case DeclSpec::TST_int128: Index: lib/Sema/SemaTemplateVariadic.cpp =================================================================== --- lib/Sema/SemaTemplateVariadic.cpp +++ lib/Sema/SemaTemplateVariadic.cpp @@ -831,6 +831,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/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -340,6 +340,7 @@ case TST_decimal64: case TST_double: case TST_Accum: + case TST_Fract: case TST_Float16: case TST_float128: case TST_enum: @@ -512,6 +513,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"; @@ -767,6 +769,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) { @@ -1102,29 +1117,41 @@ } } + // 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. TypeSpecSign = TSS_unspecified; } } + bool IsFixedPointType = + TypeSpecType == TST_accum || TypeSpecType == TST_fract; + // Validate the width of the type. switch (TypeSpecWidth) { case TSW_unspecified: break; case TSW_short: // short int case TSW_longlong: // long long int 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))) { + (IsFixedPointType && TypeSpecWidth != TSW_longlong))) { S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec) << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy); TypeSpecType = TST_int; @@ -1135,7 +1162,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/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -2876,6 +2876,20 @@ return false; } +// Choose the apprpriate diagnostic error for why fixed point types are +// disabled, set the previous specifier, and mark as invalid. +static void SetupFixedPointError(const LangOptions &LangOpts, + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid) { + assert(!LangOpts.FixedPoint); + if (LangOpts.CPlusPlus) + DiagID = diag::err_fixed_point_only_allowed_in_c; + else + DiagID = diag::err_fixed_point_not_enabled; + PrevSpec = ""; // Not used by diagnostic + isInvalid = true; +} + /// ParseDeclarationSpecifiers /// declaration-specifiers: [C99 6.7] /// storage-class-specifier declaration-specifiers[opt] @@ -3582,17 +3596,27 @@ break; case tok::kw__Accum: if (!getLangOpts().FixedPoint) { - if (getLangOpts().CPlusPlus) - DiagID = diag::err_fixed_point_only_allowed_in_c; - else - DiagID = diag::err_fixed_point_not_enabled; - PrevSpec = ""; // Not used by diagnostic - isInvalid = true; + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); } else { isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, DiagID, Policy); } break; + case tok::kw__Fract: + if (!getLangOpts().FixedPoint) { + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); + } else { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, + DiagID, Policy); + } + break; + case tok::kw__Sat: + if (!getLangOpts().FixedPoint) { + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); + } else { + isInvalid = DS.SetTypeSpecSat(/*isSat=*/true, Loc, PrevSpec, DiagID); + } + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -4620,6 +4644,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: @@ -4698,6 +4723,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: @@ -4721,6 +4747,7 @@ case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: + case tok::kw__Sat: // Debugger support. case tok::kw___unknown_anytype: @@ -4857,6 +4884,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: @@ -4878,6 +4906,7 @@ case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: + case tok::kw__Sat: // function-specifier case tok::kw_inline: Index: lib/Index/USRGeneration.cpp =================================================================== --- lib/Index/USRGeneration.cpp +++ lib/Index/USRGeneration.cpp @@ -715,6 +715,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: IgnoreResults = true; return; case BuiltinType::ObjCId: Index: lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- lib/CodeGen/ItaniumCXXABI.cpp +++ lib/CodeGen/ItaniumCXXABI.cpp @@ -2725,6 +2725,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 false; case BuiltinType::Dependent: Index: lib/CodeGen/CodeGenTypes.cpp =================================================================== --- lib/CodeGen/CodeGenTypes.cpp +++ lib/CodeGen/CodeGenTypes.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: ResultType = llvm::IntegerType::get(getLLVMContext(), static_cast<unsigned>(Context.getTypeSize(T))); break; Index: lib/CodeGen/CGDebugInfo.cpp =================================================================== --- lib/CodeGen/CGDebugInfo.cpp +++ lib/CodeGen/CGDebugInfo.cpp @@ -705,11 +705,29 @@ case BuiltinType::ShortAccum: case BuiltinType::Accum: case BuiltinType::LongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: Encoding = llvm::dwarf::DW_ATE_signed_fixed; break; 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: Encoding = llvm::dwarf::DW_ATE_unsigned_fixed; break; } Index: lib/Basic/TargetInfo.cpp =================================================================== --- lib/Basic/TargetInfo.cpp +++ lib/Basic/TargetInfo.cpp @@ -43,6 +43,15 @@ ShortAccumWidth = ShortAccumAlign = 16; AccumWidth = AccumAlign = 32; LongAccumWidth = LongAccumAlign = 64; + ShortFractWidth = ShortFractAlign = 16; + FractWidth = FractAlign = 32; + LongFractWidth = LongFractAlign = 64; + SatShortAccumWidth = SatShortAccumAlign = 16; + SatAccumWidth = SatAccumAlign = 32; + SatLongAccumWidth = SatLongAccumAlign = 64; + SatShortFractWidth = SatShortFractAlign = 16; + SatFractWidth = SatFractAlign = 32; + SatLongFractWidth = SatLongFractAlign = 64; SuitableAlign = 64; DefaultAlignForAttributeAligned = 128; MinGlobalAlign = 0; Index: lib/Analysis/PrintfFormatString.cpp =================================================================== --- lib/Analysis/PrintfFormatString.cpp +++ lib/Analysis/PrintfFormatString.cpp @@ -661,6 +661,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/AST/TypeLoc.cpp =================================================================== --- lib/AST/TypeLoc.cpp +++ lib/AST/TypeLoc.cpp @@ -350,6 +350,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/AST/Type.cpp =================================================================== --- lib/AST/Type.cpp +++ lib/AST/Type.cpp @@ -2668,6 +2668,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: @@ -3950,3 +3986,77 @@ CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { return getClass()->getAsCXXRecordDecl()->getMostRecentDecl(); } + +QualType clang::fixedpoint::getCorrespondingSignedType( + const ASTContext &Context, const QualType &Ty) { + assert(Ty->isFixedPointType()); + + if (Ty->isSignedFixedPointType()) return Ty; + + const auto &BT = Ty->getAs<BuiltinType>(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::UShortAccum: + return Context.ShortAccumTy; + case BuiltinType::UAccum: + return Context.AccumTy; + case BuiltinType::ULongAccum: + return Context.LongAccumTy; + case BuiltinType::SatUShortAccum: + return Context.SatShortAccumTy; + case BuiltinType::SatUAccum: + return Context.SatAccumTy; + case BuiltinType::SatULongAccum: + return Context.SatLongAccumTy; + case BuiltinType::UShortFract: + return Context.ShortFractTy; + case BuiltinType::UFract: + return Context.FractTy; + case BuiltinType::ULongFract: + return Context.LongFractTy; + case BuiltinType::SatUShortFract: + return Context.SatShortFractTy; + case BuiltinType::SatUFract: + return Context.SatFractTy; + case BuiltinType::SatULongFract: + return Context.SatLongFractTy; + } +} + +QualType clang::fixedpoint::getCorrespondingSaturatedType( + const ASTContext &Context, const QualType &Ty) { + assert(Ty->isFixedPointType()); + + if (Ty->isSaturatedFixedPointType()) return Ty; + + const auto &BT = Ty->getAs<BuiltinType>(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + return Context.SatShortAccumTy; + case BuiltinType::Accum: + return Context.SatAccumTy; + case BuiltinType::LongAccum: + return Context.SatLongAccumTy; + case BuiltinType::UShortAccum: + return Context.SatUnsignedShortAccumTy; + case BuiltinType::UAccum: + return Context.SatUnsignedAccumTy; + case BuiltinType::ULongAccum: + return Context.SatUnsignedLongAccumTy; + case BuiltinType::ShortFract: + return Context.SatShortFractTy; + case BuiltinType::Fract: + return Context.SatFractTy; + case BuiltinType::LongFract: + return Context.SatLongFractTy; + case BuiltinType::UShortFract: + return Context.SatUnsignedShortFractTy; + case BuiltinType::UFract: + return Context.SatUnsignedFractTy; + case BuiltinType::ULongFract: + return Context.SatUnsignedLongFractTy; + } +} Index: lib/AST/NSAPI.cpp =================================================================== --- lib/AST/NSAPI.cpp +++ lib/AST/NSAPI.cpp @@ -447,6 +447,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/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -1932,6 +1932,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::Char8: case BuiltinType::Float128: { DiagnosticsEngine &Diags = Context.getDiags(); Index: lib/AST/ItaniumMangle.cpp =================================================================== --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -2558,6 +2558,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/ExprConstant.cpp =================================================================== --- lib/AST/ExprConstant.cpp +++ lib/AST/ExprConstant.cpp @@ -7358,6 +7358,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: // GCC does not cover FIXED_POINT_TYPE in its switch stmt and defaults to // no_type_class return GCCTypeClass::None; Index: lib/AST/ASTContext.cpp =================================================================== --- lib/AST/ASTContext.cpp +++ lib/AST/ASTContext.cpp @@ -1135,12 +1135,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); @@ -1808,6 +1826,51 @@ Width = Target->getLongAccumWidth(); Align = Target->getLongAccumAlign(); break; + case BuiltinType::ShortFract: + case BuiltinType::UShortFract: + Width = Target->getShortFractWidth(); + Align = Target->getShortFractAlign(); + break; + case BuiltinType::Fract: + case BuiltinType::UFract: + Width = Target->getFractWidth(); + Align = Target->getFractAlign(); + break; + case BuiltinType::LongFract: + case BuiltinType::ULongFract: + Width = Target->getLongFractWidth(); + Align = Target->getLongFractAlign(); + break; + case BuiltinType::SatShortAccum: + case BuiltinType::SatUShortAccum: + Width = Target->getSatShortAccumWidth(); + Align = Target->getSatShortAccumAlign(); + break; + case BuiltinType::SatAccum: + case BuiltinType::SatUAccum: + Width = Target->getSatAccumWidth(); + Align = Target->getSatAccumAlign(); + break; + case BuiltinType::SatLongAccum: + case BuiltinType::SatULongAccum: + Width = Target->getSatLongAccumWidth(); + Align = Target->getSatLongAccumAlign(); + break; + case BuiltinType::SatShortFract: + case BuiltinType::SatUShortFract: + Width = Target->getSatShortFractWidth(); + Align = Target->getSatShortFractAlign(); + break; + case BuiltinType::SatFract: + case BuiltinType::SatUFract: + Width = Target->getSatFractWidth(); + Align = Target->getSatFractAlign(); + break; + case BuiltinType::SatLongFract: + case BuiltinType::SatULongFract: + Width = Target->getSatLongFractWidth(); + Align = Target->getSatLongFractAlign(); + break; case BuiltinType::Float16: case BuiltinType::Half: Width = Target->getHalfWidth(); @@ -6251,6 +6314,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: // FIXME: potentially need @encodes for these! return ' '; Index: include/clang/Serialization/ASTBitCodes.h =================================================================== --- include/clang/Serialization/ASTBitCodes.h +++ include/clang/Serialization/ASTBitCodes.h @@ -957,6 +957,60 @@ /// \brief The 'unsigned long _Accum' type PREDEF_TYPE_ULONG_ACCUM_ID = 51, + /// \brief The 'short _Fract' type + PREDEF_TYPE_SHORT_FRACT_ID = 52, + + /// \brief The '_Fract' type + PREDEF_TYPE_FRACT_ID = 53, + + /// \brief The 'long _Fract' type + PREDEF_TYPE_LONG_FRACT_ID = 54, + + /// \brief The 'unsigned short _Fract' type + PREDEF_TYPE_USHORT_FRACT_ID = 55, + + /// \brief The 'unsigned _Fract' type + PREDEF_TYPE_UFRACT_ID = 56, + + /// \brief The 'unsigned long _Fract' type + PREDEF_TYPE_ULONG_FRACT_ID = 57, + + /// \brief The '_Sat short _Accum' type + PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 58, + + /// \brief The '_Sat _Accum' type + PREDEF_TYPE_SAT_ACCUM_ID = 59, + + /// \brief The '_Sat long _Accum' type + PREDEF_TYPE_SAT_LONG_ACCUM_ID = 60, + + /// \brief The '_Sat unsigned short _Accum' type + PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 61, + + /// \brief The '_Sat unsigned _Accum' type + PREDEF_TYPE_SAT_UACCUM_ID = 62, + + /// \brief The '_Sat unsigned long _Accum' type + PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 63, + + /// \brief The '_Sat short _Fract' type + PREDEF_TYPE_SAT_SHORT_FRACT_ID = 64, + + /// \brief The '_Sat _Fract' type + PREDEF_TYPE_SAT_FRACT_ID = 65, + + /// \brief The '_Sat long _Fract' type + PREDEF_TYPE_SAT_LONG_FRACT_ID = 66, + + /// \brief The '_Sat unsigned short _Fract' type + PREDEF_TYPE_SAT_USHORT_FRACT_ID = 67, + + /// \brief The '_Sat unsigned _Fract' type + PREDEF_TYPE_SAT_UFRACT_ID = 68, + + /// \brief The '_Sat unsigned long _Fract' type + PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69, + /// \brief OpenCL image types with auto numeration /// OpenCL image types with auto numeration @@ -970,7 +1024,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; /// Record codes for each kind of type. /// Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -283,6 +283,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; @@ -347,6 +348,7 @@ unsigned TypeAltiVecBool : 1; unsigned TypeSpecOwned : 1; unsigned TypeSpecPipe : 1; + unsigned TypeSpecSat : 1; // type-qualifiers unsigned TypeQualifiers : 5; // Bitwise OR of TQ. @@ -382,7 +384,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 @@ -431,6 +433,7 @@ TypeAltiVecBool(false), TypeSpecOwned(false), TypeSpecPipe(false), + TypeSpecSat(false), TypeQualifiers(TQ_unspecified), FS_inline_specified(false), FS_forceinline_specified(false), @@ -484,6 +487,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"); @@ -662,6 +666,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/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -391,6 +391,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/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -77,6 +77,15 @@ unsigned char ShortAccumWidth, ShortAccumAlign; unsigned char AccumWidth, AccumAlign; unsigned char LongAccumWidth, LongAccumAlign; + unsigned char ShortFractWidth, ShortFractAlign; + unsigned char FractWidth, FractAlign; + unsigned char LongFractWidth, LongFractAlign; + unsigned char SatShortAccumWidth, SatShortAccumAlign; + unsigned char SatAccumWidth, SatAccumAlign; + unsigned char SatLongAccumWidth, SatLongAccumAlign; + unsigned char SatShortFractWidth, SatShortFractAlign; + unsigned char SatFractWidth, SatFractAlign; + unsigned char SatLongFractWidth, SatLongFractAlign; unsigned char SuitableAlign; unsigned char DefaultAlignForAttributeAligned; unsigned char MinGlobalAlign; @@ -376,6 +385,51 @@ unsigned getLongAccumWidth() const { return LongAccumWidth; } unsigned getLongAccumAlign() const { return LongAccumAlign; } + /// getShortFractWidth/Align - Return the size of 'signed short _Fract' and + /// 'unsigned short _Fract' for this target, in bits. + unsigned getShortFractWidth() const { return ShortFractWidth; } + unsigned getShortFractAlign() const { return ShortFractAlign; } + + /// getFractWidth/Align - Return the size of 'signed _Fract' and + /// 'unsigned _Fract' for this target, in bits. + unsigned getFractWidth() const { return FractWidth; } + unsigned getFractAlign() const { return FractAlign; } + + /// getLongFractWidth/Align - Return the size of 'signed long _Fract' and + /// 'unsigned long _Fract' for this target, in bits. + unsigned getLongFractWidth() const { return LongFractWidth; } + unsigned getLongFractAlign() const { return LongFractAlign; } + + /// getSatShortAccumWidth/Align - Return the size of '_Sat signed short + /// _Accum' and '_Sat unsigned short _Accum' for this targetSat, in bits. + unsigned getSatShortAccumWidth() const { return SatShortAccumWidth; } + unsigned getSatShortAccumAlign() const { return SatShortAccumAlign; } + + /// getSatAccumWidth/Align - Return the size of '_Sat signed _Accum' and + /// '_Sat unsigned _Accum' for this targetSat, in bits. + unsigned getSatAccumWidth() const { return SatAccumWidth; } + unsigned getSatAccumAlign() const { return SatAccumAlign; } + + /// getSatLongAccumWidth/Align - Return the size of '_Sat signed long _Accum' + /// and '_Sat unsigned long _Accum' for this targetSat, in bits. + unsigned getSatLongAccumWidth() const { return SatLongAccumWidth; } + unsigned getSatLongAccumAlign() const { return SatLongAccumAlign; } + + /// getSatShortFractWidth/Align - Return the size of '_Sat signed short + /// _Fract' and '_Sat unsigned short _Fract' for this targetSat, in bits. + unsigned getSatShortFractWidth() const { return SatShortFractWidth; } + unsigned getSatShortFractAlign() const { return SatShortFractAlign; } + + /// getSatFractWidth/Align - Return the size of '_Sat signed _Fract' and + /// '_Sat unsigned _Fract' for this targetSat, in bits. + unsigned getSatFractWidth() const { return SatFractWidth; } + unsigned getSatFractAlign() const { return SatFractAlign; } + + /// getSatLongFractWidth/Align - Return the size of '_Sat signed long _Fract' + /// and '_Sat unsigned long _Fract' for this targetSat, in bits. + unsigned getSatLongFractWidth() const { return SatLongFractWidth; } + unsigned getSatLongFractAlign() const { return SatLongFractAlign; } + /// Determine whether the __int128 type is supported on this target. virtual bool hasInt128Type() const { return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; Index: include/clang/Basic/Specifiers.h =================================================================== --- include/clang/Basic/Specifiers.h +++ include/clang/Basic/Specifiers.h @@ -55,6 +55,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/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -203,6 +203,8 @@ def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>; +def err_invalid_saturation_spec : Error<"'_Sat' specifier is only valid on " + "'_Fract' or '_Accum', not '%0'">; 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/AST/Type.h =================================================================== --- include/clang/AST/Type.h +++ include/clang/AST/Type.h @@ -2108,6 +2108,26 @@ /// enumeration types whose underlying type is a unsigned integer type. bool isUnsignedIntegerOrEnumerationType() const; + /// Return true if this is a fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. + bool isFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isSaturatedFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isUnsaturatedFixedPointType() const; + + /// Return true if this is a fixed point type that is signed according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isSignedFixedPointType() const; + + /// Return true if this is a fixed point type that is unsigned according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isUnsignedFixedPointType() const; + /// Return true if this is not a variable sized type, /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types. @@ -6293,6 +6313,44 @@ return false; } +inline bool Type::isFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isSaturatedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isUnsaturatedFixedPointType() const { + return isFixedPointType() && !isSaturatedFixedPointType(); +} + +inline bool Type::isSignedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return ((BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::LongAccum) || + (BT->getKind() >= BuiltinType::ShortFract && + BT->getKind() <= BuiltinType::LongFract) || + (BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatLongAccum) || + (BT->getKind() >= BuiltinType::SatShortFract && + BT->getKind() <= BuiltinType::SatLongFract)); + } + return false; +} + +inline bool Type::isUnsignedFixedPointType() const { + return isFixedPointType() && !isSignedFixedPointType(); +} + inline bool Type::isScalarType() const { if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() > BuiltinType::Void && @@ -6488,6 +6546,14 @@ return cast<PointerType>(Decayed)->getPointeeType(); } +namespace fixedpoint { + +QualType getCorrespondingSaturatedType(const ASTContext &Context, + const QualType &Ty); +QualType getCorrespondingSignedType(const ASTContext &Context, + const QualType &Ty); + +} // namespace fixedpoint } // namespace clang #endif // LLVM_CLANG_AST_TYPE_H Index: include/clang/AST/BuiltinTypes.def =================================================================== --- include/clang/AST/BuiltinTypes.def +++ include/clang/AST/BuiltinTypes.def @@ -142,6 +142,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/AST/ASTContext.h =================================================================== --- include/clang/AST/ASTContext.h +++ include/clang/AST/ASTContext.h @@ -1010,6 +1010,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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits