tbaeder updated this revision to Diff 465708.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134859/new/

https://reviews.llvm.org/D134859

Files:
  clang/lib/AST/CMakeLists.txt
  clang/lib/AST/Interp/Boolean.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Floating.cpp
  clang/lib/AST/Interp/Floating.h
  clang/lib/AST/Interp/Integral.h
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpStack.h
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/PrimType.h
  clang/lib/AST/Interp/Primitives.h
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -270,3 +270,26 @@
   static_assert((1337 & -1) == 1337, "");
   static_assert((0 & gimme(12)) == 0, "");
 };
+
+namespace floats {
+  constexpr int i = 2;
+  constexpr float f = 1.0f;
+  static_assert(f == 1.0f, "");
+
+  constexpr float f2 = 1u * f;
+  static_assert(f2 == 1.0f, "");
+
+  static_assert(1.0f + 3u == 4, "");
+  static_assert(4.0f / 1.0f == 4, "");
+  static_assert(10.0f * false == 0, "");
+
+  constexpr float floats[] = {1.0f, 2.0f, 3.0f, 4.0f};
+
+  constexpr float m = 5.0f / 0.0f; // ref-error {{must be initialized by a constant expression}} \
+                                   // ref-note {{division by zero}} \
+                                   // expected-error {{must be initialized by a constant expression}} \
+                                   // expected-note {{division by zero}}
+
+  static_assert(~2.0f == 3, ""); // ref-error {{invalid argument type 'float' to unary expression}} \
+                                 // expected-error {{invalid argument type 'float' to unary expression}}
+};
Index: clang/lib/AST/Interp/Primitives.h
===================================================================
--- /dev/null
+++ clang/lib/AST/Interp/Primitives.h
@@ -0,0 +1,36 @@
+//===------ Primitives.h - Types for the constexpr VM -----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities and helper functions for all primitive types:
+//  - Integral
+//  - Floating
+//  - Boolean
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_INTERP_PRIMITIVES_H
+#define LLVM_CLANG_AST_INTERP_PRIMITIVES_H
+
+#include "clang/AST/ComparisonCategories.h"
+
+namespace clang {
+namespace interp {
+
+/// Helper to compare two comparable types.
+template <typename T> ComparisonCategoryResult Compare(const T &X, const T &Y) {
+  if (X < Y)
+    return ComparisonCategoryResult::Less;
+  if (X > Y)
+    return ComparisonCategoryResult::Greater;
+  return ComparisonCategoryResult::Equal;
+}
+
+} // namespace interp
+} // namespace clang
+
+#endif
Index: clang/lib/AST/Interp/PrimType.h
===================================================================
--- clang/lib/AST/Interp/PrimType.h
+++ clang/lib/AST/Interp/PrimType.h
@@ -13,11 +13,12 @@
 #ifndef LLVM_CLANG_AST_INTERP_TYPE_H
 #define LLVM_CLANG_AST_INTERP_TYPE_H
 
+#include "Boolean.h"
+#include "Floating.h"
+#include "Integral.h"
 #include <climits>
 #include <cstddef>
 #include <cstdint>
-#include "Boolean.h"
-#include "Integral.h"
 
 namespace clang {
 namespace interp {
@@ -35,6 +36,7 @@
   PT_Sint64,
   PT_Uint64,
   PT_Bool,
+  PT_Float,
   PT_Ptr,
 };
 
@@ -48,6 +50,7 @@
 template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; };
 template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; };
 template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; };
+template <> struct PrimConv<PT_Float> { using T = Floating; };
 template <> struct PrimConv<PT_Bool> { using T = Boolean; };
 template <> struct PrimConv<PT_Ptr> { using T = Pointer; };
 
@@ -70,6 +73,7 @@
   case PT_Uint32:
   case PT_Sint64:
   case PT_Uint64:
+  case PT_Float:
     return true;
   default:
     return false;
@@ -94,6 +98,7 @@
       TYPE_SWITCH_CASE(PT_Uint32, B)                                           \
       TYPE_SWITCH_CASE(PT_Sint64, B)                                           \
       TYPE_SWITCH_CASE(PT_Uint64, B)                                           \
+      TYPE_SWITCH_CASE(PT_Float, B)                                            \
       TYPE_SWITCH_CASE(PT_Bool, B)                                             \
       TYPE_SWITCH_CASE(PT_Ptr, B)                                              \
     }                                                                          \
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -25,6 +25,7 @@
 def Uint32 : Type;
 def Sint64 : Type;
 def Uint64 : Type;
+def Float : Type;
 def Ptr : Type;
 
 //===----------------------------------------------------------------------===//
@@ -40,11 +41,13 @@
 def ArgUint32 : ArgType { let Name = "uint32_t"; }
 def ArgSint64 : ArgType { let Name = "int64_t"; }
 def ArgUint64 : ArgType { let Name = "uint64_t"; }
+def ArgFloat : ArgType { let Name = "Floating"; }
 def ArgBool : ArgType { let Name = "bool"; }
 
 def ArgFunction : ArgType { let Name = "const Function *"; }
 def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; }
 def ArgRecordField : ArgType { let Name = "const Record::Field *"; }
+def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
 
 //===----------------------------------------------------------------------===//
 // Classes of types instructions operate on.
@@ -54,11 +57,19 @@
   list<Type> Types;
 }
 
-def NumberTypeClass : TypeClass {
+def IntegerTypeClass : TypeClass {
   let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
                Uint32, Sint64, Uint64];
 }
 
+def FloatTypeClass : TypeClass {
+  let Types = [Float];
+}
+
+def NumberTypeClass : TypeClass {
+  let Types = !listconcat(IntegerTypeClass.Types, [Float]);
+}
+
 def AluTypeClass : TypeClass {
   let Types = !listconcat(NumberTypeClass.Types, [Bool]);
 }
@@ -204,6 +215,7 @@
 def ConstUint32 : ConstOpcode<Uint32, ArgUint32>;
 def ConstSint64 : ConstOpcode<Sint64, ArgSint64>;
 def ConstUint64 : ConstOpcode<Uint64, ArgUint64>;
+def ConstFloat : ConstOpcode<Float, ArgFloat>;
 def ConstBool : ConstOpcode<Bool, ArgBool>;
 
 // [] -> [Integer]
@@ -397,9 +409,15 @@
 //===----------------------------------------------------------------------===//
 
 // [Pointer, Integral] -> [Pointer]
-def AddOffset : AluOpcode;
+def AddOffset : Opcode {
+  let Types = [IntegerTypeClass];
+  let HasGroup = 1;
+}
 // [Pointer, Integral] -> [Pointer]
-def SubOffset : AluOpcode;
+def SubOffset : Opcode {
+  let Types = [IntegerTypeClass];
+  let HasGroup = 1;
+}
 
 //===----------------------------------------------------------------------===//
 // Binary operators.
@@ -410,7 +428,7 @@
 def Add : AluOpcode;
 def Mul : AluOpcode;
 def Rem : Opcode {
-  let Types = [NumberTypeClass];
+  let Types = [IntegerTypeClass];
   let HasGroup = 1;
 }
 def BitAnd : IntegerOpcode;
@@ -437,21 +455,21 @@
 
 // [Real] -> [Real]
 def Comp: Opcode {
-  let Types = [NumberTypeClass];
+  let Types = [IntegerTypeClass];
   let HasGroup = 1;
 }
 
 //===----------------------------------------------------------------------===//
-// Cast.
+// Cast, CastFP.
 //===----------------------------------------------------------------------===//
 // TODO: Expand this to handle casts between more types.
 
 def FromCastTypeClass : TypeClass {
-  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
+  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Float, Bool];
 }
 
 def ToCastTypeClass : TypeClass {
-  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
+  let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Float, Bool];
 }
 
 def Cast: Opcode {
@@ -459,6 +477,11 @@
   let HasGroup = 1;
 }
 
+def CastFP : Opcode {
+  let Types = [];
+  let Args = [ArgFltSemantics];
+}
+
 //===----------------------------------------------------------------------===//
 // Comparison opcodes.
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/InterpStack.h
===================================================================
--- clang/lib/AST/Interp/InterpStack.h
+++ clang/lib/AST/Interp/InterpStack.h
@@ -160,6 +160,8 @@
     else if constexpr (std::is_same_v<T, uint64_t> ||
                        std::is_same_v<T, Integral<64, false>>)
       return PT_Uint64;
+    else if constexpr (std::is_same_v<T, Floating>)
+      return PT_Float;
 
     llvm_unreachable("unknown type push()'ed into InterpStack");
   }
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -979,6 +979,11 @@
   return true;
 }
 
+/// 1) Pops a Floating from the stack.
+/// 2) Pushes a new floating on the stack that uses the given semantics.
+/// Not templated, so implemented in Interp.cpp.
+bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem);
+
 //===----------------------------------------------------------------------===//
 // Zero, Nullptr
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Interp.cpp
===================================================================
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -418,6 +418,13 @@
   return false;
 }
 
+bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem) {
+  Floating F = S.Stk.pop<Floating>();
+  Floating Result = Floating(F.toSemantics(Sem));
+  S.Stk.push<Floating>(Result);
+  return true;
+}
+
 bool Interpret(InterpState &S, APValue &Result) {
   // The current stack frame when we started Interpret().
   // This is being used by the ops to determine wheter
Index: clang/lib/AST/Interp/Integral.h
===================================================================
--- clang/lib/AST/Interp/Integral.h
+++ clang/lib/AST/Interp/Integral.h
@@ -21,33 +21,14 @@
 #include <cstddef>
 #include <cstdint>
 
+#include "Primitives.h"
+
 namespace clang {
 namespace interp {
 
 using APInt = llvm::APInt;
 using APSInt = llvm::APSInt;
 
-/// Helper to compare two comparable types.
-template <typename T>
-ComparisonCategoryResult Compare(const T &X, const T &Y) {
-  if (X < Y)
-    return ComparisonCategoryResult::Less;
-  if (X > Y)
-    return ComparisonCategoryResult::Greater;
-  return ComparisonCategoryResult::Equal;
-}
-
-// Helper structure to select the representation.
-template <unsigned Bits, bool Signed> struct Repr;
-template <> struct Repr<8, false> { using Type = uint8_t; };
-template <> struct Repr<16, false> { using Type = uint16_t; };
-template <> struct Repr<32, false> { using Type = uint32_t; };
-template <> struct Repr<64, false> { using Type = uint64_t; };
-template <> struct Repr<8, true> { using Type = int8_t; };
-template <> struct Repr<16, true> { using Type = int16_t; };
-template <> struct Repr<32, true> { using Type = int32_t; };
-template <> struct Repr<64, true> { using Type = int64_t; };
-
 /// Wrapper around numeric types.
 ///
 /// These wrappers are required to shared an interface between APSint and
@@ -56,6 +37,16 @@
 template <unsigned Bits, bool Signed> class Integral final {
 private:
   template <unsigned OtherBits, bool OtherSigned> friend class Integral;
+  // Helper structure to select the representation.
+  template <unsigned ReprBits, bool ReprSigned> struct Repr;
+  template <> struct Repr<8, false> { using Type = uint8_t; };
+  template <> struct Repr<16, false> { using Type = uint16_t; };
+  template <> struct Repr<32, false> { using Type = uint32_t; };
+  template <> struct Repr<64, false> { using Type = uint64_t; };
+  template <> struct Repr<8, true> { using Type = int8_t; };
+  template <> struct Repr<16, true> { using Type = int16_t; };
+  template <> struct Repr<32, true> { using Type = int32_t; };
+  template <> struct Repr<64, true> { using Type = int64_t; };
 
   // The primitive representing the integral.
   using ReprT = typename Repr<Bits, Signed>::Type;
@@ -105,6 +96,7 @@
   explicit operator unsigned() const { return V; }
   explicit operator int64_t() const { return V; }
   explicit operator uint64_t() const { return V; }
+  explicit operator double() const { return V; }
 
   APSInt toAPSInt() const {
     return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed);
Index: clang/lib/AST/Interp/Floating.h
===================================================================
--- /dev/null
+++ clang/lib/AST/Interp/Floating.h
@@ -0,0 +1,147 @@
+//===--- Floating.h - Types for the constexpr VM ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the VM types and helpers operating on types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_INTERP_FLOATING_H
+#define LLVM_CLANG_AST_INTERP_FLOATING_H
+
+#include "Primitives.h"
+#include "clang/AST/APValue.h"
+#include "llvm/ADT/APFloat.h"
+#include <limits>
+
+namespace clang {
+namespace interp {
+
+using APFloat = llvm::APFloat;
+using APSInt = llvm::APSInt;
+
+class Floating final {
+private:
+  // The underlying value storage.
+  APFloat F;
+
+  /// Primitive representing limits.
+  // static constexpr auto Min = std::numeric_limits<float>::min();
+  // static constexpr auto Max = std::numeric_limits<float>::max();
+
+  /// Construct a Floating from anything that is convertible to storage.
+  template <typename T> explicit Floating(T V) : F(V) {}
+
+public:
+  /// Zero-initializes a Floating.
+  Floating() : F(0.0f) {}
+  Floating(APFloat F) : F(F) {}
+
+  // Static constructors for special floating point values.
+  static Floating getInf(const llvm::fltSemantics &Sem) {
+    return Floating(APFloat::getInf(Sem));
+  }
+  static Floating zero() { return Floating(0.0f); }
+
+  bool operator<(Floating RHS) const { return F < RHS.F; }
+  bool operator>(Floating RHS) const { return F > RHS.F; }
+  bool operator<=(Floating RHS) const { return F <= RHS.F; }
+  bool operator>=(Floating RHS) const { return F >= RHS.F; }
+  bool operator==(Floating RHS) const { return F == RHS.F; }
+  bool operator!=(Floating RHS) const { return F != RHS.F; }
+  Floating operator-() const { return Floating(-F); }
+
+  explicit operator int8_t() const { return toAPSInt().getExtValue(); }
+  explicit operator uint8_t() const { return toAPSInt().getExtValue(); }
+  explicit operator int16_t() const { return toAPSInt().getExtValue(); }
+  explicit operator uint16_t() const { return toAPSInt().getExtValue(); }
+  explicit operator int32_t() const { return toAPSInt().getExtValue(); }
+  explicit operator uint32_t() const { return toAPSInt().getExtValue(); }
+  explicit operator int64_t() const { return toAPSInt().getExtValue(); }
+  explicit operator uint64_t() const { return toAPSInt().getExtValue(); }
+  explicit operator bool() const { return F.isNonZero(); }
+
+  Floating toSemantics(const llvm::fltSemantics *Sem) const {
+    APFloat Copy = F;
+    bool LosesInfo;
+    Copy.convert(*Sem, llvm::RoundingMode::TowardZero, &LosesInfo);
+    (void)LosesInfo;
+    return Floating(Copy);
+  }
+  APFloat toAPFloat() const { return F; }
+  APSInt toAPSInt(unsigned NumBits = 0) const {
+    return APSInt(F.bitcastToAPInt());
+  }
+  APValue toAPValue() const { return APValue(toAPFloat()); }
+  void print(llvm::raw_ostream &OS) const { F.print(OS); }
+
+  constexpr static unsigned bitWidth() { return 32; }
+
+  bool isSigned() const { return true; }
+  bool isNegative() const { return F.isNegative(); }
+  bool isPositive() const { return !F.isNegative(); }
+  bool isZero() const { return F.isZero(); }
+  bool isMin() const { return false; } // TODO
+  bool isMinusOne() const { return F == APFloat(-1.0f); }
+  bool isNan() const { return F.isNaN(); }
+
+  ComparisonCategoryResult compare(const Floating &RHS) const {
+    return Compare(F, RHS.F);
+  }
+
+  // TODO: Properly implement this(?)
+  Floating truncate(unsigned TruncBits) const { return Floating(this->F); }
+
+  template <typename ValT> static Floating from(ValT Value) {
+    if constexpr (std::is_integral<ValT>::value ||
+                  std::is_floating_point<ValT>::value)
+      return Floating(Value);
+    else if constexpr (std::is_same_v<ValT, Floating>) {
+      return Floating(Value.F);
+    } else
+      return Floating::from(static_cast<double>(Value));
+  }
+
+  template <typename T> static Floating from(T Value, unsigned NumBits) {
+    return Floating(Value);
+  }
+
+  // -------
+
+  static bool add(Floating A, Floating B, unsigned OpBits, Floating *R) {
+    *R = Floating(A.F + B.F);
+    return false;
+  }
+
+  static bool sub(Floating A, Floating B, unsigned OpBits, Floating *R) {
+    *R = Floating(A.F - B.F);
+    return false;
+  }
+
+  static bool neg(Floating A, Floating *R) {
+    *R = -A;
+    return false;
+  }
+
+  static bool div(Floating A, Floating B, unsigned OpBits, Floating *R) {
+    *R = Floating(A.F / B.F);
+    return false;
+  }
+
+  static bool mul(Floating A, Floating B, unsigned OpBits, Floating *R) {
+    *R = Floating(A.F * B.F);
+    return false;
+  }
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F);
+Floating getSwappedBytes(Floating F);
+
+} // namespace interp
+} // namespace clang
+
+#endif
Index: clang/lib/AST/Interp/Floating.cpp
===================================================================
--- /dev/null
+++ clang/lib/AST/Interp/Floating.cpp
@@ -0,0 +1,16 @@
+
+
+#include "Floating.h"
+
+namespace clang {
+namespace interp {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F) {
+  F.print(OS);
+  return OS;
+}
+
+Floating getSwappedBytes(Floating F) { return F; }
+
+} // namespace interp
+} // namespace clang
Index: clang/lib/AST/Interp/Descriptor.cpp
===================================================================
--- clang/lib/AST/Interp/Descriptor.cpp
+++ clang/lib/AST/Interp/Descriptor.cpp
@@ -162,6 +162,11 @@
 }
 
 static BlockCtorFn getCtorPrim(PrimType Type) {
+  // Floating types are special. They are primitives, but need their
+  // constructor called.
+  if (Type == PT_Float)
+    return ctorTy<PrimConv<PT_Float>::T>;
+
   COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr);
 }
 
Index: clang/lib/AST/Interp/Context.cpp
===================================================================
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -126,6 +126,9 @@
   if (T->isNullPtrType())
     return PT_Ptr;
 
+  if (T->isFloatingType())
+    return PT_Float;
+
   if (auto *AT = dyn_cast<AtomicType>(T))
     return classify(AT->getValueType());
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -68,6 +68,7 @@
   // Expression visitors - result returned on interp stack.
   bool VisitCastExpr(const CastExpr *E);
   bool VisitIntegerLiteral(const IntegerLiteral *E);
+  bool VisitFloatingLiteral(const FloatingLiteral *E);
   bool VisitParenExpr(const ParenExpr *E);
   bool VisitBinaryOperator(const BinaryOperator *E);
   bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -122,6 +122,33 @@
     return this->emitGetPtrBase(ToBase->Offset, CE);
   }
 
+  case CK_FloatingCast: {
+    if (!this->visit(SubExpr))
+      return false;
+
+    const auto *TargetSemantics =
+        &Ctx.getASTContext().getFloatTypeSemantics(CE->getType());
+    return this->emitCastFP(TargetSemantics, CE);
+  }
+
+  case CK_IntegralToFloating: {
+    // First cast the integral to a Floating, THEN cast the
+    // Floating to Floating with the same semantics.
+    Optional<PrimType> FromT = classify(SubExpr->getType());
+    if (!FromT)
+      return false;
+
+    if (!this->visit(SubExpr))
+      return false;
+
+    if (!this->emitCast(*FromT, PT_Float, CE))
+      return false;
+
+    const auto *TargetSemantics =
+        &Ctx.getASTContext().getFloatTypeSemantics(CE->getType());
+    return this->emitCastFP(TargetSemantics, CE);
+  }
+
   case CK_ArrayToPointerDecay:
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
@@ -133,6 +160,7 @@
     return this->Visit(SubExpr);
 
   case CK_IntegralToBoolean:
+  case CK_FloatingToIntegral:
   case CK_IntegralCast: {
     Optional<PrimType> FromT = classify(SubExpr->getType());
     Optional<PrimType> ToT = classify(CE->getType());
@@ -166,6 +194,14 @@
   return this->bail(LE);
 }
 
+template <class Emitter>
+bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
+  if (DiscardResult)
+    return true;
+
+  return this->emitConstFloat(E->getValue(), E);
+}
+
 template <class Emitter>
 bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
   return this->Visit(PE->getSubExpr());
@@ -438,6 +474,8 @@
     return this->emitZeroUint64(E);
   case PT_Ptr:
     return this->emitNullPtr(E);
+  case PT_Float:
+    return this->emitZeroFloat(E);
   }
   llvm_unreachable("unknown primitive type");
 }
@@ -602,6 +640,7 @@
   case PT_Bool:
     return this->emitConstBool(Value.getBoolValue(), E);
   case PT_Ptr:
+  case PT_Float:
     llvm_unreachable("Invalid integral type");
     break;
   }
Index: clang/lib/AST/Interp/Boolean.h
===================================================================
--- clang/lib/AST/Interp/Boolean.h
+++ clang/lib/AST/Interp/Boolean.h
@@ -56,6 +56,7 @@
   explicit operator int64_t() const { return V; }
   explicit operator uint64_t() const { return V; }
   explicit operator bool() const { return V; }
+  explicit operator double() const { return V; }
 
   APSInt toAPSInt() const {
     return APSInt(APInt(1, static_cast<uint64_t>(V), false), true);
Index: clang/lib/AST/CMakeLists.txt
===================================================================
--- clang/lib/AST/CMakeLists.txt
+++ clang/lib/AST/CMakeLists.txt
@@ -72,6 +72,7 @@
   Interp/EvalEmitter.cpp
   Interp/Frame.cpp
   Interp/Function.cpp
+  Interp/Floating.cpp
   Interp/Interp.cpp
   Interp/InterpBuiltin.cpp
   Interp/InterpBlock.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to