leonardchan created this revision.
leonardchan added a project: clang.

This diff includes changes for the remaining _Fract and _Sat fixed point types.

  signed short _Fract s_short_fract;
  signed _Fract s_fract;
  signed long _Fract s_long_fract;
  unsigned short _Fract u_short_fract;
  unsigned _Fract u_fract;
  unsigned long _Fract u_long_fract;
  
  // Aliased fixed point types
  short _Accum short_accum;
  _Accum accum;
  long _Accum long_accum;
  short _Fract short_fract;
  _Fract fract;
  long _Fract long_fract;
  
  // Saturated fixed point types
  _Sat signed short _Accum sat_s_short_accum;
  _Sat signed _Accum sat_s_accum;
  _Sat signed long _Accum sat_s_long_accum;
  _Sat unsigned short _Accum sat_u_short_accum;
  _Sat unsigned _Accum sat_u_accum;
  _Sat unsigned long _Accum sat_u_long_accum;
  _Sat signed short _Fract sat_s_short_fract;
  _Sat signed _Fract sat_s_fract;
  _Sat signed long _Fract sat_s_long_fract;
  _Sat unsigned short _Fract sat_u_short_fract;
  _Sat unsigned _Fract sat_u_fract;
  _Sat unsigned long _Fract sat_u_long_fract;
  
  // Aliased saturated fixed point types
  _Sat short _Accum sat_short_accum;
  _Sat _Accum sat_accum;
  _Sat long _Accum sat_long_accum;
  _Sat short _Fract sat_short_fract;
  _Sat _Fract sat_fract;
  _Sat long _Fract sat_long_fract;

This diff only allows for declaration of these fixed point types. Assignment 
and other operations done on fixed point types according to 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf will be added in 
future patches.

This is a parent of https://reviews.llvm.org/D46084


Repository:
  rC Clang

https://reviews.llvm.org/D46911

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/BuiltinTypes.def
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/Specifiers.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/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/accum.c
  test/Frontend/accum_errors.c
  test/Frontend/accum_errors.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_errors.cpp

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

Reply via email to