r335148 - [Fixed Point Arithmetic] Fixed Point Precision Bits and Fixed Point Literals

Leonard Chan via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 20 10:19:40 PDT 2018


Author: leonardchan
Date: Wed Jun 20 10:19:40 2018
New Revision: 335148

URL: http://llvm.org/viewvc/llvm-project?rev=335148&view=rev
Log:
[Fixed Point Arithmetic] Fixed Point Precision Bits and Fixed Point Literals

This diff includes the logic for setting the precision bits for each primary fixed point type in the target info and logic for initializing a fixed point literal.

Fixed point literals are declared using the suffixes

```
hr: short _Fract
uhr: unsigned short _Fract
r: _Fract
ur: unsigned _Fract
lr: long _Fract
ulr: unsigned long _Fract
hk: short _Accum
uhk: unsigned short _Accum
k: _Accum
uk: unsigned _Accum
```
Errors are also thrown for illegal literal values

```
unsigned short _Accum u_short_accum = 256.0uhk;   // expected-error{{the integral part of this literal is too large for this unsigned _Accum type}}
```

Differential Revision: https://reviews.llvm.org/D46915

Added:
    cfe/trunk/test/Frontend/fixed_point_declarations.c
    cfe/trunk/test/Frontend/fixed_point_same_fbits.c
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Expr.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
    cfe/trunk/include/clang/Basic/LangOptions.def
    cfe/trunk/include/clang/Basic/StmtNodes.td
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Lex/LiteralSupport.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/AST/Expr.cpp
    cfe/trunk/lib/AST/ExprClassification.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/AST/Type.cpp
    cfe/trunk/lib/Basic/TargetInfo.cpp
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/CodeGen/CGExprAgg.cpp
    cfe/trunk/lib/CodeGen/CGExprScalar.cpp
    cfe/trunk/lib/Driver/ToolChains/Clang.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/Lex/LiteralSupport.cpp
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
    cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Frontend/fixed_point.c
    cfe/trunk/test/Frontend/fixed_point_bit_widths.c
    cfe/trunk/test/Frontend/fixed_point_errors.c
    cfe/trunk/tools/libclang/CIndex.cpp
    cfe/trunk/tools/libclang/CXCursor.cpp

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Wed Jun 20 10:19:40 2018
@@ -2170,7 +2170,12 @@ enum CXCursorKind {
    */
   CXCursor_ObjCAvailabilityCheckExpr     = 148,
 
-  CXCursor_LastExpr                      = CXCursor_ObjCAvailabilityCheckExpr,
+  /**
+   * Fixed point literal
+   */
+  CXCursor_FixedPointLiteral             = 149,
+
+  CXCursor_LastExpr                      = CXCursor_FixedPointLiteral,
 
   /* Statements */
   CXCursor_FirstStmt                     = 200,

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Wed Jun 20 10:19:40 2018
@@ -1947,6 +1947,9 @@ public:
     return getQualifiedType(type.getUnqualifiedType(), Qs);
   }
 
+  unsigned char getFixedPointScale(QualType Ty) const;
+  unsigned char getFixedPointIBits(QualType Ty) const;
+
   DeclarationNameInfo getNameForTemplate(TemplateName Name,
                                          SourceLocation NameLoc) const;
 

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Jun 20 10:19:40 2018
@@ -1351,6 +1351,47 @@ public:
   }
 };
 
+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 {

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Wed Jun 20 10:19:40 2018
@@ -2585,6 +2585,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, {
 
 // 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, {})

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Wed Jun 20 10:19:40 2018
@@ -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"
@@ -6546,6 +6547,12 @@ QualType DecayedType::getPointeeType() c
   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

Modified: cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticCommonKinds.td Wed Jun 20 10:19:40 2018
@@ -168,6 +168,8 @@ def ext_clang_enable_if : Extension<"'en
                           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">;
 

Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Wed Jun 20 10:19:40 2018
@@ -305,6 +305,8 @@ ENUM_LANGOPT(ClangABICompat, ClangABI, 4
 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

Modified: cfe/trunk/include/clang/Basic/StmtNodes.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/StmtNodes.td?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/StmtNodes.td (original)
+++ cfe/trunk/include/clang/Basic/StmtNodes.td Wed Jun 20 10:19:40 2018
@@ -57,6 +57,7 @@ def Expr : Stmt<1>;
 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>;

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Wed Jun 20 10:19:40 2018
@@ -74,12 +74,32 @@ protected:
   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 ShortAccumScale;
+  unsigned char AccumScale;
+  unsigned char LongAccumScale;
+
   unsigned char SuitableAlign;
   unsigned char DefaultAlignForAttributeAligned;
   unsigned char MinGlobalAlign;
@@ -394,6 +414,84 @@ public:
   unsigned getLongFractWidth() const { return LongFractWidth; }
   unsigned getLongFractAlign() const { return LongFractAlign; }
 
+  /// getShortAccumScale/IBits - Return the number of fractional/integral bits
+  /// in a 'signed short _Accum' type.
+  unsigned getShortAccumScale() const { return ShortAccumScale; }
+  unsigned getShortAccumIBits() const {
+    return ShortAccumWidth - ShortAccumScale - 1;
+  }
+
+  /// getAccumScale/IBits - Return the number of fractional/integral bits
+  /// in a 'signed _Accum' type.
+  unsigned getAccumScale() const { return AccumScale; }
+  unsigned getAccumIBits() const { return AccumWidth - AccumScale - 1; }
+
+  /// getLongAccumScale/IBits - Return the number of fractional/integral bits
+  /// in a 'signed long _Accum' type.
+  unsigned getLongAccumScale() const { return LongAccumScale; }
+  unsigned getLongAccumIBits() const {
+    return LongAccumWidth - LongAccumScale - 1;
+  }
+
+  /// getUnsignedShortAccumScale/IBits - Return the number of
+  /// fractional/integral bits in a 'unsigned short _Accum' type.
+  unsigned getUnsignedShortAccumScale() const {
+    return SameFBits ? ShortAccumScale : ShortAccumScale + 1;
+  }
+  unsigned getUnsignedShortAccumIBits() const {
+    return SameFBits ? getShortAccumIBits()
+                     : ShortAccumWidth - getUnsignedShortAccumScale();
+  }
+
+  /// getUnsignedAccumScale/IBits - Return the number of fractional/integral
+  /// bits in a 'unsigned _Accum' type.
+  unsigned getUnsignedAccumScale() const {
+    return SameFBits ? AccumScale : AccumScale + 1;
+  }
+  unsigned getUnsignedAccumIBits() const {
+    return SameFBits ? getAccumIBits() : AccumWidth - getUnsignedAccumScale();
+  }
+
+  /// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral
+  /// bits in a 'unsigned long _Accum' type.
+  unsigned getUnsignedLongAccumScale() const {
+    return SameFBits ? LongAccumScale : LongAccumScale + 1;
+  }
+  unsigned getUnsignedLongAccumIBits() const {
+    return SameFBits ? getLongAccumIBits()
+                     : LongAccumWidth - getUnsignedLongAccumScale();
+  }
+
+  /// getShortFractScale - Return the number of fractional bits
+  /// in a 'signed short _Fract' type.
+  unsigned getShortFractScale() const { return ShortFractWidth - 1; }
+
+  /// getFractScale - Return the number of fractional bits
+  /// in a 'signed _Fract' type.
+  unsigned getFractScale() const { return FractWidth - 1; }
+
+  /// getLongFractScale - Return the number of fractional bits
+  /// in a 'signed long _Fract' type.
+  unsigned getLongFractScale() const { return LongFractWidth - 1; }
+
+  /// getUnsignedShortFractScale - Return the number of fractional bits
+  /// in a 'unsigned short _Fract' type.
+  unsigned getUnsignedShortFractScale() const {
+    return SameFBits ? getShortFractScale() : getShortFractScale() + 1;
+  }
+
+  /// getUnsignedFractScale - Return the number of fractional bits
+  /// in a 'unsigned _Fract' type.
+  unsigned getUnsignedFractScale() const {
+    return SameFBits ? getFractScale() : getFractScale() + 1;
+  }
+
+  /// getUnsignedLongFractScale - Return the number of fractional bits
+  /// in a 'unsigned long _Fract' type.
+  unsigned getUnsignedLongFractScale() const {
+    return SameFBits ? getLongFractScale() : getLongFractScale() + 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 @@ protected:
   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

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Wed Jun 20 10:19:40 2018
@@ -893,6 +893,10 @@ def ffixed_point : Flag<["-"], "ffixed-p
                    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.

Modified: cfe/trunk/include/clang/Lex/LiteralSupport.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/LiteralSupport.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/LiteralSupport.h (original)
+++ cfe/trunk/include/clang/Lex/LiteralSupport.h Wed Jun 20 10:19:40 2018
@@ -50,7 +50,7 @@ class NumericLiteralParser {
 
   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 @@ public:
   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 @@ public:
   /// 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);

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jun 20 10:19:40 2018
@@ -10162,3 +10162,92 @@ clang::LazyGenerationalUpdatePtr<
 clang::LazyGenerationalUpdatePtr<
     const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue(
         const clang::ASTContext &Ctx, Decl *Value);
+
+unsigned char ASTContext::getFixedPointScale(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.getShortAccumScale();
+    case BuiltinType::Accum:
+    case BuiltinType::SatAccum:
+      return Target.getAccumScale();
+    case BuiltinType::LongAccum:
+    case BuiltinType::SatLongAccum:
+      return Target.getLongAccumScale();
+    case BuiltinType::UShortAccum:
+    case BuiltinType::SatUShortAccum:
+      return Target.getUnsignedShortAccumScale();
+    case BuiltinType::UAccum:
+    case BuiltinType::SatUAccum:
+      return Target.getUnsignedAccumScale();
+    case BuiltinType::ULongAccum:
+    case BuiltinType::SatULongAccum:
+      return Target.getUnsignedLongAccumScale();
+    case BuiltinType::ShortFract:
+    case BuiltinType::SatShortFract:
+      return Target.getShortFractScale();
+    case BuiltinType::Fract:
+    case BuiltinType::SatFract:
+      return Target.getFractScale();
+    case BuiltinType::LongFract:
+    case BuiltinType::SatLongFract:
+      return Target.getLongFractScale();
+    case BuiltinType::UShortFract:
+    case BuiltinType::SatUShortFract:
+      return Target.getUnsignedShortFractScale();
+    case BuiltinType::UFract:
+    case BuiltinType::SatUFract:
+      return Target.getUnsignedFractScale();
+    case BuiltinType::ULongFract:
+    case BuiltinType::SatULongFract:
+      return Target.getUnsignedLongFractScale();
+  }
+}
+
+unsigned char ASTContext::getFixedPointIBits(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;
+  }
+}

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Wed Jun 20 10:19:40 2018
@@ -525,6 +525,7 @@ namespace  {
     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 @@ void ASTDumper::VisitIntegerLiteral(cons
   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);

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Jun 20 10:19:40 2018
@@ -755,6 +755,36 @@ IntegerLiteral::Create(const ASTContext
   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,
@@ -2991,6 +3021,7 @@ bool Expr::HasSideEffects(const ASTConte
   case ObjCIvarRefExprClass:
   case PredefinedExprClass:
   case IntegerLiteralClass:
+  case FixedPointLiteralClass:
   case FloatingLiteralClass:
   case ImaginaryLiteralClass:
   case StringLiteralClass:

Modified: cfe/trunk/lib/AST/ExprClassification.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprClassification.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprClassification.cpp (original)
+++ cfe/trunk/lib/AST/ExprClassification.cpp Wed Jun 20 10:19:40 2018
@@ -161,6 +161,7 @@ static Cl::Kinds ClassifyInternal(ASTCon
   case Expr::ShuffleVectorExprClass:
   case Expr::ConvertVectorExprClass:
   case Expr::IntegerLiteralClass:
+  case Expr::FixedPointLiteralClass:
   case Expr::CharacterLiteralClass:
   case Expr::AddrLabelExprClass:
   case Expr::CXXDeleteExprClass:

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Wed Jun 20 10:19:40 2018
@@ -7220,6 +7220,73 @@ public:
 
   // 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
@@ -9460,6 +9527,37 @@ bool IntExprEvaluator::VisitCXXNoexceptE
   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
 //===----------------------------------------------------------------------===//
@@ -10311,6 +10409,8 @@ static bool Evaluate(APValue &Result, Ev
     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 +10859,7 @@ static ICEDiag CheckICE(const Expr* E, c
   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:

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Jun 20 10:19:40 2018
@@ -3501,6 +3501,7 @@ recurse:
   case Expr::AsTypeExprClass:
   case Expr::PseudoObjectExprClass:
   case Expr::AtomicExprClass:
+  case Expr::FixedPointLiteralClass:
   {
     if (!NullOut) {
       // As bad as this diagnostic is, it's better than crashing.

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Wed Jun 20 10:19:40 2018
@@ -1529,6 +1529,28 @@ void StmtPrinter::VisitIntegerLiteral(In
   }
 }
 
+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;

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Wed Jun 20 10:19:40 2018
@@ -1007,6 +1007,12 @@ void StmtProfiler::VisitIntegerLiteral(c
   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());

Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Wed Jun 20 10:19:40 2018
@@ -3986,3 +3986,19 @@ QualType::DestructionKind QualType::isDe
 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());
+}

Modified: cfe/trunk/lib/Basic/TargetInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/TargetInfo.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/TargetInfo.cpp (original)
+++ cfe/trunk/lib/Basic/TargetInfo.cpp Wed Jun 20 10:19:40 2018
@@ -40,12 +40,24 @@ TargetInfo::TargetInfo(const llvm::Tripl
   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;
+  ShortAccumScale = 7;
+  AccumScale = 15;
+  LongAccumScale = 31;
+
   SuitableAlign = 64;
   DefaultAlignForAttributeAligned = 128;
   MinGlobalAlign = 0;
@@ -362,6 +374,11 @@ void TargetInfo::adjust(LangOptions &Opt
 
   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 +733,63 @@ bool TargetInfo::validateInputConstraint
 
   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(ShortAccumScale + getShortAccumIBits() + 1 <= ShortAccumWidth);
+  assert(AccumScale + getAccumIBits() + 1 <= AccumWidth);
+  assert(LongAccumScale + getLongAccumIBits() + 1 <= LongAccumWidth);
+  assert(getUnsignedShortAccumScale() + getUnsignedShortAccumIBits() <=
+         ShortAccumWidth);
+  assert(getUnsignedAccumScale() + getUnsignedAccumIBits() <= AccumWidth);
+  assert(getUnsignedLongAccumScale() + getUnsignedLongAccumIBits() <=
+         LongAccumWidth);
+
+  assert(getShortFractScale() + 1 <= ShortFractWidth);
+  assert(getFractScale() + 1 <= FractWidth);
+  assert(getLongFractScale() + 1 <= LongFractWidth);
+  assert(getUnsignedShortFractScale() <= ShortFractWidth);
+  assert(getUnsignedFractScale() <= FractWidth);
+  assert(getUnsignedLongFractScale() <= 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(getShortFractScale() == getUnsignedShortFractScale() ||
+         getShortFractScale() == getUnsignedShortFractScale() - 1);
+  assert(getFractScale() == getUnsignedFractScale() ||
+         getFractScale() == getUnsignedFractScale() - 1);
+  assert(getLongFractScale() == getUnsignedLongFractScale() ||
+         getLongFractScale() == getUnsignedLongFractScale() - 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(getLongFractScale() >= getFractScale() &&
+         getFractScale() >= getShortFractScale());
+  assert(getUnsignedLongFractScale() >= getUnsignedFractScale() &&
+         getUnsignedFractScale() >= getUnsignedShortFractScale());
+  assert(LongAccumScale >= AccumScale && AccumScale >= ShortAccumScale);
+  assert(getUnsignedLongAccumScale() >= getUnsignedAccumScale() &&
+         getUnsignedAccumScale() >= getUnsignedShortAccumScale());
+
+  // 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());
+}

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Wed Jun 20 10:19:40 2018
@@ -652,5 +652,7 @@ TargetInfo::CreateTargetInfo(Diagnostics
   if (!Target->validateTarget(Diags))
     return nullptr;
 
+  Target->CheckFixedPointBits();
+
   return Target.release();
 }

Modified: cfe/trunk/lib/CodeGen/CGExprAgg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprAgg.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprAgg.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprAgg.cpp Wed Jun 20 10:19:40 2018
@@ -684,12 +684,12 @@ void AggExprEmitter::VisitCastExpr(CastE
       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()) {

Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Wed Jun 20 10:19:40 2018
@@ -387,6 +387,9 @@ public:
   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());
   }

Modified: cfe/trunk/lib/Driver/ToolChains/Clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/ToolChains/Clang.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/ToolChains/Clang.cpp (original)
+++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp Wed Jun 20 10:19:40 2018
@@ -3766,6 +3766,11 @@ void Clang::ConstructJob(Compilation &C,
                    /*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).
   //

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Wed Jun 20 10:19:40 2018
@@ -2338,6 +2338,10 @@ static void ParseLangArgs(LangOptions &O
   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,

Modified: cfe/trunk/lib/Lex/LiteralSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/LiteralSupport.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/LiteralSupport.cpp (original)
+++ cfe/trunk/lib/Lex/LiteralSupport.cpp Wed Jun 20 10:19:40 2018
@@ -538,6 +538,7 @@ NumericLiteralParser::NumericLiteralPars
   saw_exponent = false;
   saw_period = false;
   saw_ud_suffix = false;
+  saw_fixed_point_suffix = false;
   isLong = false;
   isUnsigned = false;
   isLongLong = false;
@@ -547,6 +548,8 @@ NumericLiteralParser::NumericLiteralPars
   isFloat16 = false;
   isFloat128 = false;
   MicrosoftInteger = 0;
+  isFract = false;
+  isAccum = false;
   hadError = false;
 
   if (*s == '0') { // parse radix
@@ -568,6 +571,14 @@ NumericLiteralParser::NumericLiteralPars
   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();
@@ -576,11 +587,21 @@ NumericLiteralParser::NumericLiteralPars
   // 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 +714,9 @@ NumericLiteralParser::NumericLiteralPars
         isHalf = false;
         isImaginary = false;
         MicrosoftInteger = 0;
+        saw_fixed_point_suffix = false;
+        isFract = false;
+        isAccum = false;
       }
 
       saw_ud_suffix = true;
@@ -707,6 +731,11 @@ NumericLiteralParser::NumericLiteralPars
       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 +1041,126 @@ NumericLiteralParser::GetFloatValue(llvm
   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

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Jun 20 10:19:40 2018
@@ -1258,6 +1258,7 @@ CanThrowResult Sema::canThrow(const Expr
   case Expr::ImaginaryLiteralClass:
   case Expr::ImplicitValueInitExprClass:
   case Expr::IntegerLiteralClass:
+  case Expr::FixedPointLiteralClass:
   case Expr::ArrayInitIndexExprClass:
   case Expr::NoInitExprClass:
   case Expr::ObjCEncodeExprClass:

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Jun 20 10:19:40 2018
@@ -3326,7 +3326,52 @@ ExprResult Sema::ActOnNumericConstant(co
 
   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"))
@@ -13122,7 +13167,7 @@ ExprResult Sema::ActOnChooseExpr(SourceL
     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();

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Wed Jun 20 10:19:40 2018
@@ -8888,6 +8888,12 @@ TreeTransform<Derived>::TransformInteger
   return E;
 }
 
+template <typename Derived>
+ExprResult TreeTransform<Derived>::TransformFixedPointLiteral(
+    FixedPointLiteral *E) {
+  return E;
+}
+
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformFloatingLiteral(FloatingLiteral *E) {

Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Jun 20 10:19:40 2018
@@ -533,6 +533,12 @@ void ASTStmtReader::VisitIntegerLiteral(
   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()));

Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Jun 20 10:19:40 2018
@@ -444,6 +444,13 @@ void ASTStmtWriter::VisitIntegerLiteral(
   Code = serialization::EXPR_INTEGER_LITERAL;
 }
 
+void ASTStmtWriter::VisitFixedPointLiteral(FixedPointLiteral *E) {
+  VisitExpr(E);
+  Record.AddSourceLocation(E->getLocation());
+  Record.AddAPInt(E->getValue());
+  Code = serialization::EXPR_INTEGER_LITERAL;
+}
+
 void ASTStmtWriter::VisitFloatingLiteral(FloatingLiteral *E) {
   VisitExpr(E);
   Record.push_back(E->getRawSemantics());

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Jun 20 10:19:40 2018
@@ -1297,6 +1297,7 @@ void ExprEngine::Visit(const Stmt *S, Ex
     case Stmt::AddrLabelExprClass:
     case Stmt::AttributedStmtClass:
     case Stmt::IntegerLiteralClass:
+    case Stmt::FixedPointLiteralClass:
     case Stmt::CharacterLiteralClass:
     case Stmt::ImplicitValueInitExprClass:
     case Stmt::CXXScalarValueInitExprClass:

Modified: cfe/trunk/test/Frontend/fixed_point.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/fixed_point.c?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/test/Frontend/fixed_point.c (original)
+++ cfe/trunk/test/Frontend/fixed_point.c Wed Jun 20 10:19:40 2018
@@ -236,4 +236,164 @@ SatlF_t   SatlF_type;
 //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

Modified: cfe/trunk/test/Frontend/fixed_point_bit_widths.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/fixed_point_bit_widths.c?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/test/Frontend/fixed_point_bit_widths.c (original)
+++ cfe/trunk/test/Frontend/fixed_point_bit_widths.c Wed Jun 20 10:19:40 2018
@@ -44,12 +44,12 @@ int align_SsF = __alignof(signed short _
 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_UsF = __alignof(unsigned short
 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_sF = __alignof(short _Fract);
 int align_F  = __alignof(_Fract);
 int align_lF = __alignof(long _Fract);
 
-// CHECK-NEXT: @size_sF   = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @size_F    = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @size_lF   = {{.*}}global i{{[0-9]+}} 8
-// CHECK-NEXT: @align_sF  = {{.*}}global i{{[0-9]+}} 2
-// CHECK-NEXT: @align_F   = {{.*}}global i{{[0-9]+}} 4
-// CHECK-NEXT: @align_lF  = {{.*}}global i{{[0-9]+}} 8
+// 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_SatSsF = __alignof(_Sat signed
 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_SatUsF = __alignof(_Sat unsign
 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_SatsF = __alignof(_Sat short _
 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

Added: cfe/trunk/test/Frontend/fixed_point_declarations.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/fixed_point_declarations.c?rev=335148&view=auto
==============================================================================
--- cfe/trunk/test/Frontend/fixed_point_declarations.c (added)
+++ cfe/trunk/test/Frontend/fixed_point_declarations.c Wed Jun 20 10:19:40 2018
@@ -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

Modified: cfe/trunk/test/Frontend/fixed_point_errors.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/fixed_point_errors.c?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/test/Frontend/fixed_point_errors.c (original)
+++ cfe/trunk/test/Frontend/fixed_point_errors.c Wed Jun 20 10:19:40 2018
@@ -78,6 +78,50 @@ _Sat char c;              // expected-er
 _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 +135,16 @@ _Sat fract_t td_sat_fract;
 _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}}

Added: cfe/trunk/test/Frontend/fixed_point_same_fbits.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Frontend/fixed_point_same_fbits.c?rev=335148&view=auto
==============================================================================
--- cfe/trunk/test/Frontend/fixed_point_same_fbits.c (added)
+++ cfe/trunk/test/Frontend/fixed_point_same_fbits.c Wed Jun 20 10:19:40 2018
@@ -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
+}

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Wed Jun 20 10:19:40 2018
@@ -5061,6 +5061,8 @@ CXString clang_getCursorKindSpelling(enu
     return cxstring::createRef("VariableRef");
   case CXCursor_IntegerLiteral:
       return cxstring::createRef("IntegerLiteral");
+  case CXCursor_FixedPointLiteral:
+      return cxstring::createRef("FixedPointLiteral");
   case CXCursor_FloatingLiteral:
       return cxstring::createRef("FloatingLiteral");
   case CXCursor_ImaginaryLiteral:

Modified: cfe/trunk/tools/libclang/CXCursor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXCursor.cpp?rev=335148&r1=335147&r2=335148&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CXCursor.cpp (original)
+++ cfe/trunk/tools/libclang/CXCursor.cpp Wed Jun 20 10:19:40 2018
@@ -305,6 +305,10 @@ CXCursor cxcursor::MakeCXCursor(const St
     K = CXCursor_IntegerLiteral;
     break;
 
+  case Stmt::FixedPointLiteralClass:
+    K = CXCursor_FixedPointLiteral;
+    break;
+
   case Stmt::FloatingLiteralClass:
     K = CXCursor_FloatingLiteral;
     break;




More information about the cfe-commits mailing list