leonardchan updated this revision to Diff 151433.
leonardchan added a comment.

- Removed the functions for performing casting between fixed point types to a 
common type when performing a binary operation since operations should be 
performed on the types as is. Also this patch is meant more for declaring fixed 
point literals. Binary operations will come in later patches, but it's good to 
catch these types of things early.
- Removed `fixed_point_validation.c` since that was the test for the logic 
described above.


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_bit_widths.c
  test/Frontend/fixed_point_declarations.c
  test/Frontend/fixed_point_errors.c
  test/Frontend/fixed_point_same_fbits.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_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 i8  -128, i8* %u_short_fract, align 1
+// DEFAULT: store i16 -32768, i16* %u_fract, align 2
+// DEFAULT: store i32 -2147483648, i32* %u_long_fract, align 4
+
+// 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 i8  64, i8* %u_short_fract, align 1
+// SAME: store i16 16384, i16* %u_fract, align 2
+// SAME: store i32 1073741824, i32* %u_long_fract, align 4
+}
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 fixed point type}}
+unsigned short _Accum u_short_accum = 256.0uhk;         // expected-error{{this value is too large for this fixed point type}}
+signed _Accum s_accum = 65536.0k;                       // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum u_accum = 65536.0uk;                    // expected-error{{this value is too large for this fixed point type}}
+signed long _Accum s_long_accum = 4294967296.0lk;       // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum u_long_accum = 4294967296.0ulk;    // expected-error{{this value is too large for this fixed point type}}
+
+// Large values from decimal exponents
+short _Accum          short_accum_exp   = 2.56e2hk;           // expected-error{{this value is too large for this fixed point type}}
+_Accum                accum_exp         = 6.5536e4k;          // expected-error{{this value is too large for this fixed point type}}
+long _Accum           long_accum_exp    = 4.294967296e9lk;    // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Accum u_short_accum_exp = 2.56e2uhk;          // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum       u_accum_exp       = 6.5536e4uk;         // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum  u_long_accum_exp  = 4.294967296e9ulk;   // expected-error{{this value is too large for this fixed point type}}
+
+// Large value from hexidecimal exponents
+short _Accum          short_accum_hex_exp   = 0x1p8hk;        // expected-error{{this value is too large for this fixed point type}}
+_Accum                accum_hex_exp         = 0x1p16k;        // expected-error{{this value is too large for this fixed point type}}
+long _Accum           long_accum_hex_exp    = 0x1p32lk;       // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Accum u_short_accum_hex_exp = 0x1p8uhk;       // expected-error{{this value is too large for this fixed point type}}
+unsigned _Accum       u_accum_hex_exp       = 0x1p16uk;       // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Accum  u_long_accum_hex_exp  = 0x1p32ulk;      // expected-error{{this value is too large for this fixed point type}}
+
+// Very large exponent
+_Accum x = 1e1000000000000000000000000000000000k;   // expected-error{{this value is too large for this fixed point 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{{this value is too large for this fixed point type}}
+_Fract                fract_above_1          = 1.1r;    // expected-error{{this value is too large for this fixed point type}}
+long _Fract           long_fract_above_1     = 1.1lr;   // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Fract u_short_fract_above_1  = 1.1uhr;  // expected-error{{this value is too large for this fixed point type}}
+unsigned _Fract       u_fract_above_1        = 1.1ur;   // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Fract  u_long_fract_above_1   = 1.1ulr;  // expected-error{{this value is too large for this fixed point type}}
+
+short _Fract          short_fract_hex_exp   = 0x0.fp1hr;      // expected-error{{this value is too large for this fixed point type}}
+_Fract                fract_hex_exp         = 0x0.fp1r;       // expected-error{{this value is too large for this fixed point type}}
+long _Fract           long_fract_hex_exp    = 0x0.fp1lr;      // expected-error{{this value is too large for this fixed point type}}
+unsigned short _Fract u_short_fract_hex_exp = 0x0.fp1uhr;     // expected-error{{this value is too large for this fixed point type}}
+unsigned _Fract       u_fract_hex_exp       = 0x0.fp1ur;      // expected-error{{this value is too large for this fixed point type}}
+unsigned long _Fract  u_long_fract_hex_exp  = 0x0.fp1ulr;     // expected-error{{this value is too large for this fixed point type}}
+
 /* 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 i8  0, align 1
+signed _Fract         s_fract;        // CHECK-DAG: @s_fract        = {{.*}}global i16 0, align 2
+signed long _Fract    s_long_fract;   // CHECK-DAG: @s_long_fract   = {{.*}}global i32 0, align 4
+unsigned short _Fract u_short_fract;  // CHECK-DAG: @u_short_fract  = {{.*}}global i8  0, align 1
+unsigned _Fract       u_fract;        // CHECK-DAG: @u_fract        = {{.*}}global i16 0, align 2
+unsigned long _Fract  u_long_fract;   // CHECK-DAG: @u_long_fract   = {{.*}}global i32 0, align 4
+
+// 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 i8  0, align 1
+_Fract        fract;                  // CHECK-DAG: @fract          = {{.*}}global i16 0, align 2
+long _Fract   long_fract;             // CHECK-DAG: @long_fract     = {{.*}}global i32 0, align 4
+
+// 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 i8  0, align 1
+_Sat signed _Fract         sat_s_fract;        // CHECK-DAG: @sat_s_fract        = {{.*}}global i16 0, align 2
+_Sat signed long _Fract    sat_s_long_fract;   // CHECK-DAG: @sat_s_long_fract   = {{.*}}global i32 0, align 4
+_Sat unsigned short _Fract sat_u_short_fract;  // CHECK-DAG: @sat_u_short_fract  = {{.*}}global i8  0, align 1
+_Sat unsigned _Fract       sat_u_fract;        // CHECK-DAG: @sat_u_fract        = {{.*}}global i16 0, align 2
+_Sat unsigned long _Fract  sat_u_long_fract;   // CHECK-DAG: @sat_u_long_fract   = {{.*}}global i32 0, align 4
+
+// 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 i8  0, align 1
+_Sat _Fract        sat_fract;                  // CHECK-DAG: @sat_fract          = {{.*}}global i16 0, align 2
+_Sat long _Fract   sat_long_fract;             // CHECK-DAG: @sat_long_fract     = {{.*}}global i32 0, align 4
+
+/* 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 i8  64, align 1
+_Fract        fract_literal       = 0.5r;     // CHECK-DAG: @fract_literal        = {{.*}}global i16 16384, align 2
+long _Fract   long_fract_literal  = 0.5lr;    // CHECK-DAG: @long_fract_literal   = {{.*}}global i32 1073741824, align 4
+
+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 i8  -128, align 1
+unsigned _Fract        u_fract_literal       = 0.5ur;     // CHECK-DAG: @u_fract_literal        = {{.*}}global i16 -32768, align 2
+unsigned long _Fract   u_long_fract_literal  = 0.5ulr;    // CHECK-DAG: @u_long_fract_literal   = {{.*}}global i32 -2147483648, align 4
+
+// 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 i8  127, align 1
+_Fract                fract_max         = 0.9999999999999999r;            // CHECK-DAG: @fract_max         = {{.*}}global i16 32767, align 2
+long _Fract           long_fract_max    = 0.9999999999999999lr;           // CHECK-DAG: @long_fract_max    = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_max = 0.9999999999999999uhr;          // CHECK-DAG: @u_short_fract_max = {{.*}}global i8  -1, align 1
+unsigned _Fract       u_fract_max       = 0.9999999999999999ur;           // CHECK-DAG: @u_fract_max       = {{.*}}global i16 -1, align 2
+unsigned long _Fract  u_long_fract_max  = 0.9999999999999999ulr;          // CHECK-DAG: @u_long_fract_max  = {{.*}}global i32 -1, align 4
+
+// Fracts may be exactly one but evaluate to the Fract max
+short _Fract          short_fract_one   = 1.0hr;    // CHECK-DAG: @short_fract_one    = {{.*}}global i8  127, align 1
+_Fract                fract_one         = 1.0r;     // CHECK-DAG: @fract_one          = {{.*}}global i16 32767, align 2
+long _Fract           long_fract_one    = 1.0lr;    // CHECK-DAG: @long_fract_one     = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_one = 1.0uhr;   // CHECK-DAG: @u_short_fract_one  = {{.*}}global i8  -1, align 1
+unsigned _Fract       u_fract_one       = 1.0ur;    // CHECK-DAG: @u_fract_one        = {{.*}}global i16 -1, align 2
+unsigned long _Fract  u_long_fract_one  = 1.0ulr;   // CHECK-DAG: @u_long_fract_one   = {{.*}}global i32 -1, align 4
+
+short _Fract          short_fract_exp_one   = 0.1e1hr;    // CHECK-DAG: @short_fract_exp_one    = {{.*}}global i8  127, align 1
+_Fract                fract_exp_one         = 0.1e1r;     // CHECK-DAG: @fract_exp_one          = {{.*}}global i16 32767, align 2
+long _Fract           long_fract_exp_one    = 0.1e1lr;    // CHECK-DAG: @long_fract_exp_one     = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_exp_one = 0.1e1uhr;   // CHECK-DAG: @u_short_fract_exp_one  = {{.*}}global i8  -1, align 1
+unsigned _Fract       u_fract_exp_one       = 0.1e1ur;    // CHECK-DAG: @u_fract_exp_one        = {{.*}}global i16 -1, align 2
+unsigned long _Fract  u_long_fract_exp_one  = 0.1e1ulr;   // CHECK-DAG: @u_long_fract_exp_one   = {{.*}}global i32 -1, align 4
+
+short _Fract          short_fract_hex_exp_one   = 0x0.8p1hr;    // CHECK-DAG: @short_fract_hex_exp_one    = {{.*}}global i8  127, align 1
+_Fract                fract_hex_exp_one         = 0x0.8p1r;     // CHECK-DAG: @fract_hex_exp_one          = {{.*}}global i16 32767, align 2
+long _Fract           long_fract_hex_exp_one    = 0x0.8p1lr;    // CHECK-DAG: @long_fract_hex_exp_one     = {{.*}}global i32 2147483647, align 4
+unsigned short _Fract u_short_fract_hex_exp_one = 0x0.8p1uhr;   // CHECK-DAG: @u_short_fract_hex_exp_one  = {{.*}}global i8  -1, align 1
+unsigned _Fract       u_fract_hex_exp_one       = 0x0.8p1ur;    // CHECK-DAG: @u_fract_hex_exp_one        = {{.*}}global i16 -1, align 2
+unsigned long _Fract  u_long_fract_hex_exp_one  = 0x0.8p1ulr;   // CHECK-DAG: @u_long_fract_hex_exp_one   = {{.*}}global i32 -1, align 4
+
+// 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 i8  1, align 1
+_Fract                fract_eps         = 0x1p-15r;         // CHECK-DAG: @fract_eps         = {{.*}}global i16 1, align 2
+long _Fract           long_fract_eps    = 0x1p-31lr;        // CHECK-DAG: @long_fract_eps    = {{.*}}global i32 1, align 4
+unsigned short _Fract u_short_fract_eps = 0x1p-8uhr;        // CHECK-DAG: @u_short_fract_eps = {{.*}}global i8  1, align 1
+unsigned _Fract       u_fract_eps       = 0x1p-16ur;        // CHECK-DAG: @u_fract_eps       = {{.*}}global i16 1, align 2
+unsigned long _Fract  u_long_fract_eps  = 0x1p-32ulr;       // CHECK-DAG: @u_long_fract_eps  = {{.*}}global i32 1, align 4
Index: test/Frontend/fixed_point_bit_widths.c
===================================================================
--- test/Frontend/fixed_point_bit_widths.c
+++ test/Frontend/fixed_point_bit_widths.c
@@ -44,12 +44,12 @@
 int align_SF  = __alignof(signed _Fract);
 int align_SlF = __alignof(signed long _Fract);
 
-// CHECK-NEXT: @size_SsF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_SF   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_SlF  = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_SF  = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_SlF = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_SsF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SF   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SlF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SlF = {{.*}}global i{{[0-9]+}} 4
 
 /* Primary unsigned _Fract */
 
@@ -60,12 +60,12 @@
 int align_UF  = __alignof(unsigned _Fract);
 int align_UlF = __alignof(unsigned long _Fract);
 
-// CHECK-NEXT: @size_UsF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_UF   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_UlF  = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_UF  = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_UlF = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_UsF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_UF   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_UlF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_UsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_UF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_UlF = {{.*}}global i{{[0-9]+}} 4
 
 /* Aliased _Accum */
 
@@ -92,12 +92,12 @@
 int align_F  = __alignof(_Fract);
 int align_lF = __alignof(long _Fract);
 
-// CHECK-NEXT: @size_sF   = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_F    = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_lF   = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_sF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_F   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_lF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_sF   = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_F    = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_lF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_sF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_F   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_lF  = {{.*}}global i{{[0-9]+}} 4
 
 /* Saturated signed _Accum */
 
@@ -140,12 +140,12 @@
 int align_SatSF  = __alignof(_Sat signed _Fract);
 int align_SatSlF = __alignof(_Sat signed long _Fract);
 
-// CHECK-NEXT: @size_SatSsF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_SatSF   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_SatSlF  = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_SatSF  = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_SatSlF = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_SatSsF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatSF   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatSlF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatSsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatSF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatSlF = {{.*}}global i{{[0-9]+}} 4
 
 /* Saturated unsigned _Fract */
 
@@ -156,12 +156,12 @@
 int align_SatUF  = __alignof(_Sat unsigned _Fract);
 int align_SatUlF = __alignof(_Sat unsigned long _Fract);
 
-// CHECK-NEXT: @size_SatUsF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_SatUF   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_SatUlF  = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_SatUF  = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_SatUlF = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_SatUsF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatUF   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatUlF  = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatUsF = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatUF  = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatUlF = {{.*}}global i{{[0-9]+}} 4
 
 /* Aliased saturated signed _Accum */
 
@@ -188,9 +188,9 @@
 int align_SatF  = __alignof(_Sat _Fract);
 int align_SatlF = __alignof(_Sat long _Fract);
 
-// CHECK-NEXT: @size_SatsF   = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_SatF    = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_SatlF   = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_SatsF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_SatF   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_SatlF  = {{.*}}global i{{[0-9]+}} 8
+// CHECK-NEXT: @size_SatsF   = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @size_SatF    = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @size_SatlF   = {{.*}}global i{{[0-9]+}} 4
+// CHECK-NEXT: @align_SatsF  = {{.*}}global i{{[0-9]+}} 1
+// CHECK-NEXT: @align_SatF   = {{.*}}global i{{[0-9]+}} 2
+// CHECK-NEXT: @align_SatlF  = {{.*}}global i{{[0-9]+}} 4
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
@@ -3326,7 +3326,52 @@
 
   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;
+
+    llvm::APInt Val(bit_width, 0, isSigned);
+    bool Overflowed = Literal.GetFixedPointValue(Val, scale);
+
+    // Do not use bit_width since some types may have padding like _Fract or
+    // unsigned _Accums if SameFBits is set.
+    auto MaxVal = llvm::APInt::getMaxValue(ibits + scale).zextOrSelf(bit_width);
+    if (Literal.isFract && Val == MaxVal + 1)
+      // 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 if (Val.ugt(MaxVal) || Overflowed)
+      Diag(Tok.getLocation(), diag::err_too_large_for_fixed_point);
+
+    Res = FixedPointLiteral::CreateFromRawInt(Context, Val, Ty,
+                                              Tok.getLocation(), scale);
+  } else if (Literal.isFloatingLiteral()) {
     QualType Ty;
     if (Literal.isHalf){
       if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
@@ -5807,13 +5852,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 +5897,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 +5927,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 +5960,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 +13186,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,126 @@
   return Result.convertFromString(Str, APFloat::rmNearestTiesToEven);
 }
 
+static inline bool IsExponentPart(char c) {
+  return c == 'p' || c == 'P' || c == 'e' || c == 'E';
+}
+
+bool NumericLiteralParser::GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale) {
+  assert(radix == 16 || radix == 10);
+
+  // Find how many digits are needed to store the whole literal.
+  unsigned NumDigits = SuffixBegin - DigitsBegin;
+  if (saw_period) --NumDigits;
+
+  // Initial scan of the exponent if it exists
+  bool ExpOverflowOccurred = false;
+  bool NegativeExponent = false;
+  const char *ExponentBegin;
+  uint64_t Exponent = 0;
+  int64_t BaseShift = 0;
+  if (saw_exponent) {
+    const char *Ptr = DigitsBegin;
+
+    while (!IsExponentPart(*Ptr)) ++Ptr;
+    ExponentBegin = Ptr;
+    ++Ptr;
+    NegativeExponent = *Ptr == '-';
+    if (NegativeExponent) ++Ptr;
+
+    unsigned NumExpDigits = SuffixBegin - Ptr;
+    if (alwaysFitsInto64Bits(radix, NumExpDigits)) {
+      llvm::StringRef ExpStr(Ptr, NumExpDigits);
+      llvm::APInt ExpInt(/*numBits=*/64, ExpStr, /*radix=*/10);
+      Exponent = ExpInt.getZExtValue();
+    } else {
+      ExpOverflowOccurred = true;
+    }
+
+    if (NegativeExponent) BaseShift -= Exponent;
+    else BaseShift += Exponent;
+  }
+
+  // Number of bits needed for decimal literal is
+  //   ceil(NumDigits * log2(10))       Integral part
+  // + Scale                            Fractional part
+  // + ceil(Exponent * log2(10))        Exponent
+  // --------------------------------------------------
+  //   ceil((NumDigits + Exponent) * log2(10)) + Scale
+  //
+  // But for simplicity in handling integers, we can round up log2(10) to 4,
+  // making:
+  // 4 * (NumDigits + Exponent) + Scale
+  //
+  // Number of digits needed for hexadecimal literal is
+  //   4 * NumDigits                    Integral part
+  // + Scale                            Fractional part
+  // + Exponent                         Exponent
+  // --------------------------------------------------
+  //   (4 * NumDigits) + Scale + Exponent
+  uint64_t NumBitsNeeded;
+  if (radix == 10)
+    NumBitsNeeded = 4 * (NumDigits + Exponent) + Scale;
+  else
+    NumBitsNeeded = 4 * NumDigits + Exponent + Scale;
+
+  if (NumBitsNeeded > std::numeric_limits<unsigned>::max())
+    ExpOverflowOccurred = true;
+  llvm::APInt Val(static_cast<unsigned>(NumBitsNeeded), 0, /*isSigned=*/false);
+
+  bool FoundDecimal = false;
+
+  int64_t FractBaseShift = 0;
+  const char *End = saw_exponent ? ExponentBegin : SuffixBegin;
+  for (const char *Ptr = DigitsBegin; Ptr < End; ++Ptr) {
+    if (*Ptr == '.') {
+      FoundDecimal = true;
+      continue;
+    }
+
+    // Normal reading of an integer
+    unsigned C = llvm::hexDigitValue(*Ptr);
+    assert(C < radix && "NumericLiteralParser ctor should have rejected this");
+
+    Val *= radix;
+    Val += C;
+
+    if (FoundDecimal)
+      // Keep track of how much we will need to adjust this value by from the
+      // number of digits past the radix point.
+      --FractBaseShift;
+  }
+
+  // For a radix of 16, we will be multiplying by 2 instead of 16.
+  if (radix == 16) FractBaseShift *= 4;
+  BaseShift += FractBaseShift;
+
+  Val <<= Scale;
+
+  uint64_t Base = (radix == 16) ? 2 : 10;
+  if (BaseShift > 0) {
+    for (int64_t i = 0; i < BaseShift; ++i) {
+      Val *= Base;
+    }
+  } else if (BaseShift < 0) {
+    for (int64_t i = BaseShift; i < 0 && !Val.isNullValue(); ++i)
+      Val = Val.udiv(Base);
+  }
+
+  bool IntOverflowOccurred = false;
+  auto MaxVal = llvm::APInt::getMaxValue(StoreVal.getBitWidth());
+  if (Val.getBitWidth() > StoreVal.getBitWidth()) {
+    IntOverflowOccurred |= Val.ugt(MaxVal.zext(Val.getBitWidth()));
+    StoreVal = Val.trunc(StoreVal.getBitWidth());
+  } else if (Val.getBitWidth() < StoreVal.getBitWidth()) {
+    IntOverflowOccurred |= Val.zext(MaxVal.getBitWidth()).ugt(MaxVal);
+    StoreVal = Val.zext(StoreVal.getBitWidth());
+  } else {
+    StoreVal = Val;
+  }
+
+  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
@@ -2338,6 +2338,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
@@ -3766,6 +3766,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
@@ -387,6 +387,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 +1775,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,24 @@
   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;
+  ShortFractWidth = ShortFractAlign = 8;
+  FractWidth = FractAlign = 16;
+  LongFractWidth = LongFractAlign = 32;
+
+  // Fixed point default integral and fractional bit sizes
+  // We give the _Accum 1 fewer fractional bits than their corresponding _Fract
+  // types by default to have the same number of fractional bits between _Accum
+  // and _Fract types.
+  SameFBits = false;
+  ShortAccumFBits = 7;
+  AccumFBits = 15;
+  LongAccumFBits = 31;
+
   SuitableAlign = 64;
   DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
@@ -303,6 +315,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 +375,11 @@
 
   if (Opts.NewAlignOverride)
     NewAlign = Opts.NewAlignOverride * getCharWidth();
+
+  // Each unsigned fixed point type has the same number of fractional bits as
+  // its corresponding signed type.
+  SameFBits |= Opts.SameFBits;
+  CheckFixedPointBits();
 }
 
 bool TargetInfo::initFeatureMap(
@@ -716,3 +734,63 @@
 
   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 + getShortAccumIBits() + 1 <= ShortAccumWidth);
+  assert(AccumFBits + getAccumIBits() + 1 <= AccumWidth);
+  assert(LongAccumFBits + getLongAccumIBits() + 1 <= LongAccumWidth);
+  assert(getUnsignedShortAccumFBits() + getUnsignedShortAccumIBits() <=
+         ShortAccumWidth);
+  assert(getUnsignedAccumFBits() + getUnsignedAccumIBits() <= AccumWidth);
+  assert(getUnsignedLongAccumFBits() + getUnsignedLongAccumIBits() <=
+         LongAccumWidth);
+
+  assert(getShortFractFBits() + 1 <= ShortFractWidth);
+  assert(getFractFBits() + 1 <= FractWidth);
+  assert(getLongFractFBits() + 1 <= LongFractWidth);
+  assert(getUnsignedShortFractFBits() <= ShortFractWidth);
+  assert(getUnsignedFractFBits() <= FractWidth);
+  assert(getUnsignedLongFractFBits() <= 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(getShortFractFBits() == getUnsignedShortFractFBits() ||
+         getShortFractFBits() == getUnsignedShortFractFBits() - 1);
+  assert(getFractFBits() == getUnsignedFractFBits() ||
+         getFractFBits() == getUnsignedFractFBits() - 1);
+  assert(getLongFractFBits() == getUnsignedLongFractFBits() ||
+         getLongFractFBits() == getUnsignedLongFractFBits() - 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(getLongFractFBits() >= getFractFBits() &&
+         getFractFBits() >= getShortFractFBits());
+  assert(getUnsignedLongFractFBits() >= getUnsignedFractFBits() &&
+         getUnsignedFractFBits() >= getUnsignedShortFractFBits());
+  assert(LongAccumFBits >= AccumFBits && AccumFBits >= ShortAccumFBits);
+  assert(getUnsignedLongAccumFBits() >= getUnsignedAccumFBits() &&
+         getUnsignedAccumFBits() >= getUnsignedShortAccumFBits());
+
+  // 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(getLongAccumIBits() >= getAccumIBits() &&
+         getAccumIBits() >= getShortAccumIBits());
+  assert(getUnsignedLongAccumIBits() >= getUnsignedAccumIBits() &&
+         getUnsignedAccumIBits() >= getUnsignedShortAccumIBits());
+
+  // Each signed accum type has at least as many integral bits as its
+  // corresponding unsigned accum type.
+  assert(getShortAccumIBits() >= getUnsignedShortAccumIBits());
+  assert(getAccumIBits() >= getUnsignedAccumIBits());
+  assert(getLongAccumIBits() >= getUnsignedLongAccumIBits());
+}
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();
 }
+
+void clang::FixedPointValueToString(SmallVectorImpl<char> &Str,
+                                    const llvm::APSInt &Val, unsigned Scale,
+                                    unsigned Radix) {
+  llvm::APSInt ScaleVal = llvm::APSInt::getUnsigned(1ULL << Scale);
+  llvm::APSInt IntPart = Val / ScaleVal;
+  llvm::APSInt FractPart = Val % ScaleVal;
+  llvm::APSInt RadixInt = llvm::APSInt::getUnsigned(Radix);
+
+  IntPart.toString(Str, Radix);
+  Str.push_back('.');
+  do {
+    (FractPart * RadixInt / ScaleVal).toString(Str, Radix);
+    FractPart = (FractPart * RadixInt) % ScaleVal;
+  } while (FractPart.getExtValue());
+}
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,28 @@
   }
 }
 
+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
@@ -9284,6 +9351,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:
@@ -9460,6 +9530,39 @@
   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()) {
+        SmallString<64> S;
+        FixedPointValueToString(
+            S,
+            Value,
+            Info.Ctx.getTypeInfo(E->getType()).Width,
+            /*Radix=*/10);
+        Info.CCEDiag(E, diag::note_constexpr_overflow) << S << 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
 //===----------------------------------------------------------------------===//
@@ -9777,6 +9880,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:
@@ -10311,6 +10417,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))
@@ -10759,6 +10867,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,37 @@
   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 {
+  // Currently the longest decimal number that can be printed is the max for an
+  // unsigned long _Accum: 4294967295.99999999976716935634613037109375
+  // which is 43 characters.
+  SmallString<64> S;
+  FixedPointValueToString(S,
+      llvm::APSInt::getUnsigned(getValue().getZExtValue()),
+      Scale, Radix);
+  return S.str();
+}
+
 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 +1641,7 @@
   case CK_ZeroToOCLEvent:
   case CK_ZeroToOCLQueue:
   case CK_IntToOCLSampler:
+  case CK_IntegralToFixedPoint:
     assert(!getType()->isBooleanType() && "unheralded conversion to bool");
     goto CheckNoBasePath;
 
@@ -2991,6 +3023,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
@@ -10162,3 +10162,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,12 @@
   /// 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 or
+  /// calculating the digit sequence of the exponent.
+  bool GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale);
+
 private:
 
   void ParseNumberStartingWithZero(SourceLocation TokLoc);
@@ -157,7 +168,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
@@ -893,6 +893,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,32 @@
   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;
+
+  // If true, unsigned fixed point types have the same number of fractional bits
+  // as their signed counterparts. Otherwise, unsigned fixed point types have
+  // one more fractional bit than its corresponding signed type. This is false
+  // by default.
+  bool SameFBits;
+
+  // Fixed point integral and fractional bit sizes
+  // Saturated types share the same integral/fractional bits as their
+  // corresponding unsaturated types.
+  // For simplicity, the fractional bits in a _Fract type will be one less the
+  // width of that _Fract type. This leaves all signed _Fract types having no
+  // padding and unsigned _Fract types will only have 1 bit of padding after the
+  // sign if SameFBits is set.
+  unsigned char ShortAccumFBits;
+  unsigned char AccumFBits;
+  unsigned char LongAccumFBits;
+
   unsigned char SuitableAlign;
   unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
@@ -394,6 +414,84 @@
   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 ShortAccumWidth - ShortAccumFBits - 1;
+  }
+
+  /// getAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'signed _Accum' type.
+  unsigned getAccumFBits() const { return AccumFBits; }
+  unsigned getAccumIBits() const { return AccumWidth - AccumFBits - 1; }
+
+  /// getLongAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'signed long _Accum' type.
+  unsigned getLongAccumFBits() const { return LongAccumFBits; }
+  unsigned getLongAccumIBits() const {
+    return LongAccumWidth - LongAccumFBits - 1;
+  }
+
+  /// getUnsignedShortAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned short _Accum' type.
+  unsigned getUnsignedShortAccumFBits() const {
+    return SameFBits ? ShortAccumFBits : ShortAccumFBits + 1;
+  }
+  unsigned getUnsignedShortAccumIBits() const {
+    return SameFBits ? getShortAccumIBits()
+                     : ShortAccumWidth - getUnsignedShortAccumFBits();
+  }
+
+  /// getUnsignedAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned _Accum' type.
+  unsigned getUnsignedAccumFBits() const {
+    return SameFBits ? AccumFBits : AccumFBits + 1;
+  }
+  unsigned getUnsignedAccumIBits() const {
+    return SameFBits ? getAccumIBits() : AccumWidth - getUnsignedAccumFBits();
+  }
+
+  /// getUnsignedLongAccumFBits/IBits - Return the number of fractional/integral bits
+  /// in a 'unsigned long _Accum' type.
+  unsigned getUnsignedLongAccumFBits() const {
+    return SameFBits ? LongAccumFBits : LongAccumFBits + 1;
+  }
+  unsigned getUnsignedLongAccumIBits() const {
+    return SameFBits ? getLongAccumIBits()
+                     : LongAccumWidth - getUnsignedLongAccumFBits();
+  }
+
+  /// getShortFractFBits - Return the number of fractional bits
+  /// in a 'signed short _Fract' type.
+  unsigned getShortFractFBits() const { return ShortFractWidth - 1; }
+
+  /// getFractFBits - Return the number of fractional bits
+  /// in a 'signed _Fract' type.
+  unsigned getFractFBits() const { return FractWidth - 1; }
+
+  /// getLongFractFBits - Return the number of fractional bits
+  /// in a 'signed long _Fract' type.
+  unsigned getLongFractFBits() const { return LongFractWidth - 1; }
+
+  /// getUnsignedShortFractFBits - Return the number of fractional bits
+  /// in a 'unsigned short _Fract' type.
+  unsigned getUnsignedShortFractFBits() const {
+    return SameFBits ? getShortFractFBits() : getShortFractFBits() + 1;
+  }
+
+  /// getUnsignedFractFBits - Return the number of fractional bits
+  /// in a 'unsigned _Fract' type.
+  unsigned getUnsignedFractFBits() const {
+    return SameFBits ? getFractFBits() : getFractFBits() + 1;
+  }
+
+  /// getUnsignedLongFractFBits - Return the number of fractional bits
+  /// in a 'unsigned long _Fract' type.
+  unsigned getUnsignedLongFractFBits() const {
+    return SameFBits ? getLongFractFBits() : getLongFractFBits() + 1;
+  }
+
   /// Determine whether the __int128 type is supported on this target.
   virtual bool hasInt128Type() const {
     return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128;
@@ -1189,6 +1287,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
@@ -305,6 +305,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,8 @@
                           InGroup<GccCompat>;
 def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">,
                             InGroup<GccCompat>;
+def err_too_large_for_fixed_point : Error<
+  "this value is too large for this fixed point 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
@@ -30,6 +30,7 @@
 #include "clang/Basic/Specifiers.h"
 #include "clang/Basic/Visibility.h"
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/None.h"
@@ -1918,7 +1919,8 @@
     STK_Integral,
     STK_Floating,
     STK_IntegralComplex,
-    STK_FloatingComplex
+    STK_FloatingComplex,
+    STK_FixedPoint
   };
 
   /// Given that this is a scalar type, classify it.
@@ -6546,6 +6548,12 @@
   return cast<PointerType>(Decayed)->getPointeeType();
 }
 
+// Get the decimal string representation of a fixed point type, represented
+// as a scaled integer.
+void FixedPointValueToString(SmallVectorImpl<char> &Str,
+                             const llvm::APSInt &Val,
+                             unsigned Scale, unsigned Radix);
+
 } // 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