leonardchan updated this revision to Diff 150248.
leonardchan marked 20 inline comments as done.
leonardchan added a comment.

- Moved definition of the fractional/integral bits to TargetInfo. Checks are 
also performed to make sure any target specific definitions of the F/IBits 
follow the restrictions set in clause 6.2.6.3 in N1169.
- Added flag `-fsame-fbits` to force the number of fractional bits in unsigned 
types to be the same as those of their their corresponding signed types. The 
default values for all fractional bits is of signed fixed point types are one 
less than the default values for their unsigned counterparts.
- Implemented custom parsing for fixed point literals and added tests for them. 
Both decimal and hexadecimal exponentiation are supported.
- I do not have many examples involving assignment to saturated types because 
this patch does not include conversions yet between fixed point types. This 
will be in a future patch. The same goes for testing the minimum values for 
each type because I have not yet implemented folding on binary expressions 
involving fixed point types.


Repository:
  rC Clang

https://reviews.llvm.org/D46915

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/Expr.h
  include/clang/AST/OperationKinds.def
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/AST/Type.h
  include/clang/Basic/DiagnosticCommonKinds.td
  include/clang/Basic/LangOptions.def
  include/clang/Basic/StmtNodes.td
  include/clang/Basic/TargetInfo.h
  include/clang/Driver/Options.td
  include/clang/Lex/LiteralSupport.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTDumper.cpp
  lib/AST/Expr.cpp
  lib/AST/ExprClassification.cpp
  lib/AST/ExprConstant.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/StmtProfile.cpp
  lib/AST/Type.cpp
  lib/Basic/TargetInfo.cpp
  lib/Basic/Targets.cpp
  lib/CodeGen/CGExpr.cpp
  lib/CodeGen/CGExprAgg.cpp
  lib/CodeGen/CGExprComplex.cpp
  lib/CodeGen/CGExprConstant.cpp
  lib/CodeGen/CGExprScalar.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Edit/RewriteObjCFoundationAPI.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Index/USRGeneration.cpp
  lib/Lex/LiteralSupport.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExceptionSpec.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTReaderStmt.cpp
  lib/Serialization/ASTWriterStmt.cpp
  lib/StaticAnalyzer/Core/ExprEngine.cpp
  lib/StaticAnalyzer/Core/ExprEngineC.cpp
  test/Frontend/fixed_point.c
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_same_fbits.c
  test/Frontend/fixed_point_validation.c
  tools/libclang/CXCursor.cpp

Index: tools/libclang/CXCursor.cpp
===================================================================
--- tools/libclang/CXCursor.cpp
+++ tools/libclang/CXCursor.cpp
@@ -305,6 +305,10 @@
     K = CXCursor_IntegerLiteral;
     break;
 
+  case Stmt::FixedPointLiteralClass:
+    llvm_unreachable("No cursor for FixedPointLiteralClass");
+    break;
+
   case Stmt::FloatingLiteralClass:
     K = CXCursor_FloatingLiteral;
     break;
Index: test/Frontend/fixed_point_validation.c
===================================================================
--- /dev/null
+++ test/Frontend/fixed_point_validation.c
@@ -0,0 +1,19 @@
+// RUN: %clang -ffixed-point -S -emit-llvm -o - %s | lli -force-interpreter=true
+
+// Run simple validation tests
+
+#define assert(b) if (!(b)) { return 1; }
+
+int main(){
+  short _Accum s_accum = 0.0hk;
+  short _Accum s_accum2 = 2.0hk;
+  short _Fract s_fract = 0.999hr;
+  short _Fract s_fract2 = -0.999hr;
+
+  assert(s_accum == 0);
+
+  s_accum = s_accum2;
+
+  assert(s_accum == s_accum2);
+  assert(s_accum == 2);
+}
Index: test/Frontend/fixed_point_same_fbits.c
===================================================================
--- /dev/null
+++ test/Frontend/fixed_point_same_fbits.c
@@ -0,0 +1,28 @@
+// RUN: %clang -ffixed-point -S -emit-llvm -o - %s | FileCheck %s -check-prefix=DEFAULT
+// RUN: %clang -ffixed-point -fsame-fbits -S -emit-llvm -o - %s | FileCheck %s -check-prefix=SAME
+
+/* The scale for unsigned fixed point types should be the same as that of signed
+ * fixed point types when -fsame-fbits is enabled. */
+
+void func() {
+  unsigned short _Accum u_short_accum = 0.5uhk;
+  unsigned _Accum u_accum = 0.5uk;
+  unsigned long _Accum u_long_accum = 0.5ulk;
+  unsigned short _Fract u_short_fract = 0.5uhr;
+  unsigned _Fract u_fract = 0.5ur;
+  unsigned long _Fract u_long_fract = 0.5ulr;
+
+// DEFAULT: store i16 128, i16* %u_short_accum, align 2
+// DEFAULT: store i32 32768, i32* %u_accum, align 4
+// DEFAULT: store i64 2147483648, i64* %u_long_accum, align 8
+// DEFAULT: store i16 128, i16* %u_short_fract, align 2
+// DEFAULT: store i32 32768, i32* %u_fract, align 4
+// DEFAULT: store i64 2147483648, i64* %u_long_fract, align 8
+
+// SAME: store i16 64, i16* %u_short_accum, align 2
+// SAME: store i32 16384, i32* %u_accum, align 4
+// SAME: store i64 1073741824, i64* %u_long_accum, align 8
+// SAME: store i16 64, i16* %u_short_fract, align 2
+// SAME: store i32 16384, i32* %u_fract, align 4
+// SAME: store i64 1073741824, i64* %u_long_fract, align 8
+}
Index: test/Frontend/fixed_point_errors.c
===================================================================
--- test/Frontend/fixed_point_errors.c
+++ test/Frontend/fixed_point_errors.c
@@ -13,7 +13,6 @@
 _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. */
 
@@ -78,6 +77,50 @@
 _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}}
 
+
+/* Literals that cannot fit into types */
+signed short _Accum s_short_accum = 256.0hk;            // expected-error{{this value is too large for this signed _Accum type}}
+unsigned short _Accum u_short_accum = 256.0uhk;         // expected-error{{this value is too large for this unsigned _Accum type}}
+signed _Accum s_accum = 65536.0k;                       // expected-error{{this value is too large for this signed _Accum type}}
+unsigned _Accum u_accum = 65536.0uk;                    // expected-error{{this value is too large for this unsigned _Accum type}}
+signed long _Accum s_long_accum = 4294967296.0lk;       // expected-error{{this value is too large for this signed _Accum type}}
+unsigned long _Accum u_long_accum = 4294967296.0ulk;    // expected-error{{this value is too large for this unsigned _Accum type}}
+
+// Large values from decimal exponents
+short _Accum          short_accum_exp   = 2.56e2hk;           // expected-error{{this value is too large for this signed _Accum type}}
+_Accum                accum_exp         = 6.5536e4k;          // expected-error{{this value is too large for this signed _Accum type}}
+long _Accum           long_accum_exp    = 4.294967296e9lk;    // expected-error{{this value is too large for this signed _Accum type}}
+unsigned short _Accum u_short_accum_exp = 2.56e2uhk;          // expected-error{{this value is too large for this unsigned _Accum type}}
+unsigned _Accum       u_accum_exp       = 6.5536e4uk;         // expected-error{{this value is too large for this unsigned _Accum type}}
+unsigned long _Accum  u_long_accum_exp  = 4.294967296e9ulk;   // expected-error{{this value is too large for this unsigned _Accum type}}
+
+// Large value from hexidecimal exponents
+short _Accum          short_accum_hex_exp   = 0x1e8hk;        // expected-error{{this value is too large for this signed _Accum type}}
+_Accum                accum_hex_exp         = 0x1e16k;        // expected-error{{this value is too large for this signed _Accum type}}
+long _Accum           long_accum_hex_exp    = 0x1e32lk;       // expected-error{{this value is too large for this signed _Accum type}}
+unsigned short _Accum u_short_accum_hex_exp = 0x1e8uhk;       // expected-error{{this value is too large for this unsigned _Accum type}}
+unsigned _Accum       u_accum_hex_exp       = 0x1e16uk;       // expected-error{{this value is too large for this unsigned _Accum type}}
+unsigned long _Accum  u_long_accum_hex_exp  = 0x1e32ulk;      // expected-error{{this value is too large for this unsigned _Accum type}}
+
+// Very large exponent
+_Accum x = 1e1000000000000000000000000000000000k;   // expected-error{{this value is too large for this signed _Accum type}}
+
+/* Although _Fract's cannot equal 1, _Fract literals written as 1 are allowed
+ * and the underlying value represents the max value for that _Fract type. */
+short _Fract          short_fract_above_1    = 1.1hr;   // expected-error{{a _Fract type cannot have an integral part}}
+_Fract                fract_above_1          = 1.1r;    // expected-error{{a _Fract type cannot have an integral part}}
+long _Fract           long_fract_above_1     = 1.1lr;   // expected-error{{a _Fract type cannot have an integral part}}
+unsigned short _Fract u_short_fract_above_1  = 1.1uhr;  // expected-error{{a _Fract type cannot have an integral part}}
+unsigned _Fract       u_fract_above_1        = 1.1ur;   // expected-error{{a _Fract type cannot have an integral part}}
+unsigned long _Fract  u_long_fract_above_1   = 1.1ulr;  // expected-error{{a _Fract type cannot have an integral part}}
+
+short _Fract          short_fract_hex_exp   = 0x0.fp1hr;      // expected-error{{a _Fract type cannot have an integral part}}
+_Fract                fract_hex_exp         = 0x0.fp1r;       // expected-error{{a _Fract type cannot have an integral part}}
+long _Fract           long_fract_hex_exp    = 0x0.fp1lr;      // expected-error{{a _Fract type cannot have an integral part}}
+unsigned short _Fract u_short_fract_hex_exp = 0x0.fp1uhr;     // expected-error{{a _Fract type cannot have an integral part}}
+unsigned _Fract       u_fract_hex_exp       = 0x0.fp1ur;      // expected-error{{a _Fract type cannot have an integral part}}
+unsigned long _Fract  u_long_fract_hex_exp  = 0x0.fp1ulr;     // expected-error{{a _Fract type cannot have an integral part}}
+
 /* Do not allow typedef to be used with typedef'd types */
 typedef short _Fract shortfract_t;
 typedef short _Accum shortaccum_t;
@@ -91,3 +134,16 @@
 _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'}}
+
+/* Bad suffixes  */
+_Accum fk = 1.0fk;    // expected-error{{invalid suffix 'fk' on integer constant}}
+_Accum kk = 1.0kk;    // expected-error{{invalid suffix 'kk' on integer constant}}
+_Accum rk = 1.0rk;    // expected-error{{invalid suffix 'rk' on integer constant}}
+_Accum rk = 1.0rr;    // expected-error{{invalid suffix 'rr' on integer constant}}
+_Accum qk = 1.0qr;    // expected-error{{invalid suffix 'qr' on integer constant}}
+
+/* Using wrong exponent notation */
+_Accum dec_with_hex_exp1 = 0.1p10k;    // expected-error{{invalid suffix 'p10k' on integer constant}}
+_Accum dec_with_hex_exp2 = 0.1P10k;    // expected-error{{invalid suffix 'P10k' on integer constant}}
+_Accum hex_with_dex_exp1 = 0x0.1e10k;  // expected-error{{hexadecimal floating constant requires an exponent}}
+_Accum hex_with_dex_exp2 = 0x0.1E10k;  // expected-error{{hexadecimal floating constant requires an exponent}}
Index: test/Frontend/fixed_point_declarations.c
===================================================================
--- /dev/null
+++ test/Frontend/fixed_point_declarations.c
@@ -0,0 +1,113 @@
+// RUN: %clang -ffixed-point -S -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang -ffixed-point -S -emit-llvm %s -o - --target=x86_64-scei-ps4-ubuntu-fast | FileCheck %s
+
+// Primary fixed point types
+signed short _Accum   s_short_accum;  // CHECK-DAG: @s_short_accum  = {{.*}}global i16 0, align 2
+signed _Accum         s_accum;        // CHECK-DAG: @s_accum        = {{.*}}global i32 0, align 4
+signed long _Accum    s_long_accum;   // CHECK-DAG: @s_long_accum   = {{.*}}global i64 0, align 8
+unsigned short _Accum u_short_accum;  // CHECK-DAG: @u_short_accum  = {{.*}}global i16 0, align 2
+unsigned _Accum       u_accum;        // CHECK-DAG: @u_accum        = {{.*}}global i32 0, align 4
+unsigned long _Accum  u_long_accum;   // CHECK-DAG: @u_long_accum   = {{.*}}global i64 0, align 8
+signed short _Fract   s_short_fract;  // CHECK-DAG: @s_short_fract  = {{.*}}global i16 0, align 2
+signed _Fract         s_fract;        // CHECK-DAG: @s_fract        = {{.*}}global i32 0, align 4
+signed long _Fract    s_long_fract;   // CHECK-DAG: @s_long_fract   = {{.*}}global i64 0, align 8
+unsigned short _Fract u_short_fract;  // CHECK-DAG: @u_short_fract  = {{.*}}global i16 0, align 2
+unsigned _Fract       u_fract;        // CHECK-DAG: @u_fract        = {{.*}}global i32 0, align 4
+unsigned long _Fract  u_long_fract;   // CHECK-DAG: @u_long_fract   = {{.*}}global i64 0, align 8
+
+// Aliased
+short _Accum  short_accum;            // CHECK-DAG: @short_accum    = {{.*}}global i16 0, align 2
+_Accum        accum;                  // CHECK-DAG: @accum          = {{.*}}global i32 0, align 4
+long _Accum   long_accum;             // CHECK-DAG: @long_accum     = {{.*}}global i64 0, align 8
+short _Fract  short_fract;            // CHECK-DAG: @short_fract    = {{.*}}global i16 0, align 2
+_Fract        fract;                  // CHECK-DAG: @fract          = {{.*}}global i32 0, align 4
+long _Fract   long_fract;             // CHECK-DAG: @long_fract     = {{.*}}global i64 0, align 8
+
+// Primary saturated
+_Sat signed short _Accum   sat_s_short_accum;  // CHECK-DAG: @sat_s_short_accum  = {{.*}}global i16 0, align 2
+_Sat signed _Accum         sat_s_accum;        // CHECK-DAG: @sat_s_accum        = {{.*}}global i32 0, align 4
+_Sat signed long _Accum    sat_s_long_accum;   // CHECK-DAG: @sat_s_long_accum   = {{.*}}global i64 0, align 8
+_Sat unsigned short _Accum sat_u_short_accum;  // CHECK-DAG: @sat_u_short_accum  = {{.*}}global i16 0, align 2
+_Sat unsigned _Accum       sat_u_accum;        // CHECK-DAG: @sat_u_accum        = {{.*}}global i32 0, align 4
+_Sat unsigned long _Accum  sat_u_long_accum;   // CHECK-DAG: @sat_u_long_accum   = {{.*}}global i64 0, align 8
+_Sat signed short _Fract   sat_s_short_fract;  // CHECK-DAG: @sat_s_short_fract  = {{.*}}global i16 0, align 2
+_Sat signed _Fract         sat_s_fract;        // CHECK-DAG: @sat_s_fract        = {{.*}}global i32 0, align 4
+_Sat signed long _Fract    sat_s_long_fract;   // CHECK-DAG: @sat_s_long_fract   = {{.*}}global i64 0, align 8
+_Sat unsigned short _Fract sat_u_short_fract;  // CHECK-DAG: @sat_u_short_fract  = {{.*}}global i16 0, align 2
+_Sat unsigned _Fract       sat_u_fract;        // CHECK-DAG: @sat_u_fract        = {{.*}}global i32 0, align 4
+_Sat unsigned long _Fract  sat_u_long_fract;   // CHECK-DAG: @sat_u_long_fract   = {{.*}}global i64 0, align 8
+
+// Aliased saturated
+_Sat short _Accum  sat_short_accum;            // CHECK-DAG: @sat_short_accum    = {{.*}}global i16 0, align 2
+_Sat _Accum        sat_accum;                  // CHECK-DAG: @sat_accum          = {{.*}}global i32 0, align 4
+_Sat long _Accum   sat_long_accum;             // CHECK-DAG: @sat_long_accum     = {{.*}}global i64 0, align 8
+_Sat short _Fract  sat_short_fract;            // CHECK-DAG: @sat_short_fract    = {{.*}}global i16 0, align 2
+_Sat _Fract        sat_fract;                  // CHECK-DAG: @sat_fract          = {{.*}}global i32 0, align 4
+_Sat long _Fract   sat_long_fract;             // CHECK-DAG: @sat_long_fract     = {{.*}}global i64 0, align 8
+
+/* Fixed point literals */
+short _Accum  short_accum_literal = 2.5hk;    // CHECK-DAG: @short_accum_literal  = {{.*}}global i16 320, align 2
+_Accum        accum_literal       = 2.5k;     // CHECK-DAG: @accum_literal        = {{.*}}global i32 81920, align 4
+long _Accum   long_accum_literal  = 2.5lk;    // CHECK-DAG: @long_accum_literal   = {{.*}}global i64 5368709120, align 8
+short _Fract  short_fract_literal = 0.5hr;    // CHECK-DAG: @short_fract_literal  = {{.*}}global i16 64, align 2
+_Fract        fract_literal       = 0.5r;     // CHECK-DAG: @fract_literal        = {{.*}}global i32 16384, align 4
+long _Fract   long_fract_literal  = 0.5lr;    // CHECK-DAG: @long_fract_literal   = {{.*}}global i64 1073741824, align 8
+
+unsigned short _Accum  u_short_accum_literal = 2.5uhk;    // CHECK-DAG: @u_short_accum_literal  = {{.*}}global i16 640, align 2
+unsigned _Accum        u_accum_literal       = 2.5uk;     // CHECK-DAG: @u_accum_literal        = {{.*}}global i32 163840, align 4
+unsigned long _Accum   u_long_accum_literal  = 2.5ulk;    // CHECK-DAG: @u_long_accum_literal   = {{.*}}global i64 10737418240, align 8
+unsigned short _Fract  u_short_fract_literal = 0.5uhr;    // CHECK-DAG: @u_short_fract_literal  = {{.*}}global i16 128, align 2
+unsigned _Fract        u_fract_literal       = 0.5ur;     // CHECK-DAG: @u_fract_literal        = {{.*}}global i32 32768, align 4
+unsigned long _Fract   u_long_fract_literal  = 0.5ulr;    // CHECK-DAG: @u_long_fract_literal   = {{.*}}global i64 2147483648, align 8
+
+// Max literal values
+short _Accum          short_accum_max   = 255.9999999999999999hk;         // CHECK-DAG: @short_accum_max   = {{.*}}global i16 32767, align 2
+_Accum                accum_max         = 65535.9999999999999999k;        // CHECK-DAG: @accum_max         = {{.*}}global i32 2147483647, align 4
+long _Accum           long_accum_max    = 4294967295.9999999999999999lk;  // CHECK-DAG: @long_accum_max    = {{.*}}global i64 9223372036854775807, align 8
+unsigned short _Accum u_short_accum_max = 255.9999999999999999uhk;        // CHECK-DAG: @u_short_accum_max = {{.*}}global i16 -1, align 2
+unsigned _Accum       u_accum_max       = 65535.9999999999999999uk;       // CHECK-DAG: @u_accum_max       = {{.*}}global i32 -1, align 4
+unsigned long _Accum  u_long_accum_max  = 4294967295.9999999999999999ulk; // CHECK-DAG: @u_long_accum_max  = {{.*}}global i64 -1, align 8
+
+short _Fract          short_fract_max   = 0.9999999999999999hr;           // CHECK-DAG: @short_fract_max   = {{.*}}global i16 127, align 2
+_Fract                fract_max         = 0.9999999999999999r;            // CHECK-DAG: @fract_max         = {{.*}}global i32 32767, align 4
+long _Fract           long_fract_max    = 0.9999999999999999lr;           // CHECK-DAG: @long_fract_max    = {{.*}}global i64 2147483647, align 8
+unsigned short _Fract u_short_fract_max = 0.9999999999999999uhr;          // CHECK-DAG: @u_short_fract_max = {{.*}}global i16 255, align 2
+unsigned _Fract       u_fract_max       = 0.9999999999999999ur;           // CHECK-DAG: @u_fract_max       = {{.*}}global i32 65535, align 4
+unsigned long _Fract  u_long_fract_max  = 0.9999999999999999ulr;          // CHECK-DAG: @u_long_fract_max  = {{.*}}global i64 4294967295, align 8
+
+// Fracts may be exactly one but evaluate to the Fract max
+short _Fract          short_fract_one   = 1.0hr;    // CHECK-DAG: @short_fract_one    = {{.*}}global i16 127, align 2
+_Fract                fract_one         = 1.0r;     // CHECK-DAG: @fract_one          = {{.*}}global i32 32767, align 4
+long _Fract           long_fract_one    = 1.0lr;    // CHECK-DAG: @long_fract_one     = {{.*}}global i64 2147483647, align 8
+unsigned short _Fract u_short_fract_one = 1.0uhr;   // CHECK-DAG: @u_short_fract_one  = {{.*}}global i16 255, align 2
+unsigned _Fract       u_fract_one       = 1.0ur;    // CHECK-DAG: @u_fract_one        = {{.*}}global i32 65535, align 4
+unsigned long _Fract  u_long_fract_one  = 1.0ulr;   // CHECK-DAG: @u_long_fract_one   = {{.*}}global i64 4294967295, align 8
+
+short _Fract          short_fract_exp_one   = 0.1e1hr;    // CHECK-DAG: @short_fract_exp_one    = {{.*}}global i16 127, align 2
+_Fract                fract_exp_one         = 0.1e1r;     // CHECK-DAG: @fract_exp_one          = {{.*}}global i32 32767, align 4
+long _Fract           long_fract_exp_one    = 0.1e1lr;    // CHECK-DAG: @long_fract_exp_one     = {{.*}}global i64 2147483647, align 8
+unsigned short _Fract u_short_fract_exp_one = 0.1e1uhr;   // CHECK-DAG: @u_short_fract_exp_one  = {{.*}}global i16 255, align 2
+unsigned _Fract       u_fract_exp_one       = 0.1e1ur;    // CHECK-DAG: @u_fract_exp_one        = {{.*}}global i32 65535, align 4
+unsigned long _Fract  u_long_fract_exp_one  = 0.1e1ulr;   // CHECK-DAG: @u_long_fract_exp_one   = {{.*}}global i64 4294967295, align 8
+
+short _Fract          short_fract_hex_exp_one   = 0x0.8p1hr;    // CHECK-DAG: @short_fract_hex_exp_one    = {{.*}}global i16 127, align 2
+_Fract                fract_hex_exp_one         = 0x0.8p1r;     // CHECK-DAG: @fract_hex_exp_one          = {{.*}}global i32 32767, align 4
+long _Fract           long_fract_hex_exp_one    = 0x0.8p1lr;    // CHECK-DAG: @long_fract_hex_exp_one     = {{.*}}global i64 2147483647, align 8
+unsigned short _Fract u_short_fract_hex_exp_one = 0x0.8p1uhr;   // CHECK-DAG: @u_short_fract_hex_exp_one  = {{.*}}global i16 255, align 2
+unsigned _Fract       u_fract_hex_exp_one       = 0x0.8p1ur;    // CHECK-DAG: @u_fract_hex_exp_one        = {{.*}}global i32 65535, align 4
+unsigned long _Fract  u_long_fract_hex_exp_one  = 0x0.8p1ulr;   // CHECK-DAG: @u_long_fract_hex_exp_one   = {{.*}}global i64 4294967295, align 8
+
+// Expsilon values
+short _Accum          short_accum_eps   = 0x1p-7hk;         // CHECK-DAG: @short_accum_eps   = {{.*}}global i16 1, align 2
+_Accum                accum_eps         = 0x1p-15k;         // CHECK-DAG: @accum_eps         = {{.*}}global i32 1, align 4
+long _Accum           long_accum_eps    = 0x1p-31lk;        // CHECK-DAG: @long_accum_eps    = {{.*}}global i64 1, align 8
+unsigned short _Accum u_short_accum_eps = 0x1p-8uhk;        // CHECK-DAG: @u_short_accum_eps = {{.*}}global i16 1, align 2
+unsigned _Accum       u_accum_eps       = 0x1p-16uk;        // CHECK-DAG: @u_accum_eps       = {{.*}}global i32 1, align 4
+unsigned long _Accum  u_long_accum_eps  = 0x1p-32ulk;       // CHECK-DAG: @u_long_accum_eps  = {{.*}}global i64 1, align 8
+
+short _Fract          short_fract_eps   = 0x1p-7hr;         // CHECK-DAG: @short_fract_eps   = {{.*}}global i16 1, align 2
+_Fract                fract_eps         = 0x1p-15r;         // CHECK-DAG: @fract_eps         = {{.*}}global i32 1, align 4
+long _Fract           long_fract_eps    = 0x1p-31lr;        // CHECK-DAG: @long_fract_eps    = {{.*}}global i64 1, align 8
+unsigned short _Fract u_short_fract_eps = 0x1p-8uhr;        // CHECK-DAG: @u_short_fract_eps = {{.*}}global i16 1, align 2
+unsigned _Fract       u_fract_eps       = 0x1p-16ur;        // CHECK-DAG: @u_fract_eps       = {{.*}}global i32 1, align 4
+unsigned long _Fract  u_long_fract_eps  = 0x1p-32ulr;       // CHECK-DAG: @u_long_fract_eps  = {{.*}}global i64 1, align 8
Index: test/Frontend/fixed_point.c
===================================================================
--- test/Frontend/fixed_point.c
+++ test/Frontend/fixed_point.c
@@ -236,4 +236,164 @@
 //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'
+//CHECK-NEXT: |-VarDecl {{.*}} SatlF_type 'SatlF_t':'_Sat long _Fract'
+
+// Fixed point literal exponent syntax
+_Accum decexp1 = 1.575e1k;
+_Accum decexp2 = 1.575E1k;
+_Accum decexp3 = 1575e-2k;
+_Accum decexp4 = 1575E-2k;
+
+_Accum hexexp1 = 0x0.3p10k;
+_Accum hexexp2 = 0x0.3P10k;
+_Accum hexexp3 = 0x30000p-10k;
+_Accum hexexp4 = 0x30000P-10k;
+
+_Accum zeroexp1 = 1e0k;
+_Accum zeroexp2 = 1e-0k;
+
+//CHECK-NEXT: |-VarDecl {{.*}} decexp1 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp3 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 15.75
+//CHECK-NEXT: |-VarDecl {{.*}} decexp4 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 15.75
+
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp1 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp3 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 192.0
+//CHECK-NEXT: |-VarDecl {{.*}} hexexp4 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 192.0
+
+//CHECK-NEXT: |-VarDecl {{.*}} zeroexp1 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.0
+//CHECK-NEXT: |-VarDecl {{.*}} zeroexp2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.0
+
+// Fixed point literal values
+_Accum literal1 = 2.5k;       // Precise decimal
+_Accum literal2 = 0.0k;       // Zero
+_Accum literal3 = 1.1k;       // Imprecise decimal
+_Accum literal4 = 1.11k;
+_Accum literal5 = 1.111k;
+_Accum literal6 = 1.1111k;
+_Accum literal7 = 1.11111k;   // After some point after the radix, adding any more
+                              // digits to the literal will not result in any
+                              // further precision since the nth digit added may
+                              // be less than the precision that can be
+                              // represented by the fractional bits of the type.
+                              // This results in the same value being stored for
+                              // the type.
+
+//CHECK-NEXT: |-VarDecl {{.*}} literal1 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 2.5
+//CHECK-NEXT: |-VarDecl {{.*}} literal2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} literal3 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.0999755859375
+//CHECK-NEXT: |-VarDecl {{.*}} literal4 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.1099853515625
+//CHECK-NEXT: |-VarDecl {{.*}} literal5 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.110992431640625
+//CHECK-NEXT: |-VarDecl {{.*}} literal6 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375
+//CHECK-NEXT: |-VarDecl {{.*}} literal7 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.111083984375
+
+long _Accum longaccumliteral     = 0.99999999lk;
+long _Accum longaccumliteral2    = 0.999999999lk;
+long _Accum verylongaccumliteral = 0.99999999999999999999999999lk;
+long _Fract longfractliteral     = 0.99999999lr;
+long _Fract longfractliteral2    = 0.999999999lr;
+long _Fract verylongfractliteral = 0.99999999999999999999999999lr;
+
+//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.999999989755451679229736328125
+//CHECK-NEXT: |-VarDecl {{.*}} longaccumliteral2 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999986030161380767822265625
+//CHECK-NEXT: |-VarDecl {{.*}} verylongaccumliteral 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875
+//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral 'long _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Fract' 0.999999989755451679229736328125
+//CHECK-NEXT: |-VarDecl {{.*}} longfractliteral2 'long _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999986030161380767822265625
+//CHECK-NEXT: |-VarDecl {{.*}} verylongfractliteral 'long _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875
+
+unsigned _Accum uliteral1 = 2.5uk;    // Unsigned
+_Accum literal8 = -2.5k;              // Negative
+
+//CHECK-NEXT: |-VarDecl {{.*}} uliteral1 'unsigned _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'unsigned _Accum' 2.5
+//CHECK-NEXT: |-VarDecl {{.*}} literal8 '_Accum' cinit
+//CHECK-NEXT:   `-UnaryOperator {{.*}} '_Accum' prefix '-'
+//CHECK-NEXT:     `-FixedPointLiteral {{.*}} '_Accum' 2.5
+
+short _Accum  literalexact1 = 0.9921875hk;  // Exact value
+_Accum        literalexact2 = 0.999969482421875k;
+
+//CHECK-NEXT: |-VarDecl {{.*}} literalexact1 'short _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'short _Accum' 0.9921875
+//CHECK-NEXT: |-VarDecl {{.*}} literalexact2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 0.999969482421875
+
+// Unfortunately we do not have enough space to store the exact decimal value of
+// 0.9999999995343387126922607421875 ((1 << 31) - 1), but we can still use a
+// large number of 9s to get the max fractional value.
+long _Accum   long_accum_max = 0.999999999999999999999999999lk;
+
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_max 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.9999999995343387126922607421875
+
+// Epsilon
+short _Accum  short_accum_eps   = 0.0078125hk;
+short _Accum  short_accum_eps2  = 0.0078124hk;  // Less than epsilon floors to zero
+_Accum        accum_eps         = 0.000030517578125k;
+_Accum        accum_eps2        = 0.000030517578124k;
+long _Accum   long_accum_eps    = 0x1p-31lk;
+long _Accum   long_accum_eps2   = 0x0.99999999p-31lk;
+
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps 'short _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'short _Accum' 0.0078125
+//CHECK-NEXT: |-VarDecl {{.*}} short_accum_eps2 'short _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'short _Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} accum_eps '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 0.000030517578125
+//CHECK-NEXT: |-VarDecl {{.*}} accum_eps2 '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 0.0
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.0000000004656612873077392578125
+//CHECK-NEXT: |-VarDecl {{.*}} long_accum_eps2 'long _Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Accum' 0.0
+
+// Fract literals can be one but evaluate to the respective Fract max
+short _Fract           short_fract_one   = 1.0hr;
+_Fract                 fract_one         = 1.0r;
+long _Fract            long_fract_one    = 1.0lr;
+unsigned short _Fract  u_short_fract_one = 1.0uhr;
+unsigned _Fract        u_fract_one       = 1.0ur;
+unsigned long _Fract   u_long_fract_one  = 1.0ulr;
+
+//CHECK-NEXT: |-VarDecl {{.*}} short_fract_one 'short _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'short _Fract' 0.9921875
+//CHECK-NEXT: |-VarDecl {{.*}} fract_one '_Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Fract' 0.999969482421875
+//CHECK-NEXT: |-VarDecl {{.*}} long_fract_one 'long _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'long _Fract' 0.9999999995343387126922607421875
+
+//CHECK-NEXT: |-VarDecl {{.*}} u_short_fract_one 'unsigned short _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'unsigned short _Fract' 0.99609375
+//CHECK-NEXT: |-VarDecl {{.*}} u_fract_one 'unsigned _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'unsigned _Fract' 0.9999847412109375
+//CHECK-NEXT: |-VarDecl {{.*}} u_long_fract_one 'unsigned long _Fract' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} 'unsigned long _Fract' 0.99999999976716935634613037109375
+
+_Accum literallast = 1.0k;    // One
+
+//CHECK-NEXT: `-VarDecl {{.*}} literallast '_Accum' cinit
+//CHECK-NEXT:   `-FixedPointLiteral {{.*}} '_Accum' 1.0
Index: lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -328,6 +328,9 @@
     const LocationContext *LCtx = Pred->getLocationContext();
 
     switch (CastE->getCastKind()) {
+      case CK_IntegralToFixedPoint:
+        llvm_unreachable(
+            "ExprEngine::VisitCast CK_IntegralToFixedPoint");  // TODO
       case CK_LValueToRValue:
         llvm_unreachable("LValueToRValue casts handled earlier.");
       case CK_ToVoid:
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1297,6 +1297,7 @@
     case Stmt::AddrLabelExprClass:
     case Stmt::AttributedStmtClass:
     case Stmt::IntegerLiteralClass:
+    case Stmt::FixedPointLiteralClass:
     case Stmt::CharacterLiteralClass:
     case Stmt::ImplicitValueInitExprClass:
     case Stmt::CXXScalarValueInitExprClass:
Index: lib/Serialization/ASTWriterStmt.cpp
===================================================================
--- lib/Serialization/ASTWriterStmt.cpp
+++ lib/Serialization/ASTWriterStmt.cpp
@@ -444,6 +444,10 @@
   Code = serialization::EXPR_INTEGER_LITERAL;
 }
 
+void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) {
+  llvm_unreachable("ASTStmtWriter::VisitFixedPointLiteral");
+}
+
 void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
   VisitExpr(E);
   Record.push_back(E->getRawSemantics());
Index: lib/Serialization/ASTReaderStmt.cpp
===================================================================
--- lib/Serialization/ASTReaderStmt.cpp
+++ lib/Serialization/ASTReaderStmt.cpp
@@ -533,6 +533,12 @@
   E->setValue(Record.getContext(), Record.readAPInt());
 }
 
+void ASTStmtReader::VisitFixedPointLiteral(FixedPointLiteral *E) {
+  VisitExpr(E);
+  E->setLocation(ReadSourceLocation());
+  E->setValue(Record.getContext(), Record.readAPInt());
+}
+
 void ASTStmtReader::VisitFloatingLiteral(FloatingLiteral *E) {
   VisitExpr(E);
   E->setRawSemantics(static_cast<Stmt::APFloatSemantics>(Record.readInt()));
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -8888,6 +8888,12 @@
   return E;
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformFixedPointLiteral(
+    FixedPointLiteral *E) {
+  return E;
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {
Index: lib/Sema/SemaExpr.cpp
===================================================================
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -26,6 +26,7 @@
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Basic/TargetInfo.h"
@@ -1218,6 +1219,46 @@
                               CK_IntegralRealToComplex);
   return ComplexType;
 }
+/// \brief Handle arithmetic conversion from integer to fixed point.  Helper
+/// function of UsualArithmeticConversions()
+static QualType handleIntToFixedPointConversion(Sema &S,
+                                                ExprResult &FixedPointExpr,
+                                                ExprResult &IntExpr,
+                                                QualType FixedPointTy,
+                                                QualType IntTy) {
+  assert(IntTy->isIntegerType());
+  assert(FixedPointTy->isFixedPointType());
+
+  IntExpr =
+      S.ImpCastExprToType(IntExpr.get(), FixedPointTy, CK_IntegralToFixedPoint);
+  return FixedPointTy;
+}
+
+/// \brief Handle arithmethic conversion with fixed point types.  Helper
+/// function of UsualArithmeticConversions().
+static QualType handleFixedPointConversion(Sema &S, ExprResult &LHS,
+                                           ExprResult &RHS, QualType LHSType,
+                                           QualType RHSType,
+                                           bool IsCompAssign) {
+  // At this point, the only other type we should be able to convert to is
+  // integer types since all prior types were handled beforehand in
+  // UsualArithmeticConventions().
+  bool LHSFixed = LHSType->isFixedPointType();
+  bool RHSFixed = RHSType->isFixedPointType();
+
+  if (LHSFixed && RHSFixed) {
+    // Cast up the smaller operand to the bigger
+    llvm_unreachable("Unhandled conversion between fixed point types");  // TODO
+  } else if (LHSFixed) {
+    assert(RHSType->isIntegerType());
+    return handleIntToFixedPointConversion(S, LHS, RHS, LHSType, RHSType);
+  } else if (RHSFixed) {
+    assert(LHSType->isIntegerType());
+    return handleIntToFixedPointConversion(S, RHS, LHS, RHSType, LHSType);
+  } else {
+    llvm_unreachable("Expected LHS and RHS to both be fixed point types.");
+  }
+}
 
 /// UsualArithmeticConversions - Performs various conversions that are common to
 /// binary operators (C99 6.3.1.8). If both operands aren't arithmetic, this
@@ -1291,6 +1332,11 @@
     return handleComplexIntConversion(*this, LHS, RHS, LHSType, RHSType,
                                       IsCompAssign);
 
+  // Handle fixed point types
+  if (LHSType->isFixedPointType() || RHSType->isFixedPointType())
+    return handleFixedPointConversion(*this, LHS, RHS, LHSType, RHSType,
+                                      IsCompAssign);
+
   // Finally, we have two differing integer types.
   return handleIntegerConversion<doIntegralCast, doIntegralCast>
            (*this, LHS, RHS, LHSType, RHSType, IsCompAssign);
@@ -3144,33 +3190,40 @@
                                 Context.IntTy, Loc);
 }
 
-static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
-                                  QualType Ty, SourceLocation Loc) {
-  const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty);
-
-  using llvm::APFloat;
-  APFloat Val(Format);
-
-  APFloat::opStatus result = Literal.GetFloatValue(Val);
-
+static void HandleFloatOverflow(Sema &S, QualType Ty, SourceLocation Loc,
+                                const llvm::APFloat::opStatus &result,
+                                const llvm::APFloat &Val,
+                                const llvm::fltSemantics &Format) {
   // Overflow is always an error, but underflow is only an error if
   // we underflowed to zero (APFloat reports denormals as underflow).
-  if ((result & APFloat::opOverflow) ||
-      ((result & APFloat::opUnderflow) && Val.isZero())) {
+  if ((result & llvm::APFloat::opOverflow) ||
+      ((result & llvm::APFloat::opUnderflow) && Val.isZero())) {
     unsigned diagnostic;
     SmallString<20> buffer;
-    if (result & APFloat::opOverflow) {
+    if (result & llvm::APFloat::opOverflow) {
       diagnostic = diag::warn_float_overflow;
-      APFloat::getLargest(Format).toString(buffer);
+      llvm::APFloat::getLargest(Format).toString(buffer);
     } else {
       diagnostic = diag::warn_float_underflow;
-      APFloat::getSmallest(Format).toString(buffer);
+      llvm::APFloat::getSmallest(Format).toString(buffer);
     }
 
     S.Diag(Loc, diagnostic)
       << Ty
       << StringRef(buffer.data(), buffer.size());
   }
+}
+
+static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal,
+                                  QualType Ty, SourceLocation Loc) {
+  const llvm::fltSemantics &Format = S.Context.getFloatTypeSemantics(Ty);
+
+  using llvm::APFloat;
+  APFloat Val(Format);
+
+  APFloat::opStatus result = Literal.GetFloatValue(Val);
+
+  HandleFloatOverflow(S, Ty, Loc, result, Val, Format);
 
   bool isExact = (result == APFloat::opOK);
   return FloatingLiteral::Create(S.Context, Val, isExact, Ty, Loc);
@@ -3326,7 +3379,65 @@
 
   Expr *Res;
 
-  if (Literal.isFloatingLiteral()) {
+  if (Literal.isFixedPointLiteral()) {
+    QualType Ty;
+
+    if (Literal.isAccum) {
+      if (Literal.isHalf) {
+        Ty = Context.ShortAccumTy;
+      } else if (Literal.isLong) {
+        Ty = Context.LongAccumTy;
+      } else {
+        Ty = Context.AccumTy;
+      }
+    } else if (Literal.isFract) {
+      if (Literal.isHalf) {
+        Ty = Context.ShortFractTy;
+      } else if (Literal.isLong) {
+        Ty = Context.LongFractTy;
+      } else {
+        Ty = Context.FractTy;
+      }
+    }
+
+    if (Literal.isUnsigned) Ty = Context.getCorrespondingUnsignedType(Ty);
+
+    bool isSigned = !Literal.isUnsigned;
+    unsigned scale = Context.getFixedPointScale(Ty);
+    unsigned ibits = Context.getFixedPointIBits(Ty);
+    unsigned bit_width = Context.getTypeInfo(Ty).Width;
+
+    uint64_t Val;
+    bool Overflowed = Literal.GetFixedPointValue(Val, scale);
+
+    // Throw an error if we receive a literal that cannot fit into the type.
+    if (Literal.isFract) {
+      uint64_t MaxVal = 1ULL << scale;
+      if (Val > MaxVal) {
+        Diag(Tok.getLocation(), diag::err_integral_part_on_fract);
+      } else if (Val == MaxVal) {
+        // Clause 6.4.4 - The value of a constant shall be in the range of
+        // representable values for its type, with exception for constants of a
+        // fract type with a value of exactly 1; such a constant shall denote
+        // the maximal value for the type.
+        --Val;
+      }
+    } else {
+      // Split the underlying integer into an integral and fractional part to
+      // prevent potential overflow when comparing against a single maximum
+      // value.
+      uint64_t MaxUnscaledVal = (1ULL << ibits) - 1;
+      uint64_t UnscaledVal = Val >> scale;
+      if (UnscaledVal > MaxUnscaledVal || Overflowed) {
+        Diag(Tok.getLocation(), diag::err_accum_too_large)
+            << (isSigned ? 0 : 1);
+      }
+    }
+
+    llvm::APInt ResultVal(bit_width, Val, isSigned);
+    Res = FixedPointLiteral::CreateFromRawInt(Context, ResultVal, Ty,
+                                              Tok.getLocation(), scale);
+  } else if (Literal.isFloatingLiteral()) {
     QualType Ty;
     if (Literal.isHalf){
       if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
@@ -5807,13 +5918,21 @@
     case Type::STK_FloatingComplex:
     case Type::STK_IntegralComplex:
     case Type::STK_MemberPointer:
+    case Type::STK_FixedPoint:
       llvm_unreachable("illegal cast from pointer");
     }
     llvm_unreachable("Should have returned before this");
 
+  case Type::STK_FixedPoint:
+    llvm_unreachable(
+        "Sema::PrepareScalarCast from STK_FixedPoint to anything");  // TODO
+
   case Type::STK_Bool: // casting from bool is like casting from an integer
   case Type::STK_Integral:
     switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FixedPoint:
+      llvm_unreachable(
+          "Sema::PrepareScalarCast from STK_Integral to STK_FixedPoint");  // TODO
     case Type::STK_CPointer:
     case Type::STK_ObjCObjectPointer:
     case Type::STK_BlockPointer:
@@ -5844,6 +5963,9 @@
 
   case Type::STK_Floating:
     switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FixedPoint:
+      llvm_unreachable(
+          "Sema::PrepareScalarCast from STK_Floating to STK_FixedPoint");  // TODO
     case Type::STK_Floating:
       return CK_FloatingCast;
     case Type::STK_Bool:
@@ -5871,6 +5993,10 @@
 
   case Type::STK_FloatingComplex:
     switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FixedPoint:
+      llvm_unreachable(
+          "Sema::PrepareScalarCast from STK_FloatingComplex to "
+          "STK_FixedPoint");  // TODO
     case Type::STK_FloatingComplex:
       return CK_FloatingComplexCast;
     case Type::STK_IntegralComplex:
@@ -5900,6 +6026,10 @@
 
   case Type::STK_IntegralComplex:
     switch (DestTy->getScalarTypeKind()) {
+    case Type::STK_FixedPoint:
+      llvm_unreachable(
+          "Sema::PrepareScalarCast from STK_IntegralComplex to "
+          "STK_FixedPoint");  // TODO
     case Type::STK_FloatingComplex:
       return CK_IntegralComplexToFloatingComplex;
     case Type::STK_IntegralComplex:
@@ -13122,7 +13252,7 @@
     CondExpr = CondICE.get();
     CondIsTrue = condEval.getZExtValue();
 
-    // If the condition is > zero, then the AST type is the same as the LSHExpr.
+    // If the condition is > zero, then the AST type is the same as the LHSExpr.
     Expr *ActiveExpr = CondIsTrue ? LHSExpr : RHSExpr;
 
     resType = ActiveExpr->getType();
Index: lib/Sema/SemaExceptionSpec.cpp
===================================================================
--- lib/Sema/SemaExceptionSpec.cpp
+++ lib/Sema/SemaExceptionSpec.cpp
@@ -1258,6 +1258,7 @@
   case Expr::ImaginaryLiteralClass:
   case Expr::ImplicitValueInitExprClass:
   case Expr::IntegerLiteralClass:
+  case Expr::FixedPointLiteralClass:
   case Expr::ArrayInitIndexExprClass:
   case Expr::NoInitExprClass:
   case Expr::ObjCEncodeExprClass:
Index: lib/Sema/Sema.cpp
===================================================================
--- lib/Sema/Sema.cpp
+++ lib/Sema/Sema.cpp
@@ -532,6 +532,9 @@
   case Type::STK_Floating: return CK_FloatingToBoolean;
   case Type::STK_IntegralComplex: return CK_IntegralComplexToBoolean;
   case Type::STK_FloatingComplex: return CK_FloatingComplexToBoolean;
+  case Type::STK_FixedPoint:
+    llvm_unreachable(
+        "Sema::ScalarTypeToBooleanCastKind for fixed point");  // TODO
   }
   llvm_unreachable("unknown scalar type kind");
 }
Index: lib/Lex/LiteralSupport.cpp
===================================================================
--- lib/Lex/LiteralSupport.cpp
+++ lib/Lex/LiteralSupport.cpp
@@ -27,6 +27,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ScaledNumber.h"
 #include <algorithm>
 #include <cassert>
 #include <cstddef>
@@ -538,6 +539,7 @@
   saw_exponent = false;
   saw_period = false;
   saw_ud_suffix = false;
+  saw_fixed_point_suffix = false;
   isLong = false;
   isUnsigned = false;
   isLongLong = false;
@@ -547,6 +549,8 @@
   isFloat16 = false;
   isFloat128 = false;
   MicrosoftInteger = 0;
+  isFract = false;
+  isAccum = false;
   hadError = false;
 
   if (*s == '0') { // parse radix
@@ -568,19 +572,37 @@
   SuffixBegin = s;
   checkSeparator(TokLoc, s, CSK_AfterDigits);
 
+  // Initial scan to lookahead for fixed point suffix.
+  for (const char *c = s; c != ThisTokEnd; ++c) {
+    if (*c == 'r' || *c == 'k' || *c == 'R' || *c == 'K') {
+      saw_fixed_point_suffix = true;
+      break;
+    }
+  }
+
   // Parse the suffix.  At this point we can classify whether we have an FP or
   // integer constant.
   bool isFPConstant = isFloatingLiteral();
 
   // Loop over all of the characters of the suffix.  If we see something bad,
   // we break out of the loop.
   for (; s != ThisTokEnd; ++s) {
     switch (*s) {
+    case 'R':
+    case 'r':
+      if (isFract || isAccum) break;
+      isFract = true;
+      continue;
+    case 'K':
+    case 'k':
+      if (isFract || isAccum) break;
+      isAccum = true;
+      continue;
     case 'h':      // FP Suffix for "half".
     case 'H':
       // OpenCL Extension v1.2 s9.5 - h or H suffix for half type.
-      if (!PP.getLangOpts().Half) break;
-      if (!isFPConstant) break;  // Error for integer constant.
+      if (!(PP.getLangOpts().Half || PP.getLangOpts().FixedPoint)) break;
+      if (isIntegerLiteral()) break;          // Error for integer constant.
       if (isHalf || isFloat || isLong) break; // HH, FH, LH invalid.
       isHalf = true;
       continue;  // Success.
@@ -693,6 +715,9 @@
         isHalf = false;
         isImaginary = false;
         MicrosoftInteger = 0;
+        saw_fixed_point_suffix = false;
+        isFract = false;
+        isAccum = false;
       }
 
       saw_ud_suffix = true;
@@ -707,6 +732,11 @@
       hadError = true;
     }
   }
+
+  if (!hadError && saw_fixed_point_suffix) {
+    assert(isFract || isAccum);
+    assert(radix == 16 || radix == 10);
+  }
 }
 
 /// ParseDecimalOrOctalCommon - This method is called for decimal or octal
@@ -1012,6 +1042,99 @@
   return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
 }
 
+bool NumericLiteralParser::GetFixedPointValue(uint64_t &Val, unsigned Scale) {
+  assert(radix == 16 || radix == 10);
+
+  // Need as much storage space as possible
+  __int128 TmpVal = 0;
+  bool IntOverflowOccurred = false;
+  bool FractOverflowOccurred = false;
+  bool FoundExponent = false;
+  bool FoundDecimal = false;
+
+  int64_t BaseShift = 0;
+  const char *Ptr = DigitsBegin;
+  for (; Ptr < SuffixBegin; ++Ptr) {
+    if (*Ptr == '.') {
+      FoundDecimal = true;
+      continue;
+    }
+    if (*Ptr == 'p' || *Ptr == 'P' || *Ptr == 'e' || *Ptr == 'E') {
+      FoundExponent = true;
+      ++Ptr;
+      break;
+    }
+
+    // Normal reading of an integer
+    unsigned C = llvm::hexDigitValue(*Ptr);
+    assert(C < radix && "NumericLiteralParser ctor should have rejected this");
+
+    auto OldVal = TmpVal;
+    TmpVal *= radix;
+    if (!FoundDecimal)
+      IntOverflowOccurred |= (TmpVal / radix != OldVal);
+    else
+      FractOverflowOccurred |= (TmpVal / radix != OldVal);
+
+    TmpVal += C;
+    if (!FoundDecimal)
+      IntOverflowOccurred |= (TmpVal < C);
+    else
+      FractOverflowOccurred |= (TmpVal < C);
+
+    if (FractOverflowOccurred) {
+      TmpVal = OldVal;
+      break;
+    } else if (FoundDecimal) {
+      --BaseShift;
+    }
+  }
+
+  // For a radix of 16, we will be multiplying by 2 instead of 16.
+  if (radix == 16) BaseShift *= 4;
+
+  bool ExpOverflowOccurred = false;
+  if (FoundExponent) {
+    uint64_t Exponent = 0;
+    bool NegativeExponent = *Ptr == '-';
+    if (NegativeExponent) ++Ptr;
+    for (; Ptr < SuffixBegin; ++Ptr) {
+      unsigned C = llvm::hexDigitValue(*Ptr);
+      assert(C < 10 && "NumericLiteralParser ctor should have rejected this");
+
+      uint64_t OldExponent = Exponent;
+      Exponent *= 10;
+      ExpOverflowOccurred |= (Exponent / 10 != OldExponent);
+      Exponent += C;
+      ExpOverflowOccurred |= (Exponent < C);
+    }
+
+    if (NegativeExponent)
+      BaseShift -= Exponent;
+    else
+      BaseShift += Exponent;
+  }
+
+  auto OldVal = TmpVal;
+  TmpVal <<= Scale;
+  IntOverflowOccurred |= (TmpVal >> Scale) != OldVal;
+
+  uint64_t Base = (radix == 16) ? 2 : 10;
+  if (BaseShift > 0) {
+    for (int64_t i = 0; i < BaseShift && !IntOverflowOccurred; ++i) {
+      OldVal = TmpVal;
+      TmpVal *= Base;
+      IntOverflowOccurred |= (TmpVal / Base != OldVal);
+    }
+  } else if (BaseShift < 0) {
+    for (int64_t i = BaseShift; i < 0 && TmpVal; ++i) TmpVal /= Base;
+  }
+
+  IntOverflowOccurred |= TmpVal > std::numeric_limits<uint64_t>::max();
+  Val = TmpVal;
+  return IntOverflowOccurred || ExpOverflowOccurred;
+}
+
 /// \verbatim
 ///       user-defined-character-literal: [C++11 lex.ext]
 ///         character-literal ud-suffix
Index: lib/Index/USRGeneration.cpp
===================================================================
--- lib/Index/USRGeneration.cpp
+++ lib/Index/USRGeneration.cpp
@@ -743,6 +743,7 @@
           c = 'e'; break;
       }
       Out << c;
+
       return;
     }
 
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -2337,6 +2337,10 @@
   Opts.FixedPoint =
       Args.hasFlag(OPT_ffixed_point, OPT_fno_fixed_point, /*Default=*/false) &&
       !Opts.CPlusPlus;
+  Opts.SameFBits =
+      Args.hasFlag(OPT_fsame_fbits, OPT_fno_same_fbits,
+                   /*Default=*/false) &&
+      Opts.FixedPoint;
 
   // Handle exception personalities
   Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions,
Index: lib/Edit/RewriteObjCFoundationAPI.cpp
===================================================================
--- lib/Edit/RewriteObjCFoundationAPI.cpp
+++ lib/Edit/RewriteObjCFoundationAPI.cpp
@@ -1002,6 +1002,9 @@
 
   if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Arg)) {
     switch (ICE->getCastKind()) {
+    case CK_IntegralToFixedPoint:
+      llvm_unreachable(
+          "rewriteToNumericBoxedExpression CK_IntegralToFixedPoint");  // TODO
     case CK_LValueToRValue:
     case CK_NoOp:
     case CK_UserDefinedConversion:
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -3761,6 +3761,11 @@
                    /*Default=*/false))
     Args.AddLastArg(CmdArgs, options::OPT_ffixed_point);
 
+  if (Args.hasFlag(options::OPT_fsame_fbits,
+                   options::OPT_fno_same_fbits,
+                   /*Default=*/false))
+    Args.AddLastArg(CmdArgs, options::OPT_fsame_fbits);
+
   // Handle -{std, ansi, trigraphs} -- take the last of -{std, ansi}
   // (-ansi is equivalent to -std=c89 or -std=c++98).
   //
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -23,6 +23,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/RecordLayout.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/FixedPoint.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Frontend/CodeGenOptions.h"
 #include "llvm/ADT/Optional.h"
@@ -387,6 +388,9 @@
   Value *VisitIntegerLiteral(const IntegerLiteral *E) {
     return Builder.getInt(E->getValue());
   }
+  Value *VisitFixedPointLiteral(const FixedPointLiteral *E) {
+    return Builder.getInt(E->getValue());
+  }
   Value *VisitFloatingLiteral(const FloatingLiteral *E) {
     return llvm::ConstantFP::get(VMContext, E->getValue());
   }
@@ -1772,6 +1776,15 @@
     return Builder.CreateVectorSplat(NumElements, Elt, "splat");
   }
 
+  case CK_IntegralToFixedPoint: {
+    assert(DestTy->isFixedPointType());
+    assert(E->getType()->isIntegerType());
+    unsigned scale = CGF.getContext().getFixedPointScale(DestTy);
+    return Builder.CreateShl(
+        EmitScalarConversion(Visit(E), E->getType(), DestTy, CE->getExprLoc()),
+        scale, "integral_to_fixed_point");
+  }
+
   case CK_IntegralCast:
   case CK_IntegralToFloating:
   case CK_FloatingToIntegral:
Index: lib/CodeGen/CGExprConstant.cpp
===================================================================
--- lib/CodeGen/CGExprConstant.cpp
+++ lib/CodeGen/CGExprConstant.cpp
@@ -740,6 +740,8 @@
     Expr *subExpr = E->getSubExpr();
 
     switch (E->getCastKind()) {
+    case CK_IntegralToFixedPoint:
+      llvm_unreachable("VisitCastExpr CK_IntegralToFixedPoint");  // TODO
     case CK_ToUnion: {
       // GCC cast to union extension
       assert(E->getType()->isUnionType() &&
Index: lib/CodeGen/CGExprComplex.cpp
===================================================================
--- lib/CodeGen/CGExprComplex.cpp
+++ lib/CodeGen/CGExprComplex.cpp
@@ -509,6 +509,7 @@
   case CK_ZeroToOCLQueue:
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
+  case CK_IntegralToFixedPoint:
     llvm_unreachable("invalid cast kind for complex value");
 
   case CK_FloatingRealToComplex:
Index: lib/CodeGen/CGExprAgg.cpp
===================================================================
--- lib/CodeGen/CGExprAgg.cpp
+++ lib/CodeGen/CGExprAgg.cpp
@@ -684,12 +684,12 @@
       CGF.EmitDynamicCast(LV.getAddress(), cast<CXXDynamicCastExpr>(E));
     else
       CGF.CGM.ErrorUnsupported(E, "non-simple lvalue dynamic_cast");
-    
+
     if (!Dest.isIgnored())
       CGF.CGM.ErrorUnsupported(E, "lvalue dynamic_cast with a destination");
     break;
   }
-      
+
   case CK_ToUnion: {
     // Evaluate even if the destination is ignored.
     if (Dest.isIgnored()) {
@@ -851,6 +851,7 @@
   case CK_ZeroToOCLQueue:
   case CK_AddressSpaceConversion:
   case CK_IntToOCLSampler:
+  case CK_IntegralToFixedPoint:
     llvm_unreachable("cast kind invalid for aggregate types");
   }
 }
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp
+++ lib/CodeGen/CGExpr.cpp
@@ -4051,6 +4051,9 @@
 /// cast from scalar to union.
 LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
   switch (E->getCastKind()) {
+  case CK_IntegralToFixedPoint:
+    llvm_unreachable(
+        "CodeGenFunction::EmitCastLValue CK_IntegralToFixedPoint");  // TODO
   case CK_ToVoid:
   case CK_BitCast:
   case CK_ArrayToPointerDecay:
Index: lib/Basic/Targets.cpp
===================================================================
--- lib/Basic/Targets.cpp
+++ lib/Basic/Targets.cpp
@@ -652,5 +652,7 @@
   if (!Target->validateTarget(Diags))
     return nullptr;
 
+  Target->CheckFixedPointBits();
+
   return Target.release();
 }
Index: lib/Basic/TargetInfo.cpp
===================================================================
--- lib/Basic/TargetInfo.cpp
+++ lib/Basic/TargetInfo.cpp
@@ -40,12 +40,26 @@
   IntWidth = IntAlign = 32;
   LongWidth = LongAlign = 32;
   LongLongWidth = LongLongAlign = 64;
+
+  // Fixed point default bit widths
   ShortAccumWidth = ShortAccumAlign = 16;
   AccumWidth = AccumAlign = 32;
   LongAccumWidth = LongAccumAlign = 64;
   ShortFractWidth = ShortFractAlign = 16;
   FractWidth = FractAlign = 32;
   LongFractWidth = LongFractAlign = 64;
+
+  // Fixed point default integral and fractional bit sizes
+  ShortAccumFBits = ShortFractFBits =  7;
+  ShortAccumIBits = UnsignedShortAccumIBits = 8;
+  AccumFBits = FractFBits = 15;
+  AccumIBits = UnsignedAccumIBits = 16;
+  LongAccumFBits = LongFractFBits = 31;
+  LongAccumIBits = UnsignedLongAccumIBits = 32;
+  UnsignedShortAccumFBits = UnsignedShortFractFBits = 8;
+  UnsignedAccumFBits = UnsignedFractFBits = 16;
+  UnsignedLongAccumFBits = UnsignedLongFractFBits = 32;
+
   SuitableAlign = 64;
   DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
@@ -303,6 +317,7 @@
     return false;
   };
 }
+#include "llvm/Support/raw_ostream.h"
 
 /// adjust - Set forced language options.
 /// Apply changes to the target information with respect to certain
@@ -362,6 +377,17 @@
 
   if (Opts.NewAlignOverride)
     NewAlign = Opts.NewAlignOverride * getCharWidth();
+
+  // Each unsigned fixed point type has the same number of fractional bits as
+  // its corresponding signed type.
+  if (Opts.SameFBits) {
+    UnsignedShortAccumFBits = ShortAccumFBits;
+    UnsignedAccumFBits = AccumFBits;
+    UnsignedLongAccumFBits = LongAccumFBits;
+    UnsignedShortFractFBits = ShortFractFBits;
+    UnsignedFractFBits = FractFBits;
+    UnsignedLongFractFBits = LongFractFBits;
+  }
 }
 
 bool TargetInfo::initFeatureMap(
@@ -716,3 +742,62 @@
 
   return true;
 }
+
+void TargetInfo::CheckFixedPointBits() const {
+  // Check that the number of fractional and integral bits (and maybe sign) can
+  // fit into the bits given for a fixed point type.
+  assert(ShortAccumFBits + ShortAccumIBits + 1 <= ShortAccumWidth);
+  assert(AccumFBits + AccumIBits + 1 <= AccumWidth);
+  assert(LongAccumFBits + LongAccumIBits + 1 <= LongAccumWidth);
+  assert(UnsignedShortAccumFBits + UnsignedShortAccumIBits <= ShortAccumWidth);
+  assert(UnsignedAccumFBits + UnsignedAccumIBits <= AccumWidth);
+  assert(UnsignedLongAccumFBits + UnsignedLongAccumIBits <= LongAccumWidth);
+
+  assert(ShortFractFBits + 1 <= ShortFractWidth);
+  assert(FractFBits + 1 <= FractWidth);
+  assert(LongFractFBits + 1 <= LongFractWidth);
+  assert(UnsignedShortFractFBits <= ShortFractWidth);
+  assert(UnsignedFractFBits <= FractWidth);
+  assert(UnsignedLongFractFBits <= LongFractWidth);
+
+  // Each unsigned fract type has either the same number of fractional bits
+  // as, or one more fractional bit than, its corresponding signed fract type.
+  assert(ShortFractFBits == UnsignedShortFractFBits ||
+         ShortFractFBits == UnsignedShortFractFBits - 1);
+  assert(FractFBits == UnsignedFractFBits ||
+         FractFBits == UnsignedFractFBits - 1);
+  assert(LongFractFBits == UnsignedLongFractFBits ||
+         LongFractFBits == UnsignedLongFractFBits - 1);
+
+  // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+  // fractional bits is nondecreasing for each of the following sets of
+  // fixed-point types:
+  // - signed fract types
+  // - unsigned fract types
+  // - signed accum types
+  // - unsigned accum types.
+  assert(LongFractFBits >= FractFBits && FractFBits >= ShortFractFBits);
+  assert(UnsignedLongFractFBits >= UnsignedFractFBits &&
+         UnsignedFractFBits >= UnsignedShortFractFBits);
+  assert(LongAccumFBits >= AccumFBits && AccumFBits >= ShortAccumFBits);
+  assert(UnsignedLongAccumFBits >= UnsignedAccumFBits &&
+         UnsignedAccumFBits >= UnsignedShortAccumFBits);
+
+  // When arranged in order of increasing rank (see 6.3.1.3a), the number of
+  // integral bits is nondecreasing for each of the following sets of
+  // fixed-point types:
+  // - signed accum types
+  // - unsigned accum types
+  assert(LongAccumIBits >= AccumIBits && AccumIBits >= ShortAccumIBits);
+  assert(UnsignedLongAccumIBits >= UnsignedAccumIBits &&
+         UnsignedAccumIBits >= UnsignedShortAccumIBits);
+
+  // Each signed accum type has at least as many integral bits as its
+  // corresponding unsigned accum type.
+  assert(ShortAccumIBits == UnsignedShortAccumIBits ||
+         ShortAccumIBits == UnsignedShortAccumIBits - 1);
+  assert(AccumIBits == UnsignedAccumIBits ||
+         AccumIBits == UnsignedAccumIBits - 1);
+  assert(LongAccumIBits == UnsignedLongAccumIBits ||
+         LongAccumIBits == UnsignedLongAccumIBits - 1);
+}
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -50,6 +50,7 @@
 #include <cassert>
 #include <cstdint>
 #include <cstring>
+#include <sstream>
 
 using namespace clang;
 
@@ -1936,6 +1937,7 @@
     if (BT->getKind() == BuiltinType::NullPtr) return STK_CPointer;
     if (BT->isInteger()) return STK_Integral;
     if (BT->isFloatingPoint()) return STK_Floating;
+    if (BT->isFixedPointType()) return STK_FixedPoint;
     llvm_unreachable("unknown scalar builtin type");
   } else if (isa<PointerType>(T)) {
     return STK_CPointer;
@@ -3986,3 +3988,19 @@
 CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const {
   return getClass()->getAsCXXRecordDecl()->getMostRecentNonInjectedDecl();
 }
+
+std::string clang::FixedPointValueToString(unsigned Radix, unsigned Scale,
+                                           uint64_t Val) {
+  std::ostringstream s;
+  uint64_t ScaleVal = 1ULL << Scale;
+  uint64_t IntPart = Val / ScaleVal;
+  uint64_t FractPart = Val % ScaleVal;
+
+  s << IntPart;
+  s << ".";
+  do {
+    s << (FractPart * Radix / ScaleVal);
+    FractPart = (FractPart * Radix) % ScaleVal;
+  } while (FractPart);
+  return s.str();
+}
Index: lib/AST/StmtProfile.cpp
===================================================================
--- lib/AST/StmtProfile.cpp
+++ lib/AST/StmtProfile.cpp
@@ -1007,6 +1007,12 @@
   ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
 }
 
+void StmtProfiler::VisitFixedPointLiteral(const FixedPointLiteral *S) {
+  VisitExpr(S);
+  S->getValue().Profile(ID);
+  ID.AddInteger(S->getType()->castAs<BuiltinType>()->getKind());
+}
+
 void StmtProfiler::VisitCharacterLiteral(const CharacterLiteral *S) {
   VisitExpr(S);
   ID.AddInteger(S->getKind());
Index: lib/AST/StmtPrinter.cpp
===================================================================
--- lib/AST/StmtPrinter.cpp
+++ lib/AST/StmtPrinter.cpp
@@ -1529,6 +1529,53 @@
   }
 }
 
+void StmtPrinter::VisitFixedPointLiteral(FixedPointLiteral *Node) {
+  if (Policy.ConstantsAsWritten && printExprAsWritten(OS, Node, Context))
+    return;
+  OS << Node->getValueAsString(/*Radix=*/10);
+
+  switch (Node->getType()->getAs<BuiltinType>()->getKind()) {
+    default:
+      llvm_unreachable("Unexpected type for fixed point literal!");
+    case BuiltinType::ShortFract:
+      OS << "hr";
+      break;
+    case BuiltinType::ShortAccum:
+      OS << "hk";
+      break;
+    case BuiltinType::UShortFract:
+      OS << "uhr";
+      break;
+    case BuiltinType::UShortAccum:
+      OS << "uhk";
+      break;
+    case BuiltinType::Fract:
+      OS << "r";
+      break;
+    case BuiltinType::Accum:
+      OS << "k";
+      break;
+    case BuiltinType::UFract:
+      OS << "ur";
+      break;
+    case BuiltinType::UAccum:
+      OS << "uk";
+      break;
+    case BuiltinType::LongFract:
+      OS << "lr";
+      break;
+    case BuiltinType::LongAccum:
+      OS << "lk";
+      break;
+    case BuiltinType::ULongFract:
+      OS << "ulr";
+      break;
+    case BuiltinType::ULongAccum:
+      OS << "ulk";
+      break;
+  }
+}
+
 static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node,
                                  bool PrintSuffix) {
   SmallString<16> Str;
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -3445,6 +3445,8 @@
   
 recurse:
   switch (E->getStmtClass()) {
+  case Expr::FixedPointLiteralClass:
+    llvm_unreachable("Unknown mangling for FixedPointLiteralClass");
   case Expr::NoStmtClass:
 #define ABSTRACT_STMT(Type)
 #define EXPR(Type, Base)
Index: lib/AST/ExprConstant.cpp
===================================================================
--- lib/AST/ExprConstant.cpp
+++ lib/AST/ExprConstant.cpp
@@ -7220,6 +7220,73 @@
 
   // FIXME: Missing: array subscript of vector, member of vector
 };
+
+class FixedPointExprEvaluator
+    : public ExprEvaluatorBase<FixedPointExprEvaluator> {
+  APValue &Result;
+
+ public:
+  FixedPointExprEvaluator(EvalInfo &info, APValue &result)
+      : ExprEvaluatorBaseTy(info), Result(result) {}
+
+  bool Success(const llvm::APSInt &SI, const Expr *E, APValue &Result) {
+    assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+    assert(SI.isSigned() == E->getType()->isSignedFixedPointType() &&
+           "Invalid evaluation result.");
+    assert(SI.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+           "Invalid evaluation result.");
+    Result = APValue(SI);
+    return true;
+  }
+  bool Success(const llvm::APSInt &SI, const Expr *E) {
+    return Success(SI, E, Result);
+  }
+
+  bool Success(const llvm::APInt &I, const Expr *E, APValue &Result) {
+    assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+    assert(I.getBitWidth() == Info.Ctx.getIntWidth(E->getType()) &&
+           "Invalid evaluation result.");
+    Result = APValue(APSInt(I));
+    Result.getInt().setIsUnsigned(E->getType()->isUnsignedFixedPointType());
+    return true;
+  }
+  bool Success(const llvm::APInt &I, const Expr *E) {
+    return Success(I, E, Result);
+  }
+
+  bool Success(uint64_t Value, const Expr *E, APValue &Result) {
+    assert(E->getType()->isFixedPointType() && "Invalid evaluation result.");
+    Result = APValue(Info.Ctx.MakeIntValue(Value, E->getType()));
+    return true;
+  }
+  bool Success(uint64_t Value, const Expr *E) {
+    return Success(Value, E, Result);
+  }
+
+  bool Success(CharUnits Size, const Expr *E) {
+    return Success(Size.getQuantity(), E);
+  }
+
+  bool Success(const APValue &V, const Expr *E) {
+    if (V.isLValue() || V.isAddrLabelDiff()) {
+      Result = V;
+      return true;
+    }
+    return Success(V.getInt(), E);
+  }
+
+  bool ZeroInitialization(const Expr *E) { return Success(0, E); }
+
+  //===--------------------------------------------------------------------===//
+  //                            Visitor Methods
+  //===--------------------------------------------------------------------===//
+
+  bool VisitFixedPointLiteral(const FixedPointLiteral *E) {
+    return Success(E->getValue(), E);
+  }
+
+  bool VisitUnaryOperator(const UnaryOperator *E);
+};
 } // end anonymous namespace
 
 /// EvaluateIntegerOrLValue - Evaluate an rvalue integral-typed expression, and
@@ -9166,6 +9233,9 @@
   QualType SrcType = SubExpr->getType();
 
   switch (E->getCastKind()) {
+  case CK_IntegralToFixedPoint:
+    llvm_unreachable(
+        "IntExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint");  // TODO
   case CK_BaseToDerived:
   case CK_DerivedToBase:
   case CK_UncheckedDerivedToBase:
@@ -9342,6 +9412,37 @@
   return Success(E->getValue(), E);
 }
 
+bool FixedPointExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) {
+  switch (E->getOpcode()) {
+    default:
+      // Invalid unary operators
+      return Error(E);
+    case UO_Plus:
+      // The result is just the value.
+      return Visit(E->getSubExpr());
+    case UO_Minus: {
+      if (!Visit(E->getSubExpr())) return false;
+      if (!Result.isInt()) return Error(E);
+      const APSInt &Value = Result.getInt();
+      if (Value.isSigned() && Value.isMinSignedValue() && E->canOverflow()) {
+        std::string Val =
+            "-" + FixedPointValueToString(
+                      /*Radix=*/10, Info.Ctx.getTypeInfo(E->getType()).Width,
+                      Value.getExtValue());
+        Info.CCEDiag(E, diag::note_constexpr_overflow) << Val << E->getType();
+        if (Info.noteUndefinedBehavior()) return false;
+      }
+      return Success(-Value, E);
+    }
+    case UO_LNot: {
+      bool bres;
+      if (!EvaluateAsBooleanCondition(E->getSubExpr(), bres, Info))
+        return false;
+      return Success(!bres, E);
+    }
+  }
+}
+
 //===----------------------------------------------------------------------===//
 // Float Evaluation
 //===----------------------------------------------------------------------===//
@@ -9659,6 +9760,9 @@
 bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) {
 
   switch (E->getCastKind()) {
+  case CK_IntegralToFixedPoint:
+    llvm_unreachable(
+        "ComplexExprEvaluator::VisitCastExpr CK_IntegralToFixedPoint");  // TODO
   case CK_BitCast:
   case CK_BaseToDerived:
   case CK_DerivedToBase:
@@ -10193,6 +10297,8 @@
     if (!EvaluateComplex(E, C, Info))
       return false;
     C.moveInto(Result);
+  } else if (T->isFixedPointType()) {
+    if (!FixedPointExprEvaluator(Info, Result).Visit(E)) return false;
   } else if (T->isMemberPointerType()) {
     MemberPtr P;
     if (!EvaluateMemberPointer(E, P, Info))
@@ -10641,6 +10747,7 @@
   case Expr::GenericSelectionExprClass:
     return CheckICE(cast<GenericSelectionExpr>(E)->getResultExpr(), Ctx);
   case Expr::IntegerLiteralClass:
+  case Expr::FixedPointLiteralClass:
   case Expr::CharacterLiteralClass:
   case Expr::ObjCBoolLiteralExprClass:
   case Expr::CXXBoolLiteralExprClass:
Index: lib/AST/ExprClassification.cpp
===================================================================
--- lib/AST/ExprClassification.cpp
+++ lib/AST/ExprClassification.cpp
@@ -161,6 +161,7 @@
   case Expr::ShuffleVectorExprClass:
   case Expr::ConvertVectorExprClass:
   case Expr::IntegerLiteralClass:
+  case Expr::FixedPointLiteralClass:
   case Expr::CharacterLiteralClass:
   case Expr::AddrLabelExprClass:
   case Expr::CXXDeleteExprClass:
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -755,6 +755,30 @@
   return new (C) IntegerLiteral(Empty);
 }
 
+FixedPointLiteral::FixedPointLiteral(const ASTContext &C, const llvm::APInt &V,
+                                     QualType type, SourceLocation l,
+                                     unsigned Scale)
+    : Expr(FixedPointLiteralClass, type, VK_RValue, OK_Ordinary, false, false,
+           false, false),
+      Loc(l), Scale(Scale) {
+  assert(type->isFixedPointType() && "Illegal type in FixedPointLiteral");
+  assert(V.getBitWidth() == C.getTypeInfo(type).Width &&
+         "Fixed point type is not the correct size for constant.");
+  setValue(C, V);
+}
+
+FixedPointLiteral *FixedPointLiteral::CreateFromRawInt(const ASTContext &C,
+                                                       const llvm::APInt &V,
+                                                       QualType type,
+                                                       SourceLocation l,
+                                                       unsigned Scale) {
+  return new (C) FixedPointLiteral(C, V, type, l, Scale);
+}
+
+std::string FixedPointLiteral::getValueAsString(unsigned Radix) const {
+  return FixedPointValueToString(Radix, Scale, getValue().getZExtValue());
+}
+
 FloatingLiteral::FloatingLiteral(const ASTContext &C, const llvm::APFloat &V,
                                  bool isexact, QualType Type, SourceLocation L)
   : Expr(FloatingLiteralClass, Type, VK_RValue, OK_Ordinary, false, false,
@@ -1610,6 +1634,7 @@
   case CK_ZeroToOCLEvent:
   case CK_ZeroToOCLQueue:
   case CK_IntToOCLSampler:
+  case CK_IntegralToFixedPoint:
     assert(!getType()->isBooleanType() && "unheralded conversion to bool");
     goto CheckNoBasePath;
 
@@ -2991,6 +3016,7 @@
   case ObjCIvarRefExprClass:
   case PredefinedExprClass:
   case IntegerLiteralClass:
+  case FixedPointLiteralClass:
   case FloatingLiteralClass:
   case ImaginaryLiteralClass:
   case StringLiteralClass:
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -525,6 +525,7 @@
     void VisitPredefinedExpr(const PredefinedExpr *Node);
     void VisitCharacterLiteral(const CharacterLiteral *Node);
     void VisitIntegerLiteral(const IntegerLiteral *Node);
+    void VisitFixedPointLiteral(const FixedPointLiteral *Node);
     void VisitFloatingLiteral(const FloatingLiteral *Node);
     void VisitStringLiteral(const StringLiteral *Str);
     void VisitInitListExpr(const InitListExpr *ILE);
@@ -2177,6 +2178,13 @@
   OS << " " << Node->getValue().toString(10, isSigned);
 }
 
+void ASTDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
+  VisitExpr(Node);
+
+  ColorScope Color(*this, ValueColor);
+  OS << " " << Node->getValueAsString(/*Radix=*/10);
+}
+
 void ASTDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
   VisitExpr(Node);
   ColorScope Color(*this, ValueColor);
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -10131,3 +10131,92 @@
 clang::LazyGenerationalUpdatePtr<
     const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue(
         const clang::ASTContext &Ctx, Decl *Value);
+
+unsigned char ASTContext::getFixedPointScale(const QualType &Ty) const {
+  assert(Ty->isFixedPointType());
+
+  const auto *BT = Ty->getAs<BuiltinType>();
+  const TargetInfo &Target = getTargetInfo();
+  switch (BT->getKind()) {
+    default:
+      llvm_unreachable("Not a fixed point type!");
+    case BuiltinType::ShortAccum:
+    case BuiltinType::SatShortAccum:
+      return Target.getShortAccumFBits();
+    case BuiltinType::Accum:
+    case BuiltinType::SatAccum:
+      return Target.getAccumFBits();
+    case BuiltinType::LongAccum:
+    case BuiltinType::SatLongAccum:
+      return Target.getLongAccumFBits();
+    case BuiltinType::UShortAccum:
+    case BuiltinType::SatUShortAccum:
+      return Target.getUnsignedShortAccumFBits();
+    case BuiltinType::UAccum:
+    case BuiltinType::SatUAccum:
+      return Target.getUnsignedAccumFBits();
+    case BuiltinType::ULongAccum:
+    case BuiltinType::SatULongAccum:
+      return Target.getUnsignedLongAccumFBits();
+    case BuiltinType::ShortFract:
+    case BuiltinType::SatShortFract:
+      return Target.getShortFractFBits();
+    case BuiltinType::Fract:
+    case BuiltinType::SatFract:
+      return Target.getFractFBits();
+    case BuiltinType::LongFract:
+    case BuiltinType::SatLongFract:
+      return Target.getLongFractFBits();
+    case BuiltinType::UShortFract:
+    case BuiltinType::SatUShortFract:
+      return Target.getUnsignedShortFractFBits();
+    case BuiltinType::UFract:
+    case BuiltinType::SatUFract:
+      return Target.getUnsignedFractFBits();
+    case BuiltinType::ULongFract:
+    case BuiltinType::SatULongFract:
+      return Target.getUnsignedLongFractFBits();
+  }
+}
+
+unsigned char ASTContext::getFixedPointIBits(const QualType &Ty) const {
+  assert(Ty->isFixedPointType());
+
+  const auto *BT = Ty->getAs<BuiltinType>();
+  const TargetInfo &Target = getTargetInfo();
+  switch (BT->getKind()) {
+    default:
+      llvm_unreachable("Not a fixed point type!");
+    case BuiltinType::ShortAccum:
+    case BuiltinType::SatShortAccum:
+      return Target.getShortAccumIBits();
+    case BuiltinType::Accum:
+    case BuiltinType::SatAccum:
+      return Target.getAccumIBits();
+    case BuiltinType::LongAccum:
+    case BuiltinType::SatLongAccum:
+      return Target.getLongAccumIBits();
+    case BuiltinType::UShortAccum:
+    case BuiltinType::SatUShortAccum:
+      return Target.getUnsignedShortAccumIBits();
+    case BuiltinType::UAccum:
+    case BuiltinType::SatUAccum:
+      return Target.getUnsignedAccumIBits();
+    case BuiltinType::ULongAccum:
+    case BuiltinType::SatULongAccum:
+      return Target.getUnsignedLongAccumIBits();
+    case BuiltinType::ShortFract:
+    case BuiltinType::SatShortFract:
+    case BuiltinType::Fract:
+    case BuiltinType::SatFract:
+    case BuiltinType::LongFract:
+    case BuiltinType::SatLongFract:
+    case BuiltinType::UShortFract:
+    case BuiltinType::SatUShortFract:
+    case BuiltinType::UFract:
+    case BuiltinType::SatUFract:
+    case BuiltinType::ULongFract:
+    case BuiltinType::SatULongFract:
+      return 0;
+  }
+}
Index: include/clang/Lex/LiteralSupport.h
===================================================================
--- include/clang/Lex/LiteralSupport.h
+++ include/clang/Lex/LiteralSupport.h
@@ -50,7 +50,7 @@
 
   unsigned radix;
 
-  bool saw_exponent, saw_period, saw_ud_suffix;
+  bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix;
 
   SmallString<32> UDSuffixBuf;
 
@@ -69,11 +69,16 @@
   bool isFloat128 : 1;      // 1.0q
   uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64.
 
+  bool isFract : 1;         // 1.0hr/r/lr/uhr/ur/ulr
+  bool isAccum : 1;         // 1.0hk/k/lk/uhk/uk/ulk
+
+  bool isFixedPointLiteral() const { return saw_fixed_point_suffix; }
+
   bool isIntegerLiteral() const {
-    return !saw_period && !saw_exponent;
+    return !saw_period && !saw_exponent && !isFixedPointLiteral();
   }
   bool isFloatingLiteral() const {
-    return saw_period || saw_exponent;
+    return (saw_period || saw_exponent) && !isFixedPointLiteral();
   }
 
   bool hasUDSuffix() const {
@@ -105,6 +110,11 @@
   /// literal exactly, and false otherwise.
   llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result);
 
+  /// GetFixedPointValue - Convert this numeric literal value into a
+  /// scaled integer that represents this value. Returns true if an overflow
+  /// occurred when calculating the integral part of the scaled integer.
+  bool GetFixedPointValue(uint64_t &Val, unsigned Scale);
+
 private:
 
   void ParseNumberStartingWithZero(SourceLocation TokLoc);
@@ -157,7 +167,6 @@
       ptr++;
     return ptr;
   }
-
 };
 
 /// CharLiteralParser - Perform interpretation and semantic analysis of a
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -891,6 +891,10 @@
                    Flags<[CC1Option]>, HelpText<"Enable fixed point types">;
 def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>,
                       HelpText<"Disable fixed point types">;
+def fsame_fbits : Flag<["-"], "fsame-fbits">, Group<f_Group>,
+                  Flags<[CC1Option]>,
+		  HelpText<"Force each unsigned fixed point type to have the same number of fractional bits as its corresponding signed type">;
+def fno_same_fbits : Flag<["-"], "fno-same-fbits">, Group<f_Group>;
 
 // Begin sanitizer flags. These should all be core options exposed in all driver
 // modes.
Index: include/clang/Basic/TargetInfo.h
===================================================================
--- include/clang/Basic/TargetInfo.h
+++ include/clang/Basic/TargetInfo.h
@@ -74,12 +74,31 @@
   unsigned char LargeArrayMinWidth, LargeArrayAlign;
   unsigned char LongWidth, LongAlign;
   unsigned char LongLongWidth, LongLongAlign;
+
+  // Fixed point bit widths
   unsigned char ShortAccumWidth, ShortAccumAlign;
   unsigned char AccumWidth, AccumAlign;
   unsigned char LongAccumWidth, LongAccumAlign;
   unsigned char ShortFractWidth, ShortFractAlign;
   unsigned char FractWidth, FractAlign;
   unsigned char LongFractWidth, LongFractAlign;
+
+  // Fixed point integral and fractional bit sizes
+  // Saturated types share the same integral/fractional bits as their
+  // corresponding unsaturated types.
+  unsigned char ShortAccumFBits, ShortAccumIBits;
+  unsigned char AccumFBits, AccumIBits;
+  unsigned char LongAccumFBits, LongAccumIBits;
+  unsigned char UnsignedShortAccumFBits, UnsignedShortAccumIBits;
+  unsigned char UnsignedAccumFBits, UnsignedAccumIBits;
+  unsigned char UnsignedLongAccumFBits, UnsignedLongAccumIBits;
+  unsigned char ShortFractFBits;
+  unsigned char FractFBits;
+  unsigned char LongFractFBits;
+  unsigned char UnsignedShortFractFBits;
+  unsigned char UnsignedFractFBits;
+  unsigned char UnsignedLongFractFBits;
+
   unsigned char SuitableAlign;
   unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
@@ -394,6 +413,60 @@
   unsigned getLongFractWidth() const { return LongFractWidth; }
   unsigned getLongFractAlign() const { return LongFractAlign; }
 
+  /// getShortAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'signed short _Accum' type.
+  unsigned getShortAccumFBits() const { return ShortAccumFBits; }
+  unsigned getShortAccumIBits() const { return ShortAccumIBits; }
+
+  /// getAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'signed _Accum' type.
+  unsigned getAccumFBits() const { return AccumFBits; }
+  unsigned getAccumIBits() const { return AccumIBits; }
+
+  /// getLongAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'signed long _Accum' type.
+  unsigned getLongAccumFBits() const { return LongAccumFBits; }
+  unsigned getLongAccumIBits() const { return LongAccumIBits; }
+
+  /// getUnsignedShortAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned short _Accum' type.
+  unsigned getUnsignedShortAccumFBits() const { return UnsignedShortAccumFBits; }
+  unsigned getUnsignedShortAccumIBits() const { return UnsignedShortAccumIBits; }
+
+  /// getUnsignedAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned _Accum' type.
+  unsigned getUnsignedAccumFBits() const { return UnsignedAccumFBits; }
+  unsigned getUnsignedAccumIBits() const { return UnsignedAccumIBits; }
+
+  /// getUnsignedLongAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned long _Accum' type.
+  unsigned getUnsignedLongAccumFBits() const { return UnsignedLongAccumFBits; }
+  unsigned getUnsignedLongAccumIBits() const { return UnsignedLongAccumIBits; }
+
+  /// getShortFractFBits - Return the number of fractional bits
+  /// in a 'signed short _Fract' type.
+  unsigned getShortFractFBits() const { return ShortFractFBits; }
+
+  /// getFractFBits - Return the number of fractional bits
+  /// in a 'signed _Fract' type.
+  unsigned getFractFBits() const { return FractFBits; }
+
+  /// getLongFractFBits - Return the number of fractional bits
+  /// in a 'signed long _Fract' type.
+  unsigned getLongFractFBits() const { return LongFractFBits; }
+
+  /// getUnsignedShortFractFBits - Return the number of fractional bits
+  /// in a 'unsigned short _Fract' type.
+  unsigned getUnsignedShortFractFBits() const { return UnsignedShortFractFBits; }
+
+  /// getUnsignedFractFBits - Return the number of fractional bits
+  /// in a 'unsigned _Fract' type.
+  unsigned getUnsignedFractFBits() const { return UnsignedFractFBits; }
+
+  /// getUnsignedLongFractFBits - Return the number of fractional bits
+  /// in a 'unsigned long _Fract' type.
+  unsigned getUnsignedLongFractFBits() const { return UnsignedLongFractFBits; }
+
   /// Determine whether the __int128 type is supported on this target.
   virtual bool hasInt128Type() const {
     return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
@@ -1189,6 +1262,11 @@
   virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const {
     return None;
   }
+
+ private:
+  // Assert the values for the fractional and integral bits for each fixed point
+  // type follow the restrictions given in clause 6.2.6.3 of N1169.
+  void CheckFixedPointBits() const;
 };
 
 }  // end namespace clang
Index: include/clang/Basic/StmtNodes.td
===================================================================
--- include/clang/Basic/StmtNodes.td
+++ include/clang/Basic/StmtNodes.td
@@ -57,6 +57,7 @@
 def PredefinedExpr : DStmt<Expr>;
 def DeclRefExpr : DStmt<Expr>;
 def IntegerLiteral : DStmt<Expr>;
+def FixedPointLiteral : DStmt<Expr>;
 def FloatingLiteral : DStmt<Expr>;
 def ImaginaryLiteral : DStmt<Expr>;
 def StringLiteral : DStmt<Expr>;
Index: include/clang/Basic/LangOptions.def
===================================================================
--- include/clang/Basic/LangOptions.def
+++ include/clang/Basic/LangOptions.def
@@ -303,6 +303,8 @@
 COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions")
 
 LANGOPT(FixedPoint, 1, 0, "fixed point types")
+LANGOPT(SameFBits, 1, 0,
+        "unsigned and signed fixed point type having the same number of fractional bits")
 
 #undef LANGOPT
 #undef COMPATIBLE_LANGOPT
Index: include/clang/Basic/DiagnosticCommonKinds.td
===================================================================
--- include/clang/Basic/DiagnosticCommonKinds.td
+++ include/clang/Basic/DiagnosticCommonKinds.td
@@ -168,6 +168,10 @@
                           InGroup<GccCompat>;
 def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">,
                             InGroup<GccCompat>;
+def err_integral_part_on_fract : Error<"a _Fract type cannot have an "
+  "integral part">;
+def err_accum_too_large : Error<
+  "this value is too large for this %select{signed|unsigned}0 _Accum type">;
 def err_fixed_point_not_enabled : Error<"compile with "
   "'-ffixed-point' to enable fixed point types">;
 
Index: include/clang/AST/Type.h
===================================================================
--- include/clang/AST/Type.h
+++ include/clang/AST/Type.h
@@ -1918,7 +1918,8 @@
     STK_Integral,
     STK_Floating,
     STK_IntegralComplex,
-    STK_FloatingComplex
+    STK_FloatingComplex,
+    STK_FixedPoint
   };
 
   /// Given that this is a scalar type, classify it.
@@ -6546,6 +6547,11 @@
   return cast<PointerType>(Decayed)->getPointeeType();
 }
 
+// Return the string representation of an unsigned fixed point type, represented
+// as a scaled integer.
+std::string FixedPointValueToString(unsigned Radix, unsigned Scale,
+                                    uint64_t Val);
+
 } // namespace clang
 
 #endif // LLVM_CLANG_AST_TYPE_H
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -2585,6 +2585,7 @@
 
 // These literals (all of them) do not need any action.
 DEF_TRAVERSE_STMT(IntegerLiteral, {})
+DEF_TRAVERSE_STMT(FixedPointLiteral, {})
 DEF_TRAVERSE_STMT(CharacterLiteral, {})
 DEF_TRAVERSE_STMT(FloatingLiteral, {})
 DEF_TRAVERSE_STMT(ImaginaryLiteral, {})
Index: include/clang/AST/OperationKinds.def
===================================================================
--- include/clang/AST/OperationKinds.def
+++ include/clang/AST/OperationKinds.def
@@ -197,6 +197,10 @@
 ///    float f = i;
 CAST_OPERATION(IntegralToFloating)
 
+/// CK_IntegralToFixedPoint - Integral to fixed point.
+///    (short _Accum) i;
+CAST_OPERATION(IntegralToFixedPoint)
+
 /// CK_FloatingToIntegral - Floating point to integral.  Rounds
 /// towards zero, discarding any fractional component.
 ///    (int) f
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -1351,6 +1351,47 @@
   }
 };
 
+class FixedPointLiteral : public Expr, public APIntStorage {
+  SourceLocation Loc;
+  unsigned Scale;
+
+  /// \brief Construct an empty integer literal.
+  explicit FixedPointLiteral(EmptyShell Empty)
+      : Expr(FixedPointLiteralClass, Empty) {}
+
+ public:
+  FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type,
+                    SourceLocation l, unsigned Scale);
+
+  // Store the int as is without any bit shifting.
+  static FixedPointLiteral *CreateFromRawInt(const ASTContext &C,
+                                             const llvm::APInt &V,
+                                             QualType type, SourceLocation l,
+                                             unsigned Scale);
+
+  SourceLocation getLocStart() const LLVM_READONLY { return Loc; }
+  SourceLocation getLocEnd() const LLVM_READONLY { return Loc; }
+
+  /// \brief Retrieve the location of the literal.
+  SourceLocation getLocation() const { return Loc; }
+
+  void setLocation(SourceLocation Location) { Loc = Location; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == FixedPointLiteralClass;
+  }
+
+  std::string getValueAsString(unsigned Radix) const;
+
+  // Iterators
+  child_range children() {
+    return child_range(child_iterator(), child_iterator());
+  }
+  const_child_range children() const {
+    return const_child_range(const_child_iterator(), const_child_iterator());
+  }
+};
+
 class CharacterLiteral : public Expr {
 public:
   enum CharacterKind {
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -1947,6 +1947,9 @@
     return getQualifiedType(type.getUnqualifiedType(), Qs);
   }
 
+  unsigned char getFixedPointScale(const QualType &Ty) const;
+  unsigned char getFixedPointIBits(const QualType &Ty) const;
+
   DeclarationNameInfo getNameForTemplate(TemplateName Name,
                                          SourceLocation NameLoc) const;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to