This revision was automatically updated to reflect the committed changes.
Closed by commit rC334718: [Fixed Point Arithmetic] Addition of the remaining 
fixed point types and their… (authored by leonardchan, committed by ).

Repository:
  rL LLVM

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
  test/Frontend/fixed_point_errors.cpp

Index: test/Frontend/fixed_point_errors.cpp
===================================================================
--- test/Frontend/fixed_point_errors.cpp
+++ test/Frontend/fixed_point_errors.cpp
@@ -1,5 +1,9 @@
+// RUN: %clang_cc1 -x c++ %s -verify
 // RUN: %clang_cc1 -x c++ -ffixed-point %s -verify
 
 // Name namgling is not provided for fixed point types in c++
 
 _Accum accum;                           // expected-error{{unknown type name '_Accum'}}
+_Fract fract;                           // expected-error{{unknown type name '_Fract'}}
+_Sat _Accum sat_accum;                  // expected-error{{unknown type name '_Sat'}}
+                                        // expected-error@-1{{expected ';' after top level declarator}}
Index: test/Frontend/fixed_point_bit_widths.c
===================================================================
--- test/Frontend/fixed_point_bit_widths.c
+++ test/Frontend/fixed_point_bit_widths.c
@@ -3,44 +3,194 @@
 // RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=ppc64 %s | FileCheck %s
 // RUN: %clang -x c -ffixed-point -S -emit-llvm -o - --target=x86_64-scei-ps4-windows10pro-fast %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  = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @size_SA   = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @size_SlA  = {{.*}}global i{{[0-9]+}} 8
 // CHECK-NEXT: @align_SsA = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @align_SA  = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @align_SlA = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @size_UA   = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @size_UlA  = {{.*}}global i{{[0-9]+}} 8
 // CHECK-NEXT: @align_UsA = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @align_UA  = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @align_UlA = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SlF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SlF = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_UF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_UlF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_UF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_UlF = {{.*}}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   = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @size_A    = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @size_lA   = {{.*}}global i{{[0-9]+}} 8
 // CHECK-NEXT: @align_sA  = {{.*}}global i{{[0-9]+}} 2
 // CHECK-NEXT: @align_A   = {{.*}}global i{{[0-9]+}} 4
 // CHECK-NEXT: @align_lA  = {{.*}}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   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_F    = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_lF   = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_sF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_F   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_lF  = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatSA   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatSlA  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatSsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatSA  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatSlA = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatUA   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatUlA  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatUsA = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatUA  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatUlA = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatSF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatSlF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatSF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatSlF = {{.*}}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  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatUF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatUlF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatUF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatUlF = {{.*}}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   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatA    = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatlA   = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatsA  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatA   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatlA  = {{.*}}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   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatF    = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @size_SatlF   = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @align_SatsF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatlF  = {{.*}}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;
-
-// 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'
+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'
 
 #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: 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,67 @@
 _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}}
+
+/* Do not allow typedef to be used with typedef'd types */
+typedef short _Fract shortfract_t;
+typedef short _Accum shortaccum_t;
+typedef _Fract fract_t;
+typedef _Accum accum_t;
+typedef long _Fract longfract_t;
+typedef long _Accum longaccum_t;
+_Sat shortfract_t td_sat_short_fract;       // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat shortaccum_t td_sat_short_accum;       // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat fract_t td_sat_fract;                  // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat accum_t td_sat_accum;                  // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat longfract_t td_sat_long_fract;         // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
+_Sat longaccum_t td_sat_long_accum;         // expected-error{{'_Sat' specifier is only valid on '_Fract' or '_Accum', not 'type-name'}}
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:
       return GCCTypeClass::None;
 
     case BuiltinType::NullPtr:
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:
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/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -1934,6 +1934,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/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/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/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);
@@ -1795,19 +1813,46 @@
       break;
     case BuiltinType::ShortAccum:
     case BuiltinType::UShortAccum:
+    case BuiltinType::SatShortAccum:
+    case BuiltinType::SatUShortAccum:
       Width = Target->getShortAccumWidth();
       Align = Target->getShortAccumAlign();
       break;
     case BuiltinType::Accum:
     case BuiltinType::UAccum:
+    case BuiltinType::SatAccum:
+    case BuiltinType::SatUAccum:
       Width = Target->getAccumWidth();
       Align = Target->getAccumAlign();
       break;
     case BuiltinType::LongAccum:
     case BuiltinType::ULongAccum:
+    case BuiltinType::SatLongAccum:
+    case BuiltinType::SatULongAccum:
       Width = Target->getLongAccumWidth();
       Align = Target->getLongAccumAlign();
       break;
+    case BuiltinType::ShortFract:
+    case BuiltinType::UShortFract:
+    case BuiltinType::SatShortFract:
+    case BuiltinType::SatUShortFract:
+      Width = Target->getShortFractWidth();
+      Align = Target->getShortFractAlign();
+      break;
+    case BuiltinType::Fract:
+    case BuiltinType::UFract:
+    case BuiltinType::SatFract:
+    case BuiltinType::SatUFract:
+      Width = Target->getFractWidth();
+      Align = Target->getFractAlign();
+      break;
+    case BuiltinType::LongFract:
+    case BuiltinType::ULongFract:
+    case BuiltinType::SatLongFract:
+    case BuiltinType::SatULongFract:
+      Width = Target->getLongFractWidth();
+      Align = Target->getLongFractAlign();
+      break;
     case BuiltinType::Float16:
     case BuiltinType::Half:
       Width = Target->getHalfWidth();
@@ -6251,6 +6296,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 ' ';
 
@@ -8854,7 +8917,8 @@
 }
 
 QualType ASTContext::getCorrespondingUnsignedType(QualType T) const {
-  assert(T->hasSignedIntegerRepresentation() && "Unexpected type");
+  assert((T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) &&
+         "Unexpected type");
   
   // Turn <4 x signed int> -> <4 x unsigned int>
   if (const auto *VTy = T->getAs<VectorType>())
@@ -8866,7 +8930,7 @@
     T = ETy->getDecl()->getIntegerType();
   
   const auto *BTy = T->getAs<BuiltinType>();
-  assert(BTy && "Unexpected signed integer type");
+  assert(BTy && "Unexpected signed integer or fixed point type");
   switch (BTy->getKind()) {
   case BuiltinType::Char_S:
   case BuiltinType::SChar:
@@ -8881,8 +8945,33 @@
     return UnsignedLongLongTy;
   case BuiltinType::Int128:
     return UnsignedInt128Ty;
+
+  case BuiltinType::ShortAccum:
+    return UnsignedShortAccumTy;
+  case BuiltinType::Accum:
+    return UnsignedAccumTy;
+  case BuiltinType::LongAccum:
+    return UnsignedLongAccumTy;
+  case BuiltinType::SatShortAccum:
+    return SatUnsignedShortAccumTy;
+  case BuiltinType::SatAccum:
+    return SatUnsignedAccumTy;
+  case BuiltinType::SatLongAccum:
+    return SatUnsignedLongAccumTy;
+  case BuiltinType::ShortFract:
+    return UnsignedShortFractTy;
+  case BuiltinType::Fract:
+    return UnsignedFractTy;
+  case BuiltinType::LongFract:
+    return UnsignedLongFractTy;
+  case BuiltinType::SatShortFract:
+    return SatUnsignedShortFractTy;
+  case BuiltinType::SatFract:
+    return SatUnsignedFractTy;
+  case BuiltinType::SatLongFract:
+    return SatUnsignedLongFractTy;
   default:
-    llvm_unreachable("Unexpected signed integer type");
+    llvm_unreachable("Unexpected signed integer or fixed point type");
   }
 }
 
@@ -10029,6 +10118,42 @@
     return (*AddrSpaceMap)[(unsigned)AS];
 }
 
+QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const {
+  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 SatShortAccumTy;
+    case BuiltinType::Accum:
+      return SatAccumTy;
+    case BuiltinType::LongAccum:
+      return SatLongAccumTy;
+    case BuiltinType::UShortAccum:
+      return SatUnsignedShortAccumTy;
+    case BuiltinType::UAccum:
+      return SatUnsignedAccumTy;
+    case BuiltinType::ULongAccum:
+      return SatUnsignedLongAccumTy;
+    case BuiltinType::ShortFract:
+      return SatShortFractTy;
+    case BuiltinType::Fract:
+      return SatFractTy;
+    case BuiltinType::LongFract:
+      return SatLongFractTy;
+    case BuiltinType::UShortFract:
+      return SatUnsignedShortFractTy;
+    case BuiltinType::UFract:
+      return SatUnsignedFractTy;
+    case BuiltinType::ULongFract:
+      return SatUnsignedLongFractTy;
+  }
+}
+
 // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that
 // doesn't include ASTContext.h
 template
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/SemaType.cpp
===================================================================
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -1392,36 +1392,49 @@
     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");
-      }
-    } 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");
-      }
+    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:
+        llvm_unreachable("Unable to specify long long as _Accum width");
     }
+
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+      Result = Context.getCorrespondingUnsignedType(Result);
+
+    if (DS.isTypeSpecSat())
+      Result = Context.getCorrespondingSaturatedType(Result);
+
+    break;
+  }
+  case DeclSpec::TST_fract: {
+    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:
+        llvm_unreachable("Unable to specify long long as _Fract width");
+    }
+
+    if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
+      Result = Context.getCorrespondingUnsignedType(Result);
+
+    if (DS.isTypeSpecSat())
+      Result = Context.getCorrespondingSaturatedType(Result);
+
     break;
   }
   case DeclSpec::TST_int128:
@@ -1592,6 +1605,15 @@
       S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
     declarator.setInvalidType(true);
 
+  bool IsFixedPointType = DS.getTypeSpecType() == DeclSpec::TST_accum ||
+                          DS.getTypeSpecType() == DeclSpec::TST_fract;
+
+  // Only fixed point types can be saturated
+  if (DS.isTypeSpecSat() && !IsFixedPointType)
+    S.Diag(DS.getTypeSpecSatLoc(), diag::err_invalid_saturation_spec)
+        << DS.getSpecifierName(DS.getTypeSpecType(),
+                               Context.getPrintingPolicy());
+
   // Handle complex types.
   if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
     if (S.getLangOpts().Freestanding)
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(SourceLocation Loc, const char *&PrevSpec,
+                              unsigned &DiagID) {
+  // Cannot set twice
+  if (TypeSpecSat) {
+    DiagID = diag::warn_duplicate_declspec;
+    PrevSpec = "_Sat";
+    return true;
+  }
+  TypeSpecSat = true;
+  TSSatLoc = Loc;
+  return false;
+}
+
 bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
                           const char *&PrevSpec, unsigned &DiagID,
                           const PrintingPolicy &Policy) {
@@ -1102,13 +1117,16 @@
     }
   }
 
+  bool IsFixedPointType =
+      TypeSpecType == TST_accum || TypeSpecType == TST_fract;
+
   // 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) {
+             !IsFixedPointType) {
       S.Diag(TSSLoc, diag::err_invalid_sign_spec)
         << getSpecifierName((TST)TypeSpecType, Policy);
       // signed double -> double.
@@ -1124,21 +1142,23 @@
     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;
+      TypeSpecSat = false;
       TypeSpecOwned = false;
     }
     break;
   case TSW_long:  // long double, long int
     if (TypeSpecType == TST_unspecified)
       TypeSpecType = TST_int;  // long -> long int.
     else if (TypeSpecType != TST_int && TypeSpecType != TST_double &&
-             TypeSpecType != TST_accum) {
+             !IsFixedPointType) {
       S.Diag(TSWRange.getBegin(), diag::err_invalid_width_spec)
           << (int)TypeSpecWidth << getSpecifierName((TST)TypeSpecType, Policy);
       TypeSpecType = TST_int;
+      TypeSpecSat = false;
       TypeSpecOwned = false;
     }
     break;
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/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -43,6 +43,9 @@
   ShortAccumWidth = ShortAccumAlign = 16;
   AccumWidth = AccumAlign = 32;
   LongAccumWidth = LongAccumAlign = 64;
+  ShortFractWidth = ShortFractAlign = 16;
+  FractWidth = FractAlign = 32;
+  LongFractWidth = LongFractAlign = 64;
   SuitableAlign = 64;
   DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
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/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2876,6 +2876,17 @@
   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);
+  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,14 +3593,27 @@
       break;
     case tok::kw__Accum:
       if (!getLangOpts().FixedPoint) {
-        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(Loc, PrevSpec, DiagID);
+      }
+      break;
     case tok::kw___float128:
       isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec,
                                      DiagID, Policy);
@@ -4617,6 +4641,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:
@@ -4695,6 +4720,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:
@@ -4718,6 +4744,7 @@
   case tok::kw_const:
   case tok::kw_volatile:
   case tok::kw_restrict:
+  case tok::kw__Sat:
 
     // Debugger support.
   case tok::kw___unknown_anytype:
@@ -4854,6 +4881,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:
@@ -4875,6 +4903,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
@@ -2738,6 +2738,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: 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/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 &&
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;
@@ -2543,8 +2551,15 @@
   // Per C99 6.2.5p6, for every signed integer type, there is a corresponding
   // unsigned integer type.  This method takes a signed type, and returns the
   // corresponding unsigned integer type.
+  // With the introduction of fixed point types in ISO N1169, this method also
+  // accepts fixed point types and returns the corresponding unsigned type for
+  // a given fixed point type.
   QualType getCorrespondingUnsignedType(QualType T) const;
 
+  // Per ISO N1169, this method accepts fixed point types and returns the
+  // corresponding saturated type for a given fixed point type.
+  QualType getCorrespondingSaturatedType(QualType Ty) const;
+
   //===--------------------------------------------------------------------===//
   //                    Integer Values
   //===--------------------------------------------------------------------===//
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");
@@ -510,6 +514,7 @@
   SourceLocation getTypeSpecSignLoc() const { return TSSLoc; }
   SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; }
   SourceLocation getAltiVecLoc() const { return AltiVecLoc; }
+  SourceLocation getTypeSpecSatLoc() const { return TSSatLoc; }
 
   SourceLocation getTypeSpecTypeNameLoc() const {
     assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename);
@@ -662,6 +667,8 @@
   bool SetTypePipe(bool isPipe, SourceLocation Loc,
                        const char *&PrevSpec, unsigned &DiagID,
                        const PrintingPolicy &Policy);
+  bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec,
+                      unsigned &DiagID);
   bool SetTypeSpecError();
   void UpdateDeclRep(Decl *Rep) {
     assert(isDeclRep((TST) TypeSpecType));
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/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -77,6 +77,9 @@
   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 SuitableAlign;
   unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
@@ -376,6 +379,21 @@
   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; }
+
   /// Determine whether the __int128 type is supported on this target.
   virtual bool hasInt128Type() const {
     return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
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                      , KEYNOCXX)
+KEYWORD(_Fract                      , KEYNOCXX)
+KEYWORD(_Sat                        , KEYNOCXX)
 
 // GNU Extensions (in impl-reserved namespace)
 KEYWORD(_Decimal32                  , KEYALL)
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,
+
       /// OpenCL image types with auto numeration
 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
       PREDEF_TYPE_##Id##_ID,
@@ -968,7 +1022,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.
     ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to