https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/185028

This is an alternative approach to 
https://github.com/llvm/llvm-project/pull/169769.

We leave the old `Integral<Bits, Signed>` intact and don't increase its size at 
all, but then introduce a new `IntegralOrPtr<Bits, Signed>`, which either holds 
its value _or_ a pointer and an offset. To support address-label-diffs, the 
offset is always pointer sized as well, making everything `>= 32` bits 
`sizeof(void*) + sizeof(void*) + sizeof(uint8_t)` in size.

The old approach did not work out in the end because we need to be able to do 
arithmetic (but essentially just `+` and `-`) on the offsets of such 
integers-that-are-actually-pointers.

c-t-t-:
https://llvm-compile-time-tracker.com/compare.php?from=e7448c3f4088cae61cb1bf8ade1a4a79d7cc4dbb&to=4aa23d5b4d8e6c43b0cf846f18f34ea967895fe5&stat=instructions:u

>From 144ec0098f7887361c8120787a5bdd259a8344ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]>
Date: Mon, 17 Nov 2025 13:58:23 +0100
Subject: [PATCH] [clang][bytecode] Support different integral types (e.g.
 addresses)

---
 clang/lib/AST/ByteCode/Boolean.h              |   3 +-
 clang/lib/AST/ByteCode/Context.cpp            |   2 +-
 clang/lib/AST/ByteCode/Descriptor.cpp         |   7 +
 clang/lib/AST/ByteCode/Descriptor.h           |   5 +
 clang/lib/AST/ByteCode/Integral.h             | 382 +++++++++++++++++-
 clang/lib/AST/ByteCode/IntegralAP.h           |   1 +
 clang/lib/AST/ByteCode/Interp.cpp             |  40 +-
 clang/lib/AST/ByteCode/Interp.h               | 215 +++++++++-
 clang/lib/AST/ByteCode/InterpBuiltin.cpp      |  60 ++-
 .../lib/AST/ByteCode/InterpBuiltinBitCast.cpp |  14 +-
 clang/lib/AST/ByteCode/InterpStack.h          |  13 +-
 clang/lib/AST/ByteCode/Pointer.cpp            |   9 +
 clang/lib/AST/ByteCode/Pointer.h              |   4 +-
 clang/lib/AST/ByteCode/PrimType.h             |  32 +-
 clang/lib/AST/ByteCode/Primitives.h           |   8 +
 clang/test/AST/ByteCode/addr-label-diff.c     |  19 +
 clang/test/AST/ByteCode/addr-label-diff.cpp   |  16 +
 clang/test/AST/ByteCode/builtin-bit-cast.cpp  |   8 +
 clang/test/AST/ByteCode/const-eval.c          |   9 +-
 clang/test/AST/ByteCode/cxx11.cpp             |  12 +
 clang/test/AST/ByteCode/int-as-ptr-arith.c    |  17 +
 clang/test/CodeGen/const-init.c               |   1 +
 clang/test/CodeGen/const-label-addr.c         |   1 +
 clang/test/CodeGen/statements.c               |   1 +
 clang/test/CodeGen/staticinit.c               |   1 +
 .../CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp   |   1 +
 clang/test/CodeGenCXX/const-init-cxx11.cpp    |   3 +
 clang/test/CodeGenCXX/const-init.cpp          |   6 +
 clang/test/Sema/array-init.c                  |   2 +
 clang/test/Sema/compound-literal.c            |   1 +
 clang/test/Sema/const-ptr-int-ptr-cast.c      |   1 +
 clang/test/Sema/init.c                        |   1 +
 clang/test/SemaCXX/constexpr-string.cpp       |   1 +
 33 files changed, 807 insertions(+), 89 deletions(-)
 create mode 100644 clang/test/AST/ByteCode/addr-label-diff.c
 create mode 100644 clang/test/AST/ByteCode/addr-label-diff.cpp
 create mode 100644 clang/test/AST/ByteCode/int-as-ptr-arith.c

diff --git a/clang/lib/AST/ByteCode/Boolean.h b/clang/lib/AST/ByteCode/Boolean.h
index fd8d546656881..09eefee14a854 100644
--- a/clang/lib/AST/ByteCode/Boolean.h
+++ b/clang/lib/AST/ByteCode/Boolean.h
@@ -61,11 +61,10 @@ class Boolean final {
   bool isMin() const { return isZero(); }
 
   constexpr static bool isMinusOne() { return false; }
-
   constexpr static bool isSigned() { return false; }
-
   constexpr static bool isNegative() { return false; }
   constexpr static bool isPositive() { return !isNegative(); }
+  constexpr static bool isNumber() { return true; }
 
   ComparisonCategoryResult compare(const Boolean &RHS) const {
     return Compare(V, RHS.V);
diff --git a/clang/lib/AST/ByteCode/Context.cpp 
b/clang/lib/AST/ByteCode/Context.cpp
index 879d51e6a2c3e..cc391ba3327f8 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -186,7 +186,7 @@ bool Context::evaluateStringRepr(State &Parent, const Expr 
*SizeExpr,
       return false;
 
     // Must be char.
-    if (Ptr.getFieldDesc()->getElemSize() != 1 /*bytes*/)
+    if (Ptr.getFieldDesc()->getElemDataSize() != 1 /*bytes*/)
       return false;
 
     if (Size > Ptr.getNumElems()) {
diff --git a/clang/lib/AST/ByteCode/Descriptor.cpp 
b/clang/lib/AST/ByteCode/Descriptor.cpp
index 5ebc726328fb7..6a192cad9bca2 100644
--- a/clang/lib/AST/ByteCode/Descriptor.cpp
+++ b/clang/lib/AST/ByteCode/Descriptor.cpp
@@ -483,3 +483,10 @@ bool Descriptor::hasTrivialDtor() const {
 }
 
 bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); 
}
+
+unsigned Descriptor::getElemDataSize() const {
+  if ((isPrimitive() || isPrimitiveArray()) && isIntegralType(getPrimType())) {
+    FIXED_SIZE_INT_TYPE_SWITCH(getPrimType(), { return T::bitWidth() / 8; });
+  }
+  return ElemSize;
+}
diff --git a/clang/lib/AST/ByteCode/Descriptor.h 
b/clang/lib/AST/ByteCode/Descriptor.h
index b052971733567..9046801f4ebef 100644
--- a/clang/lib/AST/ByteCode/Descriptor.h
+++ b/clang/lib/AST/ByteCode/Descriptor.h
@@ -246,6 +246,11 @@ struct Descriptor final {
   unsigned getAllocSize() const { return AllocSize; }
   /// returns the size of an element when the structure is viewed as an array.
   unsigned getElemSize() const { return ElemSize; }
+  /// Returns the element data size, i.e. not what the size of
+  /// our primitive data type is, but what the data size of that is.
+  /// E.g., for PT_SInt32, that's 4 bytes.
+  unsigned getElemDataSize() const;
+
   /// Returns the size of the metadata.
   unsigned getMetadataSize() const { return MDSize; }
 
diff --git a/clang/lib/AST/ByteCode/Integral.h 
b/clang/lib/AST/ByteCode/Integral.h
index e90f1a9a74e1c..82b62f7969d12 100644
--- a/clang/lib/AST/ByteCode/Integral.h
+++ b/clang/lib/AST/ByteCode/Integral.h
@@ -14,6 +14,7 @@
 #define LLVM_CLANG_AST_INTERP_INTEGRAL_H
 
 #include "clang/AST/APValue.h"
+#include "clang/AST/CharUnits.h"
 #include "clang/AST/ComparisonCategories.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/Support/MathExtras.h"
@@ -22,6 +23,7 @@
 #include <cstdint>
 
 #include "Primitives.h"
+#include "Program.h"
 
 namespace clang {
 namespace interp {
@@ -69,7 +71,7 @@ template <unsigned Bits, bool Signed> class Integral final {
 
   // The primitive representing the integral.
   using ReprT = typename Repr<Bits, Signed>::Type;
-  ReprT V;
+  ReprT V = 0;
   static_assert(std::is_trivially_copyable_v<ReprT>);
 
   /// Primitive representing limits.
@@ -83,7 +85,7 @@ template <unsigned Bits, bool Signed> class Integral final {
   using AsUnsigned = Integral<Bits, false>;
 
   /// Zero-initializes an integral.
-  Integral() : V(0) {}
+  Integral() = default;
 
   /// Constructs an integral from another integral.
   template <unsigned SrcBits, bool SrcSign>
@@ -144,15 +146,12 @@ template <unsigned Bits, bool Signed> class Integral 
final {
   }
 
   constexpr static unsigned bitWidth() { return Bits; }
+  constexpr static bool isSigned() { return Signed; }
+  constexpr static bool isNumber() { return true; }
 
   bool isZero() const { return !V; }
-
   bool isMin() const { return *this == min(bitWidth()); }
-
   bool isMinusOne() const { return Signed && V == ReprT(-1); }
-
-  constexpr static bool isSigned() { return Signed; }
-
   bool isNegative() const { return V < ReprT(0); }
   bool isPositive() const { return !isNegative(); }
 
@@ -205,7 +204,8 @@ template <unsigned Bits, bool Signed> class Integral final {
   static Integral zero(unsigned BitWidth = 0) { return from(0); }
 
   template <typename ValT>
-  static Integral from(ValT Value, unsigned NumBits = 0) {
+  static std::enable_if_t<!std::is_same_v<ValT, IntegralKind>, Integral>
+  from(ValT Value, unsigned NumBits = 0) {
     if constexpr (std::is_integral_v<ValT>)
       return Integral(Value);
     else
@@ -213,7 +213,8 @@ template <unsigned Bits, bool Signed> class Integral final {
   }
 
   template <unsigned SrcBits, bool SrcSign>
-  static Integral from(Integral<SrcBits, SrcSign> Value) {
+  static std::enable_if_t<SrcBits != 0, Integral>
+  from(Integral<SrcBits, SrcSign> Value) {
     return Integral(Value.V);
   }
 
@@ -287,7 +288,7 @@ template <unsigned Bits, bool Signed> class Integral final {
     *R = Integral::from(A.V >> B.V, OpBits);
   }
 
-private:
+public:
   template <typename T> static bool CheckAddUB(T A, T B, T &R) {
     if constexpr (std::is_signed_v<T>) {
       return llvm::AddOverflow<T>(A, B, R);
@@ -327,6 +328,367 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, 
Integral<Bits, Signed> I) {
   return OS;
 }
 
+template <unsigned Bits, bool Signed> class IntegralOrPtr final {
+  static_assert(Bits >= 32);
+
+public:
+  // The primitive representing the integral.
+  using ReprT = typename Repr<Bits, Signed>::Type;
+
+private:
+  using OffsetT = intptr_t;
+  static_assert(std::is_trivially_copyable_v<ReprT>);
+  template <unsigned OtherBits, bool OtherSigned> friend class IntegralOrPtr;
+
+  IntegralKind Kind = IntegralKind::Number;
+  union {
+    ReprT V;
+    struct {
+      const void *P;
+      OffsetT Offset;
+    } Ptr;
+  };
+
+  static_assert(sizeof(uintptr_t) >= sizeof(ReprT));
+
+  /// Primitive representing limits.
+  static const auto Min = std::numeric_limits<ReprT>::min();
+  static const auto Max = std::numeric_limits<ReprT>::max();
+
+  /// Construct an integral from anything that is convertible to storage.
+  template <typename T> explicit IntegralOrPtr(T V) : V(V) {}
+  template <typename T>
+  explicit IntegralOrPtr(IntegralKind Kind, T V) : Kind(Kind), V(V) {}
+
+public:
+  using AsUnsigned = IntegralOrPtr<Bits, false>;
+
+  /// Zero-initializes an integral.
+  IntegralOrPtr() = default;
+
+  /// Constructs an integral from another integral.
+  template <unsigned SrcBits, bool SrcSign>
+  explicit IntegralOrPtr(Integral<SrcBits, SrcSign> V) : Kind(V.Kind), V(V) {}
+
+  explicit IntegralOrPtr(IntegralKind Kind, const void *P, OffsetT Offset = 0)
+      : Kind(Kind) {
+    Ptr.P = P;
+    Ptr.Offset = Offset;
+  }
+
+  explicit IntegralOrPtr(const void *P1, const void *P2)
+      : Kind(IntegralKind::AddrLabelDiff) {
+    Ptr.P = P1;
+    Ptr.Offset = reinterpret_cast<uintptr_t>(P2);
+  }
+
+  IntegralKind getKind() const { return Kind; }
+  bool isNumber() const { return Kind == IntegralKind::Number; }
+  const void *getPtr() const {
+    assert(!isNumber());
+    return Ptr.P;
+  }
+  ReprT getOffset() const {
+    assert(!isNumber());
+    return Ptr.Offset;
+  }
+
+  /// Construct an integral from a value based on signedness.
+  explicit IntegralOrPtr(const APSInt &V)
+      : V(V.isSigned() ? V.getSExtValue() : V.getZExtValue()) {}
+
+  bool operator<(IntegralOrPtr RHS) const { return V < RHS.V; }
+  bool operator>(IntegralOrPtr RHS) const { return V > RHS.V; }
+  bool operator<=(IntegralOrPtr RHS) const { return V <= RHS.V; }
+  bool operator>=(IntegralOrPtr RHS) const { return V >= RHS.V; }
+  bool operator==(IntegralOrPtr RHS) const { return V == RHS.V; }
+  bool operator!=(IntegralOrPtr RHS) const { return V != RHS.V; }
+  bool operator>=(unsigned RHS) const {
+    return static_cast<unsigned>(V) >= RHS;
+  }
+
+  bool operator>(unsigned RHS) const {
+    return V >= 0 && static_cast<unsigned>(V) > RHS;
+  }
+
+  IntegralOrPtr operator-() const { return IntegralOrPtr(-V); }
+  IntegralOrPtr operator-(const IntegralOrPtr &Other) const {
+    return IntegralOrPtr(V - Other.V);
+  }
+  IntegralOrPtr operator~() const { return IntegralOrPtr(~V); }
+
+  template <unsigned DstBits, bool DstSign>
+  explicit operator IntegralOrPtr<DstBits, DstSign>() const {
+    return IntegralOrPtr<DstBits, DstSign>(Kind, V);
+  }
+
+  template <typename Ty, typename = std::enable_if_t<std::is_integral_v<Ty>>>
+  explicit operator Ty() const {
+    return V;
+  }
+
+  APSInt toAPSInt() const {
+    assert(isNumber());
+    return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed);
+  }
+
+  APSInt toAPSInt(unsigned BitWidth) const {
+    return APSInt(toAPInt(BitWidth), !Signed);
+  }
+
+  APInt toAPInt(unsigned BitWidth) const {
+    assert(isNumber());
+    if constexpr (Signed)
+      return APInt(Bits, static_cast<uint64_t>(V), Signed)
+          .sextOrTrunc(BitWidth);
+    else
+      return APInt(Bits, static_cast<uint64_t>(V), Signed)
+          .zextOrTrunc(BitWidth);
+  }
+
+  APValue toAPValue(const ASTContext &) const {
+    switch (Kind) {
+    case IntegralKind::Address: {
+      return APValue((const ValueDecl *)Ptr.P,
+                     CharUnits::fromQuantity(Ptr.Offset),
+                     APValue::NoLValuePath{});
+    }
+    case IntegralKind::LabelAddress: {
+      return APValue((const Expr *)Ptr.P, CharUnits::Zero(),
+                     APValue::NoLValuePath{});
+    }
+    case IntegralKind::BlockAddress: {
+      const Block *B = reinterpret_cast<const Block *>(Ptr.P);
+      const Descriptor *D = B->getDescriptor();
+      if (const Expr *E = D->asExpr())
+        return APValue(E, CharUnits::Zero(), APValue::NoLValuePath{});
+
+      return APValue(D->asValueDecl(), CharUnits::Zero(),
+                     APValue::NoLValuePath{});
+    }
+    case IntegralKind::AddrLabelDiff: {
+      return APValue(
+          (const AddrLabelExpr *)Ptr.P,
+          (const AddrLabelExpr *)reinterpret_cast<const void *>(Ptr.Offset));
+    }
+    case IntegralKind::Number:
+      return APValue(toAPSInt());
+    }
+    llvm_unreachable("Unhandled IntegralKind");
+  }
+
+  IntegralOrPtr<Bits, false> toUnsigned() const {
+    return IntegralOrPtr<Bits, false>(*this);
+  }
+
+  constexpr static unsigned bitWidth() { return Bits; }
+  constexpr static bool isSigned() { return Signed; }
+
+  bool isZero() const { return !V; }
+  bool isMin() const { return *this == min(bitWidth()); }
+  bool isMinusOne() const { return Signed && V == ReprT(-1); }
+  bool isNegative() const { return V < ReprT(0); }
+  bool isPositive() const { return !isNegative(); }
+
+  ComparisonCategoryResult compare(const IntegralOrPtr &RHS) const {
+    return Compare(V, RHS.V);
+  }
+
+  void bitcastToMemory(std::byte *Dest) const {
+    assert(isNumber());
+    std::memcpy(Dest, &V, sizeof(V));
+  }
+
+  static IntegralOrPtr bitcastFromMemory(const std::byte *Src,
+                                         unsigned BitWidth) {
+    assert(BitWidth == sizeof(ReprT) * 8);
+    ReprT V;
+
+    std::memcpy(&V, Src, sizeof(ReprT));
+    return IntegralOrPtr(V);
+  }
+
+  std::string toDiagnosticString(const ASTContext &Ctx) const {
+    std::string NameStr;
+    llvm::raw_string_ostream OS(NameStr);
+    OS << V;
+    return NameStr;
+  }
+
+  unsigned countLeadingZeros() const {
+    assert(isNumber());
+    if constexpr (!Signed)
+      return llvm::countl_zero<ReprT>(V);
+    if (isPositive())
+      return llvm::countl_zero<typename AsUnsigned::ReprT>(
+          static_cast<typename AsUnsigned::ReprT>(V));
+    llvm_unreachable("Don't call countLeadingZeros() on negative values.");
+  }
+
+  IntegralOrPtr truncate(unsigned TruncBits) const {
+    assert(TruncBits >= 1);
+    if (TruncBits >= Bits)
+      return *this;
+    const ReprT BitMask = (ReprT(1) << ReprT(TruncBits)) - 1;
+    const ReprT SignBit = ReprT(1) << (TruncBits - 1);
+    const ReprT ExtMask = ~BitMask;
+    return IntegralOrPtr((V & BitMask) |
+                         (Signed && (V & SignBit) ? ExtMask : 0));
+  }
+
+  void print(llvm::raw_ostream &OS) const {
+    switch (Kind) {
+    case IntegralKind::Number:
+      OS << V;
+      break;
+    case IntegralKind::AddrLabelDiff:
+      OS << Ptr.P << " - " << (const void *)Ptr.Offset << " (AddrLabelDiff)";
+      break;
+    case IntegralKind::Address:
+      OS << Ptr.P << " + " << Ptr.Offset << " (Address)";
+      break;
+    case IntegralKind::BlockAddress:
+      OS << Ptr.P << " + " << Ptr.Offset << " (BlockAddress)";
+      break;
+    case IntegralKind::LabelAddress:
+      OS << Ptr.P << " + " << Ptr.Offset << " (LabelAddress)";
+    }
+  }
+
+  static IntegralOrPtr min(unsigned NumBits) { return IntegralOrPtr(Min); }
+  static IntegralOrPtr max(unsigned NumBits) { return IntegralOrPtr(Max); }
+  static IntegralOrPtr zero(unsigned BitWidth = 0) { return from(0); }
+
+  template <typename ValT>
+  static std::enable_if_t<!std::is_same_v<ValT, IntegralKind>, IntegralOrPtr>
+  from(ValT V, unsigned NumBits = 0) {
+    if constexpr (std::is_integral_v<ValT>)
+      return IntegralOrPtr(V);
+    else
+      return IntegralOrPtr(static_cast<IntegralOrPtr::ReprT>(V));
+  }
+
+  template <unsigned SrcBits, bool SrcSign>
+  static std::enable_if_t<SrcBits != 0, IntegralOrPtr>
+  from(IntegralOrPtr<SrcBits, SrcSign> V) {
+    auto A = IntegralOrPtr(V.Kind, V.V);
+    switch (V.Kind) {
+    case IntegralKind::Number:
+      A.V = V.V;
+      break;
+    case IntegralKind::AddrLabelDiff:
+    case IntegralKind::Address:
+    case IntegralKind::BlockAddress:
+    case IntegralKind::LabelAddress:
+      A.Ptr.P = V.Ptr.P;
+      A.Ptr.Offset = V.Ptr.Offset;
+      break;
+    }
+    return A;
+  }
+
+  template <typename T> static IntegralOrPtr from(IntegralKind Kind, T V) {
+    return IntegralOrPtr(Kind, V);
+  }
+
+  static bool increment(IntegralOrPtr A, IntegralOrPtr *R) {
+    assert(A.isNumber());
+    return add(A, IntegralOrPtr(ReprT(1)), A.bitWidth(), R);
+  }
+
+  static bool decrement(IntegralOrPtr A, IntegralOrPtr *R) {
+    assert(A.isNumber());
+    return sub(A, IntegralOrPtr(ReprT(1)), A.bitWidth(), R);
+  }
+
+  static bool add(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                  IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    return Integral<Bits, Signed>::CheckAddUB(A.V, B.V, R->V);
+  }
+
+  static bool sub(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                  IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    return Integral<Bits, Signed>::CheckSubUB(A.V, B.V, R->V);
+  }
+
+  static bool mul(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                  IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    return Integral<Bits, Signed>::CheckMulUB(A.V, B.V, R->V);
+  }
+
+  static bool rem(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                  IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    *R = IntegralOrPtr(A.V % B.V);
+    return false;
+  }
+
+  static bool div(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                  IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    *R = IntegralOrPtr(A.V / B.V);
+    return false;
+  }
+
+  static bool bitAnd(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                     IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    *R = IntegralOrPtr(A.V & B.V);
+    return false;
+  }
+
+  static bool bitOr(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                    IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    *R = IntegralOrPtr(A.V | B.V);
+    return false;
+  }
+
+  static bool bitXor(IntegralOrPtr A, IntegralOrPtr B, unsigned OpBits,
+                     IntegralOrPtr *R) {
+    assert(A.isNumber() && B.isNumber());
+    *R = IntegralOrPtr(A.V ^ B.V);
+    return false;
+  }
+
+  static bool neg(IntegralOrPtr A, IntegralOrPtr *R) {
+    if (Signed && A.isMin())
+      return true;
+
+    *R = -A;
+    return false;
+  }
+
+  static bool comp(IntegralOrPtr A, IntegralOrPtr *R) {
+    *R = IntegralOrPtr(~A.V);
+    return false;
+  }
+
+  template <unsigned RHSBits, bool RHSSign>
+  static void shiftLeft(const IntegralOrPtr A,
+                        const IntegralOrPtr<RHSBits, RHSSign> B,
+                        unsigned OpBits, IntegralOrPtr *R) {
+    *R = IntegralOrPtr::from(A.V << B.V, OpBits);
+  }
+
+  template <unsigned RHSBits, bool RHSSign>
+  static void shiftRight(const IntegralOrPtr A,
+                         const IntegralOrPtr<RHSBits, RHSSign> B,
+                         unsigned OpBits, IntegralOrPtr *R) {
+    *R = IntegralOrPtr::from(A.V >> B.V, OpBits);
+  }
+};
+
+template <unsigned Bits, bool Signed>
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                              IntegralOrPtr<Bits, Signed> I) {
+  I.print(OS);
+  return OS;
+}
+
 } // namespace interp
 } // namespace clang
 
diff --git a/clang/lib/AST/ByteCode/IntegralAP.h 
b/clang/lib/AST/ByteCode/IntegralAP.h
index b11e6eea28e3f..9f53ac7716bba 100644
--- a/clang/lib/AST/ByteCode/IntegralAP.h
+++ b/clang/lib/AST/ByteCode/IntegralAP.h
@@ -139,6 +139,7 @@ template <bool Signed> class IntegralAP final {
   constexpr uint32_t bitWidth() const { return BitWidth; }
   constexpr unsigned numWords() const { return APInt::getNumWords(BitWidth); }
   constexpr bool singleWord() const { return numWords() == 1; }
+  constexpr static bool isNumber() { return true; }
 
   APSInt toAPSInt(unsigned Bits = 0) const {
     if (Bits == 0)
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index ebc7220aa5671..0f571f6789d10 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -88,20 +88,20 @@ static bool BCP(InterpState &S, CodePtr &RealPC, int32_t 
Offset, PrimType PT) {
     if (PT == PT_Ptr) {
       const auto &Ptr = S.Stk.pop<Pointer>();
       assert(S.Stk.size() == StackSizeBefore);
-      S.Stk.push<Integral<32, true>>(
-          Integral<32, true>::from(CheckBCPResult(S, Ptr)));
+      S.Stk.push<IntegralOrPtr<32, true>>(
+          IntegralOrPtr<32, true>::from(CheckBCPResult(S, Ptr)));
     } else {
       // Pop the result from the stack and return success.
       TYPE_SWITCH(PT, S.Stk.pop<T>(););
       assert(S.Stk.size() == StackSizeBefore);
-      S.Stk.push<Integral<32, true>>(Integral<32, true>::from(1));
+      S.Stk.push<IntegralOrPtr<32, true>>(IntegralOrPtr<32, true>::from(1));
     }
   } else {
     if (!S.inConstantContext())
       return Invalid(S, RealPC);
 
     S.Stk.clearTo(StackSizeBefore);
-    S.Stk.push<Integral<32, true>>(Integral<32, true>::from(0));
+    S.Stk.push<IntegralOrPtr<32, true>>(IntegralOrPtr<32, true>::from(0));
   }
 
   // RealPC should not have been modified.
@@ -2187,12 +2187,15 @@ bool CheckPointerToIntegralCast(InterpState &S, CodePtr 
OpPC,
   S.CCEDiag(E, diag::note_constexpr_invalid_cast)
       << 2 << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
 
-  if (Ptr.isDummy())
+  if (S.getLangOpts().CPlusPlus && Ptr.isDummy() && !Ptr.pointsToLabel())
     return false;
-  if (Ptr.isFunctionPointer())
+  if (Ptr.isIntegralPointer())
+    return true;
+
+  if (Ptr.isDummy())
     return true;
 
-  if (Ptr.isBlockPointer() && !Ptr.isZero()) {
+  if (!Ptr.isZero()) {
     // Only allow based lvalue casts if they are lossless.
     if (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) !=
         BitWidth)
@@ -2201,6 +2204,11 @@ bool CheckPointerToIntegralCast(InterpState &S, CodePtr 
OpPC,
   return true;
 }
 
+bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth) 
{
+  return (S.getASTContext().getTargetInfo().getPointerWidth(LangAS::Default) ==
+          BitWidth);
+}
+
 bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
   const Pointer &Ptr = S.Stk.pop<Pointer>();
 
@@ -2286,13 +2294,19 @@ bool DiagTypeid(InterpState &S, CodePtr OpPC) {
 
 bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS,
                                              const Pointer &RHS) {
+  if (!LHS.pointsToStringLiteral() || !RHS.pointsToStringLiteral())
+    return false;
+
   unsigned LHSOffset = LHS.isOnePastEnd() ? LHS.getNumElems() : LHS.getIndex();
   unsigned RHSOffset = RHS.isOnePastEnd() ? RHS.getNumElems() : RHS.getIndex();
-  unsigned LHSLength = (LHS.getNumElems() - 1) * LHS.elemSize();
-  unsigned RHSLength = (RHS.getNumElems() - 1) * RHS.elemSize();
+  const auto *LHSLit = cast<StringLiteral>(LHS.getDeclDesc()->asExpr());
+  const auto *RHSLit = cast<StringLiteral>(RHS.getDeclDesc()->asExpr());
+
+  StringRef LHSStr(LHSLit->getBytes());
+  unsigned LHSLength = LHSStr.size();
+  StringRef RHSStr(RHSLit->getBytes());
+  unsigned RHSLength = RHSStr.size();
 
-  StringRef LHSStr((const char *)LHS.atIndex(0).getRawAddress(), LHSLength);
-  StringRef RHSStr((const char *)RHS.atIndex(0).getRawAddress(), RHSLength);
   int32_t IndexDiff = RHSOffset - LHSOffset;
   if (IndexDiff < 0) {
     if (static_cast<int32_t>(LHSLength) < -IndexDiff)
@@ -2308,11 +2322,11 @@ bool arePotentiallyOverlappingStringLiterals(const 
Pointer &LHS,
   StringRef Shorter;
   StringRef Longer;
   if (LHSLength < RHSLength) {
-    ShorterCharWidth = LHS.elemSize();
+    ShorterCharWidth = LHS.getFieldDesc()->getElemDataSize();
     Shorter = LHSStr;
     Longer = RHSStr;
   } else {
-    ShorterCharWidth = RHS.elemSize();
+    ShorterCharWidth = RHS.getFieldDesc()->getElemDataSize();
     Shorter = RHSStr;
     Longer = LHSStr;
   }
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index 7f30def20cc36..3df632ed45c5f 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -280,6 +280,11 @@ template <typename T, bool (*OpFW)(T, T, unsigned, T *),
           template <typename U> class OpAP>
 bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
                      const T &RHS) {
+  // Should've been handled before.
+  if constexpr (isIntegralOrPointer<T>()) {
+    assert(LHS.isNumber() && RHS.isNumber());
+  }
+
   // Fast path - add the numbers with fixed width.
   T Result;
   if constexpr (needsAlloc<T>())
@@ -318,12 +323,46 @@ bool AddSubMulHelper(InterpState &S, CodePtr OpPC, 
unsigned Bits, const T &LHS,
   return true;
 }
 
+// Add or subtract an integer-thats-actually-a-pointer and one real integer.
+template <typename T, template <typename U> class Op>
+static bool AddSubNonNumber(InterpState &S, CodePtr OpPC, T LHS, T RHS) {
+  assert(!LHS.isNumber() || !RHS.isNumber());
+
+  typename T::ReprT Number;
+  const void *Ptr;
+  typename T::ReprT Offset;
+  IntegralKind Kind;
+  if (LHS.isNumber()) {
+    Number = static_cast<typename T::ReprT>(LHS);
+    Ptr = RHS.getPtr();
+    Offset = RHS.getOffset();
+    Kind = RHS.getKind();
+  } else {
+    assert(RHS.isNumber());
+    Number = static_cast<typename T::ReprT>(RHS);
+    Ptr = LHS.getPtr();
+    Offset = LHS.getOffset();
+    Kind = LHS.getKind();
+  }
+  S.Stk.push<T>(Kind, Ptr, Op<typename T::ReprT>()(Offset, Number));
+  return true;
+}
+
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool Add(InterpState &S, CodePtr OpPC) {
   const T &RHS = S.Stk.pop<T>();
   const T &LHS = S.Stk.pop<T>();
   const unsigned Bits = RHS.bitWidth() + 1;
 
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (LHS.isNumber() != RHS.isNumber())
+      return AddSubNonNumber<T, std::plus>(S, OpPC, LHS, RHS);
+    else if (LHS.isNumber() && RHS.isNumber())
+      ; // Fall through to proper addition below.
+    else
+      return false; // Reject everything else.
+  }
+
   return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
 }
 
@@ -344,6 +383,35 @@ bool Sub(InterpState &S, CodePtr OpPC) {
   const T &LHS = S.Stk.pop<T>();
   const unsigned Bits = RHS.bitWidth() + 1;
 
+  if constexpr (isIntegralOrPointer<T>()) {
+    // Handle (int)&&a - (int)&&b.
+    // Both operands should be integrals that point to labels and the result is
+    // a AddrLabelDiff integral.
+    if (LHS.getKind() == IntegralKind::LabelAddress ||
+        RHS.getKind() == IntegralKind::LabelAddress) {
+      const auto *A = reinterpret_cast<const Expr *>(LHS.getPtr());
+      const auto *B = reinterpret_cast<const Expr *>(RHS.getPtr());
+      if (!isa<AddrLabelExpr>(A) || !isa<AddrLabelExpr>(B))
+        return false;
+      const auto *LHSAddrExpr = cast<AddrLabelExpr>(A);
+      const auto *RHSAddrExpr = cast<AddrLabelExpr>(B);
+
+      if (LHSAddrExpr->getLabel()->getDeclContext() !=
+          RHSAddrExpr->getLabel()->getDeclContext())
+        return Invalid(S, OpPC);
+
+      S.Stk.push<T>(LHSAddrExpr, RHSAddrExpr);
+      return true;
+    }
+
+    if (!LHS.isNumber() && RHS.isNumber())
+      return AddSubNonNumber<T, std::minus>(S, OpPC, LHS, RHS);
+    else if (LHS.isNumber() && RHS.isNumber())
+      ; // Fall through to proper addition below.
+    else
+      return false; // Reject everything else.
+  }
+
   return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
 }
 
@@ -364,6 +432,11 @@ bool Mul(InterpState &S, CodePtr OpPC) {
   const T &LHS = S.Stk.pop<T>();
   const unsigned Bits = RHS.bitWidth() * 2;
 
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (!LHS.isNumber() || !RHS.isNumber())
+      return Invalid(S, OpPC);
+  }
+
   return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
 }
 
@@ -1049,6 +1122,12 @@ bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn 
Fn) {
   using BoolT = PrimConv<PT_Bool>::T;
   const T &RHS = S.Stk.pop<T>();
   const T &LHS = S.Stk.pop<T>();
+
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (!LHS.isNumber() || !RHS.isNumber())
+      return Invalid(S, OpPC);
+  }
+
   S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
   return true;
 }
@@ -1376,7 +1455,20 @@ bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
     S.Stk.push<T>(Result);
     return true;
   }
-  S.Stk.push<T>(Arg);
+
+  if constexpr (std::is_same_v<T, uint32_t>) {
+    S.Stk.push<IntegralOrPtr<32, false>>(IntegralOrPtr<32, false>::from(Arg));
+  } else if constexpr (std::is_same_v<T, int32_t>) {
+    S.Stk.push<IntegralOrPtr<32, true>>(IntegralOrPtr<32, true>::from(Arg));
+  } else if constexpr (std::is_same_v<T, uint64_t>) {
+    S.Stk.push<IntegralOrPtr<64, false>>(IntegralOrPtr<64, false>::from(Arg));
+  } else if constexpr (std::is_same_v<T, int64_t>) {
+    S.Stk.push<IntegralOrPtr<64, true>>(IntegralOrPtr<64, true>::from(Arg));
+  } else {
+    // Bool.
+    S.Stk.push<T>(Arg);
+  }
+
   return true;
 }
 
@@ -2451,6 +2543,26 @@ inline bool SubPtr(InterpState &S, CodePtr OpPC, bool 
ElemSizeIsZero) {
   const Pointer &LHS = S.Stk.pop<Pointer>().expand();
   const Pointer &RHS = S.Stk.pop<Pointer>().expand();
 
+  if (LHS.pointsToLabel() || RHS.pointsToLabel()) {
+    if constexpr (isIntegralOrPointer<T>()) {
+      const auto *LHSAddrExpr =
+          dyn_cast_if_present<AddrLabelExpr>(LHS.getDeclDesc()->asExpr());
+      const auto *RHSAddrExpr =
+          dyn_cast_if_present<AddrLabelExpr>(RHS.getDeclDesc()->asExpr());
+      if (!LHSAddrExpr || !RHSAddrExpr)
+        return false;
+
+      if (LHSAddrExpr->getLabel()->getDeclContext() !=
+          RHSAddrExpr->getLabel()->getDeclContext())
+        return Invalid(S, OpPC);
+
+      S.Stk.push<T>(LHSAddrExpr, RHSAddrExpr);
+      return true;
+    }
+    // Can't represent an address-label-diff in these types.
+    return false;
+  }
+
   if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
     S.FFDiag(S.Current->getSource(OpPC),
              diag::note_constexpr_pointer_arith_unspecified)
@@ -2520,7 +2632,27 @@ inline bool GetLocalEnabled(InterpState &S, CodePtr 
OpPC, uint32_t I) {
 template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) 
{
   using T = typename PrimConv<TIn>::T;
   using U = typename PrimConv<TOut>::T;
-  S.Stk.push<U>(U::from(S.Stk.pop<T>()));
+
+  auto In = S.Stk.pop<T>();
+
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (In.getKind() != IntegralKind::Number &&
+        In.getKind() != IntegralKind::AddrLabelDiff) {
+      if (!CheckIntegralAddressCast(S, OpPC, In.bitWidth()))
+        return Invalid(S, OpPC);
+    } else if (In.getKind() == IntegralKind::AddrLabelDiff) {
+      // Allow casts of address-of-label differences if they are no-ops
+      // or narrowing, if the result is at least 32 bits wide.
+      // (The narrowing case isn't actually guaranteed to
+      // be constant-evaluatable except in some narrow cases which are hard
+      // to detect here.  We let it through on the assumption the user knows
+      // what they are doing.)
+      if (!(U::bitWidth() >= 32 && U::bitWidth() <= In.bitWidth()))
+        return false;
+    }
+  }
+
+  S.Stk.push<U>(U::from(In));
   return true;
 }
 
@@ -2554,11 +2686,18 @@ inline bool CastFixedPoint(InterpState &S, CodePtr 
OpPC, uint32_t FPS) {
 /// to know what bitwidth the result should be.
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+  T Source = S.Stk.pop<T>();
+
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (!Source.isNumber())
+      return false;
+  }
+
   auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
   // Copy data.
   {
-    APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
-    Result.copy(Source);
+    APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
+    Result.copy(SourceInt);
   }
   S.Stk.push<IntegralAP<false>>(Result);
   return true;
@@ -2566,11 +2705,18 @@ bool CastAP(InterpState &S, CodePtr OpPC, uint32_t 
BitWidth) {
 
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
+  T Source = S.Stk.pop<T>();
+
+  if constexpr (isIntegralOrPointer<T>()) {
+    if (!Source.isNumber())
+      return false;
+  }
+
   auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
   // Copy data.
   {
-    APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
-    Result.copy(Source);
+    APInt SourceInt = Source.toAPSInt().extOrTrunc(BitWidth);
+    Result.copy(SourceInt);
   }
   S.Stk.push<IntegralAP<true>>(Result);
   return true;
@@ -2668,6 +2814,7 @@ static inline bool CastFloatingIntegralAPS(InterpState 
&S, CodePtr OpPC,
 
 bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
                                 const Pointer &Ptr, unsigned BitWidth);
+bool CheckIntegralAddressCast(InterpState &S, CodePtr OpPC, unsigned BitWidth);
 bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
 bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
 
@@ -2678,7 +2825,35 @@ bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
   if (!CheckPointerToIntegralCast(S, OpPC, Ptr, T::bitWidth()))
     return Invalid(S, OpPC);
 
-  S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
+  if constexpr (std::is_same_v<T, Boolean>) {
+    S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
+  } else if constexpr (isIntegralOrPointer<T>()) {
+    if (Ptr.isBlockPointer()) {
+      IntegralKind Kind = IntegralKind::Address;
+      const void *PtrVal;
+      if (Ptr.isDummy()) {
+        if (const Expr *E = Ptr.getDeclDesc()->asExpr()) {
+          PtrVal = E;
+          if (isa<AddrLabelExpr>(E))
+            Kind = IntegralKind::LabelAddress;
+        } else {
+          PtrVal = Ptr.getDeclDesc()->asDecl();
+        }
+      } else {
+        PtrVal = Ptr.block();
+        Kind = IntegralKind::BlockAddress;
+      }
+      S.Stk.push<T>(Kind, PtrVal, /*Offset=*/0);
+    } else if (Ptr.isFunctionPointer()) {
+      const void *FuncDecl = Ptr.asFunctionPointer().getFunction()->getDecl();
+      S.Stk.push<T>(IntegralKind::Address, FuncDecl, /*Offset=*/0);
+    } else {
+      // FIXME: Is this still possible?
+      S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
+    }
+  } else {
+    return false;
+  }
   return true;
 }
 
@@ -3253,7 +3428,28 @@ inline bool GetIntPtr(InterpState &S, CodePtr OpPC, 
const Descriptor *Desc) {
       << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
       << S.getLangOpts().CPlusPlus;
 
-  S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
+  if constexpr (isIntegralOrPointer<T>()) {
+
+    if (IntVal.getKind() == IntegralKind::Address) {
+      if (IntVal.getOffset() != 0) {
+        return Invalid(S, OpPC);
+      }
+      const VarDecl *VD = (const VarDecl *)IntVal.getPtr();
+      unsigned GlobalIndex = *S.P.getOrCreateGlobal(VD);
+      S.Stk.push<Pointer>(S.P.getGlobal(GlobalIndex));
+    } else if (IntVal.getKind() == IntegralKind::BlockAddress) {
+      if (IntVal.getOffset() != 0) {
+        return Invalid(S, OpPC);
+      }
+      const Block *B = (const Block *)IntVal.getPtr();
+      S.Stk.push<Pointer>(const_cast<Block *>(B));
+    } else {
+      S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
+    }
+  } else {
+    S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
+  }
+
   return true;
 }
 
@@ -3396,7 +3592,8 @@ template <PrimType Name, class T = typename 
PrimConv<Name>::T>
 inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
   llvm::SmallVector<int64_t> ArrayIndices;
   for (size_t I = 0; I != E->getNumExpressions(); ++I)
-    ArrayIndices.emplace_back(S.Stk.pop<int64_t>());
+    ArrayIndices.emplace_back(
+        static_cast<int64_t>(S.Stk.pop<IntegralOrPtr<64, true>>()));
 
   int64_t Result;
   if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index c7d3c2e500592..82fe6cfebce5d 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -364,14 +364,15 @@ static bool interp__builtin_strlen(InterpState &S, 
CodePtr OpPC,
     return false;
 
   assert(StrPtr.getFieldDesc()->isPrimitiveArray());
-  unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
+  PrimType ElemT = StrPtr.getFieldDesc()->getPrimType();
+  unsigned ElemSize = StrPtr.getFieldDesc()->getElemDataSize();
   if (ElemSize != 1 && ElemSize != 2 && ElemSize != 4)
     return Invalid(S, OpPC);
 
   if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
     const ASTContext &AC = S.getASTContext();
     unsigned WCharSize = 
AC.getTypeSizeInChars(AC.getWCharType()).getQuantity();
-    if (ElemSize != WCharSize)
+    if (StrPtr.getFieldDesc()->getElemDataSize() != WCharSize)
       return false;
   }
 
@@ -383,19 +384,8 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr 
OpPC,
       return false;
 
     uint32_t Val;
-    switch (ElemSize) {
-    case 1:
-      Val = ElemPtr.deref<uint8_t>();
-      break;
-    case 2:
-      Val = ElemPtr.deref<uint16_t>();
-      break;
-    case 4:
-      Val = ElemPtr.deref<uint32_t>();
-      break;
-    default:
-      llvm_unreachable("Unsupported char size");
-    }
+    FIXED_SIZE_INT_TYPE_SWITCH(
+        ElemT, { Val = static_cast<uint32_t>(ElemPtr.deref<T>()); });
     if (Val == 0)
       break;
   }
@@ -1383,11 +1373,11 @@ 
interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
   const auto &Ptr = S.Stk.pop<Pointer>();
   assert(Ptr.getFieldDesc()->isPrimitiveArray());
 
-  // This should be created for a StringLiteral, so should alway shold at least
+  // This should be created for a StringLiteral, so always holds at least
   // one array element.
   assert(Ptr.getFieldDesc()->getNumElems() >= 1);
-  StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);
-  uint64_t Result = getPointerAuthStableSipHash(R);
+  uint64_t Result = getPointerAuthStableSipHash(
+      cast<StringLiteral>(Ptr.getFieldDesc()->asExpr())->getString());
   pushInteger(S, Result, Call->getType());
   return true;
 }
@@ -1928,8 +1918,8 @@ static bool interp__builtin_memcpy(InterpState &S, 
CodePtr OpPC,
     Pointer SrcP = SrcPtr.stripBaseCasts();
     Pointer DestP = DestPtr.stripBaseCasts();
 
-    unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
-    unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
+    unsigned SrcIndex = SrcP.expand().getIndex() * SrcElemSize;
+    unsigned DstIndex = DestP.expand().getIndex() * DestElemSize;
 
     if ((SrcIndex <= DstIndex && (SrcIndex + Size) > DstIndex) ||
         (DstIndex <= SrcIndex && (DstIndex + Size) > SrcIndex)) {
@@ -1997,6 +1987,7 @@ static bool interp__builtin_memcmp(InterpState &S, 
CodePtr OpPC,
   BitcastBuffer BufferA(
       Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
   readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
+
   // FIXME: The swapping here is UNDOING something we do when reading the
   // data into the buffer.
   if (ASTCtx.getTargetInfo().isBigEndian())
@@ -2023,21 +2014,22 @@ static bool interp__builtin_memcmp(InterpState &S, 
CodePtr OpPC,
 
   for (size_t I = 0; I != CmpSize; I += ElemSize) {
     if (IsWide) {
-      INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {
-        T A = *reinterpret_cast<T *>(BufferA.atByte(I));
-        T B = *reinterpret_cast<T *>(BufferB.atByte(I));
-        if (A < B) {
-          pushInteger(S, -1, Call->getType());
-          return true;
-        }
-        if (A > B) {
-          pushInteger(S, 1, Call->getType());
-          return true;
-        }
-      });
+      FIXED_SIZE_INT_TYPE_SWITCH(
+          *S.getContext().classify(ASTCtx.getWCharType()), {
+            T A = T::bitcastFromMemory(BufferA.atByte(I), T::bitWidth());
+            T B = T::bitcastFromMemory(BufferB.atByte(I), T::bitWidth());
+            if (A < B) {
+              pushInteger(S, -1, Call->getType());
+              return true;
+            }
+            if (A > B) {
+              pushInteger(S, 1, Call->getType());
+              return true;
+            }
+          });
     } else {
-      std::byte A = BufferA.deref<std::byte>(Bytes(I));
-      std::byte B = BufferB.deref<std::byte>(Bytes(I));
+      auto A = BufferA.deref<std::byte>(Bytes(I));
+      auto B = BufferB.deref<std::byte>(Bytes(I));
 
       if (A < B) {
         pushInteger(S, -1, Call->getType());
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp 
b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 4bd9c66fc9974..12efd96128b71 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -311,7 +311,12 @@ bool clang::interp::readPointerToBuffer(const Context &Ctx,
 
           Buffer.markInitialized(BitOffset, NumBits);
         } else {
-          BITCAST_TYPE_SWITCH(T, { P.deref<T>().bitcastToMemory(Buff.get()); 
});
+          BITCAST_TYPE_SWITCH(T, {
+            auto Val = P.deref<T>();
+            if (!Val.isNumber())
+              return false;
+            Val.bitcastToMemory(Buff.get());
+          });
 
           if (llvm::sys::IsBigEndianHost)
             swapBytes(Buff.get(), FullBitWidth.roundToBytes());
@@ -472,9 +477,10 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr 
OpPC,
 using PrimTypeVariant =
     std::variant<Pointer, FunctionPointer, MemberPointer, FixedPoint,
                  Integral<8, false>, Integral<8, true>, Integral<16, false>,
-                 Integral<16, true>, Integral<32, false>, Integral<32, true>,
-                 Integral<64, false>, Integral<64, true>, IntegralAP<true>,
-                 IntegralAP<false>, Boolean, Floating>;
+                 Integral<16, true>, IntegralOrPtr<32, false>,
+                 IntegralOrPtr<32, true>, IntegralOrPtr<64, false>,
+                 IntegralOrPtr<64, true>, IntegralAP<true>, IntegralAP<false>,
+                 Boolean, Floating>;
 
 // NB: This implementation isn't exactly ideal, but:
 //   1) We can't just do a bitcast here since we need to be able to
diff --git a/clang/lib/AST/ByteCode/InterpStack.h 
b/clang/lib/AST/ByteCode/InterpStack.h
index c647dfa6d85ea..77fa790ac046d 100644
--- a/clang/lib/AST/ByteCode/InterpStack.h
+++ b/clang/lib/AST/ByteCode/InterpStack.h
@@ -185,18 +185,15 @@ class InterpStack final {
     else if constexpr (std::is_same_v<T, uint16_t> ||
                        std::is_same_v<T, Integral<16, false>>)
       return PT_Uint16;
-    else if constexpr (std::is_same_v<T, int32_t> ||
-                       std::is_same_v<T, Integral<32, true>>)
+    else if constexpr (std::is_same_v<T, IntegralOrPtr<32, true>>)
       return PT_Sint32;
-    else if constexpr (std::is_same_v<T, uint32_t> ||
-                       std::is_same_v<T, Integral<32, false>>)
+    else if constexpr (std::is_same_v<T, IntegralOrPtr<32, false>>)
       return PT_Uint32;
-    else if constexpr (std::is_same_v<T, int64_t> ||
-                       std::is_same_v<T, Integral<64, true>>)
+    else if constexpr (std::is_same_v<T, IntegralOrPtr<64, true>>)
       return PT_Sint64;
-    else if constexpr (std::is_same_v<T, uint64_t> ||
-                       std::is_same_v<T, Integral<64, false>>)
+    else if constexpr (std::is_same_v<T, IntegralOrPtr<64, false>>)
       return PT_Uint64;
+
     else if constexpr (std::is_same_v<T, Floating>)
       return PT_Float;
     else if constexpr (std::is_same_v<T, IntegralAP<true>>)
diff --git a/clang/lib/AST/ByteCode/Pointer.cpp 
b/clang/lib/AST/ByteCode/Pointer.cpp
index f4352e7edf5f8..866a77cb25ce8 100644
--- a/clang/lib/AST/ByteCode/Pointer.cpp
+++ b/clang/lib/AST/ByteCode/Pointer.cpp
@@ -745,6 +745,15 @@ bool Pointer::pointsToStringLiteral() const {
   return isa_and_nonnull<StringLiteral>(E);
 }
 
+bool Pointer::pointsToLabel() const {
+  if (isZero() || !isBlockPointer())
+    return false;
+
+  if (const Expr *E = BS.Pointee->getDescriptor()->asExpr())
+    return isa<AddrLabelExpr>(E);
+  return false;
+}
+
 std::optional<std::pair<Pointer, Pointer>>
 Pointer::computeSplitPoint(const Pointer &A, const Pointer &B) {
   if (!A.isBlockPointer() || !B.isBlockPointer())
diff --git a/clang/lib/AST/ByteCode/Pointer.h b/clang/lib/AST/ByteCode/Pointer.h
index 010e917de81b2..65af81817f9d3 100644
--- a/clang/lib/AST/ByteCode/Pointer.h
+++ b/clang/lib/AST/ByteCode/Pointer.h
@@ -366,7 +366,7 @@ class Pointer {
     if (isIntegralPointer()) {
       if (!Int.Desc)
         return 1;
-      return Int.Desc->getElemSize();
+      return Int.Desc->getElemDataSize();
     }
 
     if (BS.Base == RootPtrMark)
@@ -809,6 +809,8 @@ class Pointer {
   /// i.e. a non-MaterializeTemporaryExpr Expr.
   bool pointsToLiteral() const;
   bool pointsToStringLiteral() const;
+  /// Whether this points to a block created for an AddrLabelExpr.
+  bool pointsToLabel() const;
 
   /// Prints the pointer.
   void print(llvm::raw_ostream &OS) const;
diff --git a/clang/lib/AST/ByteCode/PrimType.h 
b/clang/lib/AST/ByteCode/PrimType.h
index 2433eb33c47b1..5c68aa38399ea 100644
--- a/clang/lib/AST/ByteCode/PrimType.h
+++ b/clang/lib/AST/ByteCode/PrimType.h
@@ -29,6 +29,7 @@ class MemberPointer;
 class FixedPoint;
 template <bool Signed> class IntegralAP;
 template <unsigned Bits, bool Signed> class Integral;
+template <unsigned Bits, bool Signed> class IntegralOrPtr;
 
 /// Enumeration of the primitive types of the VM.
 enum PrimType : uint8_t {
@@ -135,6 +136,13 @@ constexpr bool needsAlloc(PrimType T) {
   return T == PT_IntAP || T == PT_IntAPS || T == PT_Float || T == PT_MemberPtr;
 }
 
+template <typename T> constexpr bool isIntegralOrPointer() {
+  return std::is_same_v<T, IntegralOrPtr<32, false>> ||
+         std::is_same_v<T, IntegralOrPtr<32, true>> ||
+         std::is_same_v<T, IntegralOrPtr<64, false>> ||
+         std::is_same_v<T, IntegralOrPtr<64, true>>;
+}
+
 /// Mapping from primitive types to their representation.
 template <PrimType T> struct PrimConv;
 template <> struct PrimConv<PT_Sint8> {
@@ -150,16 +158,16 @@ template <> struct PrimConv<PT_Uint16> {
   using T = Integral<16, false>;
 };
 template <> struct PrimConv<PT_Sint32> {
-  using T = Integral<32, true>;
+  using T = IntegralOrPtr<32, true>;
 };
 template <> struct PrimConv<PT_Uint32> {
-  using T = Integral<32, false>;
+  using T = IntegralOrPtr<32, false>;
 };
 template <> struct PrimConv<PT_Sint64> {
-  using T = Integral<64, true>;
+  using T = IntegralOrPtr<64, true>;
 };
 template <> struct PrimConv<PT_Uint64> {
-  using T = Integral<64, false>;
+  using T = IntegralOrPtr<64, false>;
 };
 template <> struct PrimConv<PT_IntAP> {
   using T = IntegralAP<false>;
@@ -249,6 +257,22 @@ static inline bool aligned(const void *P) {
     }                                                                          
\
   } while (0)
 
+#define FIXED_SIZE_INT_TYPE_SWITCH(Expr, B)                                    
\
+  do {                                                                         
\
+    switch (Expr) {                                                            
\
+      TYPE_SWITCH_CASE(PT_Sint8, B)                                            
\
+      TYPE_SWITCH_CASE(PT_Uint8, B)                                            
\
+      TYPE_SWITCH_CASE(PT_Sint16, B)                                           
\
+      TYPE_SWITCH_CASE(PT_Uint16, B)                                           
\
+      TYPE_SWITCH_CASE(PT_Sint32, B)                                           
\
+      TYPE_SWITCH_CASE(PT_Uint32, B)                                           
\
+      TYPE_SWITCH_CASE(PT_Sint64, B)                                           
\
+      TYPE_SWITCH_CASE(PT_Uint64, B)                                           
\
+    default:                                                                   
\
+      llvm_unreachable("Not an integer value");                                
\
+    }                                                                          
\
+  } while (0)
+
 #define INT_TYPE_SWITCH_NO_BOOL(Expr, B)                                       
\
   do {                                                                         
\
     switch (Expr) {                                                            
\
diff --git a/clang/lib/AST/ByteCode/Primitives.h 
b/clang/lib/AST/ByteCode/Primitives.h
index e935dbfd3691c..424afb1f8007b 100644
--- a/clang/lib/AST/ByteCode/Primitives.h
+++ b/clang/lib/AST/ByteCode/Primitives.h
@@ -21,6 +21,14 @@
 namespace clang {
 namespace interp {
 
+enum class IntegralKind : uint8_t {
+  Number = 0,
+  Address,
+  BlockAddress,
+  LabelAddress,
+  AddrLabelDiff
+};
+
 /// Helper to compare two comparable types.
 template <typename T> ComparisonCategoryResult Compare(const T &X, const T &Y) 
{
   if (X < Y)
diff --git a/clang/test/AST/ByteCode/addr-label-diff.c 
b/clang/test/AST/ByteCode/addr-label-diff.c
new file mode 100644
index 0000000000000..b8f77ecf041cd
--- /dev/null
+++ b/clang/test/AST/ByteCode/addr-label-diff.c
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o -                           
              | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o - 
-fexperimental-new-constant-interpreter | FileCheck %s
+
+typedef __typeof((int*) 0 - (int*) 0) intptr_t;
+
+// CHECK: @f1.l0 = internal global i64 ptrtoint (ptr @f1 to i64)
+void f1(void) { static intptr_t l0 = (intptr_t) f1; }
+
+// CHECK: @FoldableAddrLabelDiff.x = internal global i64 sub (i64 ptrtoint 
(ptr blockaddress(@FoldableAddrLabelDiff, %a) to i64), i64 ptrtoint (ptr 
blockaddress(@FoldableAddrLabelDiff, %b) to i64)), align 8
+void FoldableAddrLabelDiff() { static long x = (long)&&a-(long)&&b; 
a:b:return;}
+
+// CHECK: @c.ar = internal global {{.*}} sub (i{{..}} ptrtoint (ptr 
blockaddress(@c, %l2) to i{{..}}), i{{..}} ptrtoint (ptr blockaddress(@c, %l1) 
to i{{..}}))
+int c(void) {
+  static int ar = &&l2 - &&l1;
+l1:
+  return 10;
+l2:
+  return 11;
+}
diff --git a/clang/test/AST/ByteCode/addr-label-diff.cpp 
b/clang/test/AST/ByteCode/addr-label-diff.cpp
new file mode 100644
index 0000000000000..336a0fbe3de3e
--- /dev/null
+++ b/clang/test/AST/ByteCode/addr-label-diff.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o -                           
              | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64 -emit-llvm %s -o - 
-fexperimental-new-constant-interpreter | FileCheck %s
+
+
+// Make sure we don't try to fold this either.
+// CHECK: @_ZZ23UnfoldableAddrLabelDiffvE1x = internal global i128 0
+void UnfoldableAddrLabelDiff() { static __int128_t x = (long)&&a-(long)&&b; 
a:b:return;}
+
+// CHECK: @_ZZ24UnfoldableAddrLabelDiff2vE1x = internal global i16 0
+void UnfoldableAddrLabelDiff2() { static short x = (long)&&a-(long)&&b; 
a:b:return;}
+
+
+// But make sure we do fold this.
+// CHECK: @_ZZ21FoldableAddrLabelDiffvE1x = internal global i64 sub (i64 
ptrtoint (ptr blockaddress(@_Z21FoldableAddrLabelDiffv
+void FoldableAddrLabelDiff() { static long x = (long)&&a-(long)&&b; 
a:b:return;}
+
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp 
b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index 09a67e60fb3be..4e3a5cd295458 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -590,3 +590,11 @@ namespace ToPrimPtrs {
                                                                                
 // both-note {{bit_cast to a member pointer type is not allowed in a constant 
expression}}
 #endif
 }
+
+namespace NonNumbers {
+#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
+  constexpr long fn(void) {
+    return __builtin_bit_cast(long, fold((long)&fn));
+  }
+  static_assert(fn() == 1); // both-error {{not an integral constant 
expression}}
+}
diff --git a/clang/test/AST/ByteCode/const-eval.c 
b/clang/test/AST/ByteCode/const-eval.c
index 70b2a4dbd86e4..e61050e5e3040 100644
--- a/clang/test/AST/ByteCode/const-eval.c
+++ b/clang/test/AST/ByteCode/const-eval.c
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=both,ref      -triple x86_64-linux %s 
-Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
-// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple x86_64-linux %s 
-Wno-tautological-pointer-compare -Wno-pointer-to-int-cast 
-fexperimental-new-constant-interpreter -DNEW_INTERP
+// RUN: %clang_cc1 -fsyntax-only -verify=both,ref      -triple x86_64-linux    
        %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast
+// RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple x86_64-linux    
        %s -Wno-tautological-pointer-compare -Wno-pointer-to-int-cast 
-fexperimental-new-constant-interpreter -DNEW_INTERP
 // RUN: %clang_cc1 -fsyntax-only -verify=both,ref      -triple 
powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare 
-Wno-pointer-to-int-cast
 // RUN: %clang_cc1 -fsyntax-only -verify=both,expected -triple 
powerpc64-ibm-aix-xcoff %s -Wno-tautological-pointer-compare 
-Wno-pointer-to-int-cast -fexperimental-new-constant-interpreter -DNEW_INTERP
 
@@ -127,7 +127,7 @@ EVAL_EXPR(43, varfloat && constfloat) // both-error {{not 
an integer constant ex
 EVAL_EXPR(45, ((char*)-1) + 1 == 0 ? 1 : -1)
 EVAL_EXPR(46, ((char*)-1) + 1 < (char*) -1 ? 1 : -1)
 EVAL_EXPR(47, &x < &x + 1 ? 1 : -1)
-EVAL_EXPR(48, &x != &x - 1 ? 1 : -1) // expected-error {{declared as an array 
with a negative size}}
+EVAL_EXPR(48, &x != &x - 1 ? 1 : -1)
 EVAL_EXPR(49, &x < &x - 100 ? 1 : -1) // ref-error {{not an integer constant 
expression}}
 
 extern struct Test50S Test50;
@@ -173,6 +173,9 @@ _Static_assert(A > B, "");
 int * GH149500_p = &(*(int *)0x400);
 static const void *GH149500_q = &(*(const struct sysrq_key_op *)0);
 
+
+void f0(void) { static intptr_t l0 = (unsigned)(intptr_t) f0;} // both-error 
{{initializer element is not a compile-time constant}}
+
 #else
 #error :(
 #endif
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index e1fb5948b7708..91c828abd87a9 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -423,3 +423,15 @@ namespace DummyToGlobalBlockMove {
   Baz Bar::_m[] = {{0}};
   const AP m = {&Bar ::m};
 }
+
+namespace AddSubMulNonNumber {
+#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
+
+  typedef decltype(sizeof(int)) LabelDiffTy;
+  constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // both-note 
{{subexpression}}
+  void LabelDiffTest() {
+    static_assert(mulBy3(fold((LabelDiffTy)&&a-(LabelDiffTy)&&b)) == 3, ""); 
// both-error {{constant expression}} \
+                                                                             
// both-note {{call to 'mulBy3(&&a - &&b)'}}
+    a:b:return;
+  }
+}
diff --git a/clang/test/AST/ByteCode/int-as-ptr-arith.c 
b/clang/test/AST/ByteCode/int-as-ptr-arith.c
new file mode 100644
index 0000000000000..af411607228ff
--- /dev/null
+++ b/clang/test/AST/ByteCode/int-as-ptr-arith.c
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -triple x86_64 %s                                         
-emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64 %s -fexperimental-new-constant-interpreter 
-emit-llvm -o - | FileCheck %s
+
+int a;
+__UINTPTR_TYPE__ ptrasintadd1 = (__UINTPTR_TYPE__)&a - 4;
+__UINTPTR_TYPE__ ptrasintadd2 = (__UINTPTR_TYPE__)&a + 4;
+__UINTPTR_TYPE__ ptrasintadd3 = ((__UINTPTR_TYPE__)&a + 4) + 10;
+__UINTPTR_TYPE__ ptrasintadd4 = (__UINTPTR_TYPE__)&a + ((__UINTPTR_TYPE__)-1);
+__UINTPTR_TYPE__ ptrasintadd5 = 4 + (__UINTPTR_TYPE__)&a;
+__UINTPTR_TYPE__ ptrasintadd6 = 10 + ((__UINTPTR_TYPE__)&a + 4);
+
+// CHECK: @ptrasintadd1 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 -4) to i64)
+// CHECK: @ptrasintadd2 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 4) to i64)
+// CHECK: @ptrasintadd3 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 14) to i64)
+// CHECK: @ptrasintadd4 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 -1) to i64)
+// CHECK: @ptrasintadd5 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 4) to i64)
+// CHECK: @ptrasintadd6 = global i64 ptrtoint (ptr getelementptr (i8, ptr @a, 
i64 14) to i64)
diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c
index 175d221ad410a..930cfab1e62b5 100644
--- a/clang/test/CodeGen/const-init.c
+++ b/clang/test/CodeGen/const-init.c
@@ -1,5 +1,6 @@
 // setting strict FP behaviour in the run line below tests that the compiler
 // does the right thing for global compound literals (compoundliteral test)
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -ffreestanding 
-Wno-pointer-to-int-cast -Wno-int-conversion -ffp-exception-behavior=strict 
-emit-llvm -o - %s -fexperimental-new-constant-interpreter | FileCheck %s
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -ffreestanding 
-Wno-pointer-to-int-cast -Wno-int-conversion -ffp-exception-behavior=strict 
-emit-llvm -o - %s | FileCheck %s
 
 #include <stdint.h>
diff --git a/clang/test/CodeGen/const-label-addr.c 
b/clang/test/CodeGen/const-label-addr.c
index 8030f96cb8aed..086971045d2ca 100644
--- a/clang/test/CodeGen/const-label-addr.c
+++ b/clang/test/CodeGen/const-label-addr.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -fexperimental-new-constant-interpreter 
| FileCheck %s
 // REQUIRES: asserts
 
 // CHECK: @a.a = internal global ptr blockaddress(@a, %A)
diff --git a/clang/test/CodeGen/statements.c b/clang/test/CodeGen/statements.c
index 07ae075d6d807..bdfb5fc718755 100644
--- a/clang/test/CodeGen/statements.c
+++ b/clang/test/CodeGen/statements.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -Wno-error=return-type -Wno-error=int-conversion %s 
-emit-llvm-only
+// RUN: %clang_cc1 -Wno-error=return-type -Wno-error=int-conversion %s 
-emit-llvm-only -fexperimental-new-constant-interpreter
 // REQUIRES: LP64
 
 // Mismatched type between return and function result.
diff --git a/clang/test/CodeGen/staticinit.c b/clang/test/CodeGen/staticinit.c
index ec9b5b34d3ade..7ada59e220776 100644
--- a/clang/test/CodeGen/staticinit.c
+++ b/clang/test/CodeGen/staticinit.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
 
 struct AStruct { 
   int i;
diff --git a/clang/test/CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp 
b/clang/test/CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp
index cb31a04c69fea..3be58ea1b7cae 100644
--- a/clang/test/CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp
+++ b/clang/test/CodeGenCXX/2008-05-07-CrazyOffsetOf.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - | FileCheck 
%s
+// RUN: %clang_cc1 -triple=x86_64-unknown-linux -emit-llvm %s -o - 
-fexperimental-new-constant-interpreter | FileCheck %s
 
 struct bork {
   struct bork *next_local;
diff --git a/clang/test/CodeGenCXX/const-init-cxx11.cpp 
b/clang/test/CodeGenCXX/const-init-cxx11.cpp
index 0795fb534af4b..125bf8c383a81 100644
--- a/clang/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/clang/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,6 +1,9 @@
 // RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm 
-o - %s -std=c++11 | FileCheck %s
 // RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm 
-o - %s -std=c++20 | FileCheck -check-prefix=CHECK20 %s
 
+// RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm 
-o - %s -std=c++11 -fexperimental-new-constant-interpreter | FileCheck %s
+// RUN: %clang_cc1 -w -fmerge-all-constants -triple x86_64-elf-gnu -emit-llvm 
-o - %s -std=c++20 -fexperimental-new-constant-interpreter | FileCheck 
-check-prefix=CHECK20 %s
+
 // FIXME: The padding in all these objects should be zero-initialized.
 namespace StructUnion {
   struct A {
diff --git a/clang/test/CodeGenCXX/const-init.cpp 
b/clang/test/CodeGenCXX/const-init.cpp
index f5b715949f23a..18ed3df22f425 100644
--- a/clang/test/CodeGenCXX/const-init.cpp
+++ b/clang/test/CodeGenCXX/const-init.cpp
@@ -2,6 +2,12 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++98 -o - %s | 
FileCheck %s
 // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++11 -o - %s | 
FileCheck %s
 
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++98 -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -std=c++11 -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+
+
+
 // CHECK: @a = global i32 10
 int a = 10;
 // CHECK: @ar = constant ptr @a
diff --git a/clang/test/Sema/array-init.c b/clang/test/Sema/array-init.c
index 54a7877e8f2e5..9482fa7722640 100644
--- a/clang/test/Sema/array-init.c
+++ b/clang/test/Sema/array-init.c
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -std=gnu99 -fsyntax-only -pedantic 
-verify=expected,pedantic %s
 // RUN: %clang_cc1 -std=gnu99 -fsyntax-only -Wgnu -Wc11-extensions -verify %s
+// RUN: %clang_cc1 -std=gnu99 -fsyntax-only -pedantic 
-verify=expected,pedantic %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=gnu99 -fsyntax-only -Wgnu -Wc11-extensions -verify %s 
-fexperimental-new-constant-interpreter
 // REQUIRES: LP64
 
 extern int foof(void) = 1; // expected-error{{illegal initializer (only 
variables can be initialized)}}
diff --git a/clang/test/Sema/compound-literal.c 
b/clang/test/Sema/compound-literal.c
index 3ed53d670d38f..1026e5ece11b4 100644
--- a/clang/test/Sema/compound-literal.c
+++ b/clang/test/Sema/compound-literal.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic %s
+// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -pedantic %s 
-fexperimental-new-constant-interpreter
 // REQUIRES: LP64
 
 struct foo { int a, b; };
diff --git a/clang/test/Sema/const-ptr-int-ptr-cast.c 
b/clang/test/Sema/const-ptr-int-ptr-cast.c
index 9e3db6eb6dae4..b1c06a723afc1 100644
--- a/clang/test/Sema/const-ptr-int-ptr-cast.c
+++ b/clang/test/Sema/const-ptr-int-ptr-cast.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s
+// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s 
-fexperimental-new-constant-interpreter
 // expected-no-diagnostics
 
 typedef __UINTPTR_TYPE__ uintptr_t;
diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c
index 249320f8445f5..cf3788bc21c93 100644
--- a/clang/test/Sema/init.c
+++ b/clang/test/Sema/init.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 %s -Wno-pointer-to-int-cast -verify -fsyntax-only 
-ffreestanding
+// RUN: %clang_cc1 %s -Wno-pointer-to-int-cast -verify -fsyntax-only 
-ffreestanding -fexperimental-new-constant-interpreter
 
 #include <stddef.h>
 #include <stdint.h>
diff --git a/clang/test/SemaCXX/constexpr-string.cpp 
b/clang/test/SemaCXX/constexpr-string.cpp
index 93e234685d284..b49979bbc8ca0 100644
--- a/clang/test/SemaCXX/constexpr-string.cpp
+++ b/clang/test/SemaCXX/constexpr-string.cpp
@@ -8,6 +8,7 @@
 // RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only 
-verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T
 
 // RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only 
-verify -pedantic -Wno-vla-extension -fno-signed-char 
-fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 %s -triple armebv7-unknown-linux -std=c++2a -fsyntax-only 
-verify -pedantic -Wno-vla-extension -fno-wchar -DNO_PREDEFINED_WCHAR_T 
-fexperimental-new-constant-interpreter
 
 # 9 "/usr/include/string.h" 1 3 4  // expected-warning {{this style of line 
directive is a GNU extension}}
 extern "C" {

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to