Initial check in
Bug: 137197907
diff --git a/src/llvm-project/llvm/unittests/ADT/APFloatTest.cpp b/src/llvm-project/llvm/unittests/ADT/APFloatTest.cpp
new file mode 100644
index 0000000..64053a8
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/APFloatTest.cpp
@@ -0,0 +1,4017 @@
+//===- llvm/unittest/ADT/APFloat.cpp - APFloat unit tests ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APFloat.h"
+#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <cmath>
+#include <ostream>
+#include <string>
+#include <tuple>
+
+using namespace llvm;
+
+static double convertToDoubleFromString(const char *Str) {
+ llvm::APFloat F(0.0);
+ F.convertFromString(Str, llvm::APFloat::rmNearestTiesToEven);
+ return F.convertToDouble();
+}
+
+static std::string convertToString(double d, unsigned Prec, unsigned Pad,
+ bool Tr = true) {
+ llvm::SmallVector<char, 100> Buffer;
+ llvm::APFloat F(d);
+ F.toString(Buffer, Prec, Pad, Tr);
+ return std::string(Buffer.data(), Buffer.size());
+}
+
+namespace {
+
+TEST(APFloatTest, isSignaling) {
+ // We test qNaN, -qNaN, +sNaN, -sNaN with and without payloads. *NOTE* The
+ // positive/negative distinction is included only since the getQNaN/getSNaN
+ // API provides the option.
+ APInt payload = APInt::getOneBitSet(4, 2);
+ EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), false).isSignaling());
+ EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true).isSignaling());
+ EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), false, &payload).isSignaling());
+ EXPECT_FALSE(APFloat::getQNaN(APFloat::IEEEsingle(), true, &payload).isSignaling());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isSignaling());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isSignaling());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false, &payload).isSignaling());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true, &payload).isSignaling());
+}
+
+TEST(APFloatTest, next) {
+
+ APFloat test(APFloat::IEEEquad(), APFloat::uninitialized);
+ APFloat expected(APFloat::IEEEquad(), APFloat::uninitialized);
+
+ // 1. Test Special Cases Values.
+ //
+ // Test all special values for nextUp and nextDown perscribed by IEEE-754R
+ // 2008. These are:
+ // 1. +inf
+ // 2. -inf
+ // 3. getLargest()
+ // 4. -getLargest()
+ // 5. getSmallest()
+ // 6. -getSmallest()
+ // 7. qNaN
+ // 8. sNaN
+ // 9. +0
+ // 10. -0
+
+ // nextUp(+inf) = +inf.
+ test = APFloat::getInf(APFloat::IEEEquad(), false);
+ expected = APFloat::getInf(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isInfinity());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+inf) = -nextUp(-inf) = -(-getLargest()) = getLargest()
+ test = APFloat::getInf(APFloat::IEEEquad(), false);
+ expected = APFloat::getLargest(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-inf) = -getLargest()
+ test = APFloat::getInf(APFloat::IEEEquad(), true);
+ expected = APFloat::getLargest(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-inf) = -nextUp(+inf) = -(+inf) = -inf.
+ test = APFloat::getInf(APFloat::IEEEquad(), true);
+ expected = APFloat::getInf(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isInfinity() && test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(getLargest()) = +inf
+ test = APFloat::getLargest(APFloat::IEEEquad(), false);
+ expected = APFloat::getInf(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isInfinity() && !test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(getLargest()) = -nextUp(-getLargest())
+ // = -(-getLargest() + inc)
+ // = getLargest() - inc.
+ test = APFloat::getLargest(APFloat::IEEEquad(), false);
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.fffffffffffffffffffffffffffep+16383");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(!test.isInfinity() && !test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-getLargest()) = -getLargest() + inc.
+ test = APFloat::getLargest(APFloat::IEEEquad(), true);
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.fffffffffffffffffffffffffffep+16383");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-getLargest()) = -nextUp(getLargest()) = -(inf) = -inf.
+ test = APFloat::getLargest(APFloat::IEEEquad(), true);
+ expected = APFloat::getInf(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isInfinity() && test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(getSmallest()) = getSmallest() + inc.
+ test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x0.0000000000000000000000000002p-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(getSmallest()) = -nextUp(-getSmallest()) = -(-0) = +0.
+ test = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
+ expected = APFloat::getZero(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isPosZero());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-getSmallest()) = -0.
+ test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
+ expected = APFloat::getZero(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isNegZero());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-getSmallest()) = -nextUp(getSmallest()) = -getSmallest() - inc.
+ test = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x0.0000000000000000000000000002p-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(qNaN) = qNaN
+ test = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ expected = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(qNaN) = qNaN
+ test = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ expected = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(sNaN) = qNaN
+ test = APFloat::getSNaN(APFloat::IEEEquad(), false);
+ expected = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opInvalidOp);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(sNaN) = qNaN
+ test = APFloat::getSNaN(APFloat::IEEEquad(), false);
+ expected = APFloat::getQNaN(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(true), APFloat::opInvalidOp);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(+0) = +getSmallest()
+ test = APFloat::getZero(APFloat::IEEEquad(), false);
+ expected = APFloat::getSmallest(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+0) = -nextUp(-0) = -getSmallest()
+ test = APFloat::getZero(APFloat::IEEEquad(), false);
+ expected = APFloat::getSmallest(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-0) = +getSmallest()
+ test = APFloat::getZero(APFloat::IEEEquad(), true);
+ expected = APFloat::getSmallest(APFloat::IEEEquad(), false);
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-0) = -nextUp(0) = -getSmallest()
+ test = APFloat::getZero(APFloat::IEEEquad(), true);
+ expected = APFloat::getSmallest(APFloat::IEEEquad(), true);
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // 2. Binade Boundary Tests.
+
+ // 2a. Test denormal <-> normal binade boundaries.
+ // * nextUp(+Largest Denormal) -> +Smallest Normal.
+ // * nextDown(-Largest Denormal) -> -Smallest Normal.
+ // * nextUp(-Smallest Normal) -> -Largest Denormal.
+ // * nextDown(+Smallest Normal) -> +Largest Denormal.
+
+ // nextUp(+Largest Denormal) -> +Smallest Normal.
+ test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.0000000000000000000000000000p-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-Largest Denormal) -> -Smallest Normal.
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.0000000000000000000000000000p-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-Smallest Normal) -> -LargestDenormal.
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x1.0000000000000000000000000000p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffffffffp-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+Smallest Normal) -> +Largest Denormal.
+ test = APFloat(APFloat::IEEEquad(),
+ "+0x1.0000000000000000000000000000p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "+0x0.ffffffffffffffffffffffffffffp-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // 2b. Test normal <-> normal binade boundaries.
+ // * nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1.
+ // * nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1.
+ // * nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary.
+ // * nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary.
+
+ // nextUp(-Normal Binade Boundary) -> -Normal Binade Boundary + 1.
+ test = APFloat(APFloat::IEEEquad(), "-0x1p+1");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffffffffp+0");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+Normal Binade Boundary) -> +Normal Binade Boundary - 1.
+ test = APFloat(APFloat::IEEEquad(), "0x1p+1");
+ expected = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(+Normal Binade Boundary - 1) -> +Normal Binade Boundary.
+ test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp+0");
+ expected = APFloat(APFloat::IEEEquad(), "0x1p+1");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-Normal Binade Boundary + 1) -> -Normal Binade Boundary.
+ test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp+0");
+ expected = APFloat(APFloat::IEEEquad(), "-0x1p+1");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // 2c. Test using next at binade boundaries with a direction away from the
+ // binade boundary. Away from denormal <-> normal boundaries.
+ //
+ // This is to make sure that even though we are at a binade boundary, since
+ // we are rounding away, we do not trigger the binade boundary code. Thus we
+ // test:
+ // * nextUp(-Largest Denormal) -> -Largest Denormal + inc.
+ // * nextDown(+Largest Denormal) -> +Largest Denormal - inc.
+ // * nextUp(+Smallest Normal) -> +Smallest Normal + inc.
+ // * nextDown(-Smallest Normal) -> -Smallest Normal - inc.
+
+ // nextUp(-Largest Denormal) -> -Largest Denormal + inc.
+ test = APFloat(APFloat::IEEEquad(), "-0x0.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x0.fffffffffffffffffffffffffffep-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+Largest Denormal) -> +Largest Denormal - inc.
+ test = APFloat(APFloat::IEEEquad(), "0x0.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x0.fffffffffffffffffffffffffffep-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(+Smallest Normal) -> +Smallest Normal + inc.
+ test = APFloat(APFloat::IEEEquad(), "0x1.0000000000000000000000000000p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.0000000000000000000000000001p-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-Smallest Normal) -> -Smallest Normal - inc.
+ test = APFloat(APFloat::IEEEquad(), "-0x1.0000000000000000000000000000p-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.0000000000000000000000000001p-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // 2d. Test values which cause our exponent to go to min exponent. This
+ // is to ensure that guards in the code to check for min exponent
+ // trigger properly.
+ // * nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382
+ // * nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) ->
+ // -0x1p-16381
+ // * nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16382
+ // * nextDown(0x1p-16382) -> 0x1.ffffffffffffffffffffffffffffp-16382
+
+ // nextUp(-0x1p-16381) -> -0x1.ffffffffffffffffffffffffffffp-16382
+ test = APFloat(APFloat::IEEEquad(), "-0x1p-16381");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffffffffp-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-0x1.ffffffffffffffffffffffffffffp-16382) ->
+ // -0x1p-16381
+ test = APFloat(APFloat::IEEEquad(), "-0x1.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(), "-0x1p-16381");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(0x1.ffffffffffffffffffffffffffffp-16382) -> 0x1p-16381
+ test = APFloat(APFloat::IEEEquad(), "0x1.ffffffffffffffffffffffffffffp-16382");
+ expected = APFloat(APFloat::IEEEquad(), "0x1p-16381");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(0x1p-16381) -> 0x1.ffffffffffffffffffffffffffffp-16382
+ test = APFloat(APFloat::IEEEquad(), "0x1p-16381");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.ffffffffffffffffffffffffffffp-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // 3. Now we test both denormal/normal computation which will not cause us
+ // to go across binade boundaries. Specifically we test:
+ // * nextUp(+Denormal) -> +Denormal.
+ // * nextDown(+Denormal) -> +Denormal.
+ // * nextUp(-Denormal) -> -Denormal.
+ // * nextDown(-Denormal) -> -Denormal.
+ // * nextUp(+Normal) -> +Normal.
+ // * nextDown(+Normal) -> +Normal.
+ // * nextUp(-Normal) -> -Normal.
+ // * nextDown(-Normal) -> -Normal.
+
+ // nextUp(+Denormal) -> +Denormal.
+ test = APFloat(APFloat::IEEEquad(),
+ "0x0.ffffffffffffffffffffffff000cp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x0.ffffffffffffffffffffffff000dp-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+Denormal) -> +Denormal.
+ test = APFloat(APFloat::IEEEquad(),
+ "0x0.ffffffffffffffffffffffff000cp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x0.ffffffffffffffffffffffff000bp-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-Denormal) -> -Denormal.
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffff000cp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffff000bp-16382");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-Denormal) -> -Denormal
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffff000cp-16382");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x0.ffffffffffffffffffffffff000dp-16382");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(+Normal) -> +Normal.
+ test = APFloat(APFloat::IEEEquad(),
+ "0x1.ffffffffffffffffffffffff000cp-16000");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.ffffffffffffffffffffffff000dp-16000");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(+Normal) -> +Normal.
+ test = APFloat(APFloat::IEEEquad(),
+ "0x1.ffffffffffffffffffffffff000cp-16000");
+ expected = APFloat(APFloat::IEEEquad(),
+ "0x1.ffffffffffffffffffffffff000bp-16000");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(!test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextUp(-Normal) -> -Normal.
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffff000cp-16000");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffff000bp-16000");
+ EXPECT_EQ(test.next(false), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ // nextDown(-Normal) -> -Normal.
+ test = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffff000cp-16000");
+ expected = APFloat(APFloat::IEEEquad(),
+ "-0x1.ffffffffffffffffffffffff000dp-16000");
+ EXPECT_EQ(test.next(true), APFloat::opOK);
+ EXPECT_TRUE(!test.isDenormal());
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+}
+
+TEST(APFloatTest, FMA) {
+ APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
+
+ {
+ APFloat f1(14.5f);
+ APFloat f2(-14.5f);
+ APFloat f3(225.0f);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(14.75f, f1.convertToFloat());
+ }
+
+ {
+ APFloat Val2(2.0f);
+ APFloat f1((float)1.17549435e-38F);
+ APFloat f2((float)1.17549435e-38F);
+ f1.divide(Val2, rdmd);
+ f2.divide(Val2, rdmd);
+ APFloat f3(12.0f);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(12.0f, f1.convertToFloat());
+ }
+
+ // Test for correct zero sign when answer is exactly zero.
+ // fma(1.0, -1.0, 1.0) -> +ve 0.
+ {
+ APFloat f1(1.0);
+ APFloat f2(-1.0);
+ APFloat f3(1.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(!f1.isNegative() && f1.isZero());
+ }
+
+ // Test for correct zero sign when answer is exactly zero and rounding towards
+ // negative.
+ // fma(1.0, -1.0, 1.0) -> +ve 0.
+ {
+ APFloat f1(1.0);
+ APFloat f2(-1.0);
+ APFloat f3(1.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmTowardNegative);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test for correct (in this case -ve) sign when adding like signed zeros.
+ // Test fma(0.0, -0.0, -0.0) -> -ve 0.
+ {
+ APFloat f1(0.0);
+ APFloat f2(-0.0);
+ APFloat f3(-0.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test -ve sign preservation when small negative results underflow.
+ {
+ APFloat f1(APFloat::IEEEdouble(), "-0x1p-1074");
+ APFloat f2(APFloat::IEEEdouble(), "+0x1p-1074");
+ APFloat f3(0.0);
+ f1.fusedMultiplyAdd(f2, f3, APFloat::rmNearestTiesToEven);
+ EXPECT_TRUE(f1.isNegative() && f1.isZero());
+ }
+
+ // Test x87 extended precision case from http://llvm.org/PR20728.
+ {
+ APFloat M1(APFloat::x87DoubleExtended(), 1.0);
+ APFloat M2(APFloat::x87DoubleExtended(), 1.0);
+ APFloat A(APFloat::x87DoubleExtended(), 3.0);
+
+ bool losesInfo = false;
+ M1.fusedMultiplyAdd(M1, A, APFloat::rmNearestTiesToEven);
+ M1.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_FALSE(losesInfo);
+ EXPECT_EQ(4.0f, M1.convertToFloat());
+ }
+}
+
+TEST(APFloatTest, MinNum) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(1.0, minnum(f1, f2).convertToDouble());
+ EXPECT_EQ(1.0, minnum(f2, f1).convertToDouble());
+ EXPECT_EQ(1.0, minnum(f1, nan).convertToDouble());
+ EXPECT_EQ(1.0, minnum(nan, f1).convertToDouble());
+}
+
+TEST(APFloatTest, MaxNum) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(2.0, maxnum(f1, f2).convertToDouble());
+ EXPECT_EQ(2.0, maxnum(f2, f1).convertToDouble());
+ EXPECT_EQ(1.0, maxnum(f1, nan).convertToDouble());
+ EXPECT_EQ(1.0, maxnum(nan, f1).convertToDouble());
+}
+
+TEST(APFloatTest, Minimum) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat zp(0.0);
+ APFloat zn(-0.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(1.0, minimum(f1, f2).convertToDouble());
+ EXPECT_EQ(1.0, minimum(f2, f1).convertToDouble());
+ EXPECT_EQ(-0.0, minimum(zp, zn).convertToDouble());
+ EXPECT_EQ(-0.0, minimum(zn, zp).convertToDouble());
+ EXPECT_TRUE(std::isnan(minimum(f1, nan).convertToDouble()));
+ EXPECT_TRUE(std::isnan(minimum(nan, f1).convertToDouble()));
+}
+
+TEST(APFloatTest, Maximum) {
+ APFloat f1(1.0);
+ APFloat f2(2.0);
+ APFloat zp(0.0);
+ APFloat zn(-0.0);
+ APFloat nan = APFloat::getNaN(APFloat::IEEEdouble());
+
+ EXPECT_EQ(2.0, maximum(f1, f2).convertToDouble());
+ EXPECT_EQ(2.0, maximum(f2, f1).convertToDouble());
+ EXPECT_EQ(0.0, maximum(zp, zn).convertToDouble());
+ EXPECT_EQ(0.0, maximum(zn, zp).convertToDouble());
+ EXPECT_TRUE(std::isnan(maximum(f1, nan).convertToDouble()));
+ EXPECT_TRUE(std::isnan(maximum(nan, f1).convertToDouble()));
+}
+
+TEST(APFloatTest, Denormal) {
+ APFloat::roundingMode rdmd = APFloat::rmNearestTiesToEven;
+
+ // Test single precision
+ {
+ const char *MinNormalStr = "1.17549435082228750797e-38";
+ EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), MinNormalStr).isDenormal());
+ EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), 0.0).isDenormal());
+
+ APFloat Val2(APFloat::IEEEsingle(), 2.0e0);
+ APFloat T(APFloat::IEEEsingle(), MinNormalStr);
+ T.divide(Val2, rdmd);
+ EXPECT_TRUE(T.isDenormal());
+ }
+
+ // Test double precision
+ {
+ const char *MinNormalStr = "2.22507385850720138309e-308";
+ EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), MinNormalStr).isDenormal());
+ EXPECT_FALSE(APFloat(APFloat::IEEEdouble(), 0.0).isDenormal());
+
+ APFloat Val2(APFloat::IEEEdouble(), 2.0e0);
+ APFloat T(APFloat::IEEEdouble(), MinNormalStr);
+ T.divide(Val2, rdmd);
+ EXPECT_TRUE(T.isDenormal());
+ }
+
+ // Test Intel double-ext
+ {
+ const char *MinNormalStr = "3.36210314311209350626e-4932";
+ EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), MinNormalStr).isDenormal());
+ EXPECT_FALSE(APFloat(APFloat::x87DoubleExtended(), 0.0).isDenormal());
+
+ APFloat Val2(APFloat::x87DoubleExtended(), 2.0e0);
+ APFloat T(APFloat::x87DoubleExtended(), MinNormalStr);
+ T.divide(Val2, rdmd);
+ EXPECT_TRUE(T.isDenormal());
+ }
+
+ // Test quadruple precision
+ {
+ const char *MinNormalStr = "3.36210314311209350626267781732175260e-4932";
+ EXPECT_FALSE(APFloat(APFloat::IEEEquad(), MinNormalStr).isDenormal());
+ EXPECT_FALSE(APFloat(APFloat::IEEEquad(), 0.0).isDenormal());
+
+ APFloat Val2(APFloat::IEEEquad(), 2.0e0);
+ APFloat T(APFloat::IEEEquad(), MinNormalStr);
+ T.divide(Val2, rdmd);
+ EXPECT_TRUE(T.isDenormal());
+ }
+}
+
+TEST(APFloatTest, Zero) {
+ EXPECT_EQ(0.0f, APFloat(0.0f).convertToFloat());
+ EXPECT_EQ(-0.0f, APFloat(-0.0f).convertToFloat());
+ EXPECT_TRUE(APFloat(-0.0f).isNegative());
+
+ EXPECT_EQ(0.0, APFloat(0.0).convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(-0.0).convertToDouble());
+ EXPECT_TRUE(APFloat(-0.0).isNegative());
+}
+
+TEST(APFloatTest, DecimalStringsWithoutNullTerminators) {
+ // Make sure that we can parse strings without null terminators.
+ // rdar://14323230.
+ APFloat Val(APFloat::IEEEdouble());
+ Val.convertFromString(StringRef("0.00", 3),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.0);
+ Val.convertFromString(StringRef("0.01", 3),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.0);
+ Val.convertFromString(StringRef("0.09", 3),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.0);
+ Val.convertFromString(StringRef("0.095", 4),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.09);
+ Val.convertFromString(StringRef("0.00e+3", 7),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.00);
+ Val.convertFromString(StringRef("0e+3", 4),
+ llvm::APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(Val.convertToDouble(), 0.00);
+
+}
+
+TEST(APFloatTest, fromZeroDecimalString) {
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "00000.").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+00000.").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-00000.").convertToDouble());
+
+ EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), ".00000").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.00000").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.00000").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0000.00000").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0000.00000").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0000.00000").convertToDouble());
+}
+
+TEST(APFloatTest, fromZeroDecimalSingleExponentString) {
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.e-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.e-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.e-1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), ".0e-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+.0e-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-.0e-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0.0e-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0.0e-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0.0e-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+000.0000e+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-000.0000e+1").convertToDouble());
+}
+
+TEST(APFloatTest, fromZeroDecimalLargeExponentString) {
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e1234").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e1234").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e1234").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e+1234").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e+1234").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e+1234").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0e-1234").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0e-1234").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0e-1234").convertToDouble());
+
+ EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e1234").convertToDouble());
+ EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), "000.0000e-1234").convertToDouble());
+
+ EXPECT_EQ(0.0, APFloat(APFloat::IEEEdouble(), StringRef("0e1234" "\0" "2", 6)).convertToDouble());
+}
+
+TEST(APFloatTest, fromZeroHexadecimalString) {
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0p-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.p-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.p-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.0p-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x.0p-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x.0p-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p+1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p+1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p+1").convertToDouble());
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.0p-1").convertToDouble());
+ EXPECT_EQ(+0.0, APFloat(APFloat::IEEEdouble(), "+0x0.0p-1").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0.0p-1").convertToDouble());
+
+
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0p1234").convertToDouble());
+ EXPECT_EQ(-0.0, APFloat(APFloat::IEEEdouble(), "-0x0p1234").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x00000.p1234").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0000.00000p1234").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x.00000p1234").convertToDouble());
+ EXPECT_EQ( 0.0, APFloat(APFloat::IEEEdouble(), "0x0.p1234").convertToDouble());
+}
+
+TEST(APFloatTest, fromDecimalString) {
+ EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1").convertToDouble());
+ EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble());
+ EXPECT_EQ(0.5, APFloat(APFloat::IEEEdouble(), ".5").convertToDouble());
+ EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "1.0").convertToDouble());
+ EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-2").convertToDouble());
+ EXPECT_EQ(-4.0, APFloat(APFloat::IEEEdouble(), "-4.").convertToDouble());
+ EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-.5").convertToDouble());
+ EXPECT_EQ(-1.5, APFloat(APFloat::IEEEdouble(), "-1.5").convertToDouble());
+ EXPECT_EQ(1.25e12, APFloat(APFloat::IEEEdouble(), "1.25e12").convertToDouble());
+ EXPECT_EQ(1.25e+12, APFloat(APFloat::IEEEdouble(), "1.25e+12").convertToDouble());
+ EXPECT_EQ(1.25e-12, APFloat(APFloat::IEEEdouble(), "1.25e-12").convertToDouble());
+ EXPECT_EQ(1024.0, APFloat(APFloat::IEEEdouble(), "1024.").convertToDouble());
+ EXPECT_EQ(1024.05, APFloat(APFloat::IEEEdouble(), "1024.05000").convertToDouble());
+ EXPECT_EQ(0.05, APFloat(APFloat::IEEEdouble(), ".05000").convertToDouble());
+ EXPECT_EQ(2.0, APFloat(APFloat::IEEEdouble(), "2.").convertToDouble());
+ EXPECT_EQ(2.0e2, APFloat(APFloat::IEEEdouble(), "2.e2").convertToDouble());
+ EXPECT_EQ(2.0e+2, APFloat(APFloat::IEEEdouble(), "2.e+2").convertToDouble());
+ EXPECT_EQ(2.0e-2, APFloat(APFloat::IEEEdouble(), "2.e-2").convertToDouble());
+ EXPECT_EQ(2.05e2, APFloat(APFloat::IEEEdouble(), "002.05000e2").convertToDouble());
+ EXPECT_EQ(2.05e+2, APFloat(APFloat::IEEEdouble(), "002.05000e+2").convertToDouble());
+ EXPECT_EQ(2.05e-2, APFloat(APFloat::IEEEdouble(), "002.05000e-2").convertToDouble());
+ EXPECT_EQ(2.05e12, APFloat(APFloat::IEEEdouble(), "002.05000e12").convertToDouble());
+ EXPECT_EQ(2.05e+12, APFloat(APFloat::IEEEdouble(), "002.05000e+12").convertToDouble());
+ EXPECT_EQ(2.05e-12, APFloat(APFloat::IEEEdouble(), "002.05000e-12").convertToDouble());
+
+ // These are "carefully selected" to overflow the fast log-base
+ // calculations in APFloat.cpp
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "99e99999").isInfinity());
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-99e99999").isInfinity());
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "1e-99999").isPosZero());
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-1e-99999").isNegZero());
+
+ EXPECT_EQ(2.71828, convertToDoubleFromString("2.71828"));
+}
+
+TEST(APFloatTest, fromToStringSpecials) {
+ auto expects = [] (const char *first, const char *second) {
+ std::string roundtrip = convertToString(convertToDoubleFromString(second), 0, 3);
+ EXPECT_STREQ(first, roundtrip.c_str());
+ };
+ expects("+Inf", "+Inf");
+ expects("+Inf", "INFINITY");
+ expects("+Inf", "inf");
+ expects("-Inf", "-Inf");
+ expects("-Inf", "-INFINITY");
+ expects("-Inf", "-inf");
+ expects("NaN", "NaN");
+ expects("NaN", "nan");
+ expects("NaN", "-NaN");
+ expects("NaN", "-nan");
+}
+
+TEST(APFloatTest, fromHexadecimalString) {
+ EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble());
+ EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p0").convertToDouble());
+ EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p0").convertToDouble());
+
+ EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p+0").convertToDouble());
+ EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p+0").convertToDouble());
+ EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p+0").convertToDouble());
+
+ EXPECT_EQ( 1.0, APFloat(APFloat::IEEEdouble(), "0x1p-0").convertToDouble());
+ EXPECT_EQ(+1.0, APFloat(APFloat::IEEEdouble(), "+0x1p-0").convertToDouble());
+ EXPECT_EQ(-1.0, APFloat(APFloat::IEEEdouble(), "-0x1p-0").convertToDouble());
+
+
+ EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p1").convertToDouble());
+ EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p1").convertToDouble());
+ EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p1").convertToDouble());
+
+ EXPECT_EQ( 2.0, APFloat(APFloat::IEEEdouble(), "0x1p+1").convertToDouble());
+ EXPECT_EQ(+2.0, APFloat(APFloat::IEEEdouble(), "+0x1p+1").convertToDouble());
+ EXPECT_EQ(-2.0, APFloat(APFloat::IEEEdouble(), "-0x1p+1").convertToDouble());
+
+ EXPECT_EQ( 0.5, APFloat(APFloat::IEEEdouble(), "0x1p-1").convertToDouble());
+ EXPECT_EQ(+0.5, APFloat(APFloat::IEEEdouble(), "+0x1p-1").convertToDouble());
+ EXPECT_EQ(-0.5, APFloat(APFloat::IEEEdouble(), "-0x1p-1").convertToDouble());
+
+
+ EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p1").convertToDouble());
+ EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p1").convertToDouble());
+ EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p1").convertToDouble());
+
+ EXPECT_EQ( 3.0, APFloat(APFloat::IEEEdouble(), "0x1.8p+1").convertToDouble());
+ EXPECT_EQ(+3.0, APFloat(APFloat::IEEEdouble(), "+0x1.8p+1").convertToDouble());
+ EXPECT_EQ(-3.0, APFloat(APFloat::IEEEdouble(), "-0x1.8p+1").convertToDouble());
+
+ EXPECT_EQ( 0.75, APFloat(APFloat::IEEEdouble(), "0x1.8p-1").convertToDouble());
+ EXPECT_EQ(+0.75, APFloat(APFloat::IEEEdouble(), "+0x1.8p-1").convertToDouble());
+ EXPECT_EQ(-0.75, APFloat(APFloat::IEEEdouble(), "-0x1.8p-1").convertToDouble());
+
+
+ EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p1").convertToDouble());
+ EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p1").convertToDouble());
+ EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p1").convertToDouble());
+
+ EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p+1").convertToDouble());
+ EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p+1").convertToDouble());
+ EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p+1").convertToDouble());
+
+ EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000.000p-1").convertToDouble());
+ EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000.000p-1").convertToDouble());
+ EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000.000p-1").convertToDouble());
+
+
+ EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p1").convertToDouble());
+ EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p1").convertToDouble());
+ EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p1").convertToDouble());
+
+ EXPECT_EQ( 8192.0, APFloat(APFloat::IEEEdouble(), "0x1000p+1").convertToDouble());
+ EXPECT_EQ(+8192.0, APFloat(APFloat::IEEEdouble(), "+0x1000p+1").convertToDouble());
+ EXPECT_EQ(-8192.0, APFloat(APFloat::IEEEdouble(), "-0x1000p+1").convertToDouble());
+
+ EXPECT_EQ( 2048.0, APFloat(APFloat::IEEEdouble(), "0x1000p-1").convertToDouble());
+ EXPECT_EQ(+2048.0, APFloat(APFloat::IEEEdouble(), "+0x1000p-1").convertToDouble());
+ EXPECT_EQ(-2048.0, APFloat(APFloat::IEEEdouble(), "-0x1000p-1").convertToDouble());
+
+
+ EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p10").convertToDouble());
+ EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p10").convertToDouble());
+ EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p10").convertToDouble());
+
+ EXPECT_EQ( 16384.0, APFloat(APFloat::IEEEdouble(), "0x10p+10").convertToDouble());
+ EXPECT_EQ(+16384.0, APFloat(APFloat::IEEEdouble(), "+0x10p+10").convertToDouble());
+ EXPECT_EQ(-16384.0, APFloat(APFloat::IEEEdouble(), "-0x10p+10").convertToDouble());
+
+ EXPECT_EQ( 0.015625, APFloat(APFloat::IEEEdouble(), "0x10p-10").convertToDouble());
+ EXPECT_EQ(+0.015625, APFloat(APFloat::IEEEdouble(), "+0x10p-10").convertToDouble());
+ EXPECT_EQ(-0.015625, APFloat(APFloat::IEEEdouble(), "-0x10p-10").convertToDouble());
+
+ EXPECT_EQ(1.0625, APFloat(APFloat::IEEEdouble(), "0x1.1p0").convertToDouble());
+ EXPECT_EQ(1.0, APFloat(APFloat::IEEEdouble(), "0x1p0").convertToDouble());
+
+ EXPECT_EQ(convertToDoubleFromString("0x1p-150"),
+ convertToDoubleFromString("+0x800000000000000001.p-221"));
+ EXPECT_EQ(2251799813685248.5,
+ convertToDoubleFromString("0x80000000000004000000.010p-28"));
+}
+
+TEST(APFloatTest, toString) {
+ ASSERT_EQ("10", convertToString(10.0, 6, 3));
+ ASSERT_EQ("1.0E+1", convertToString(10.0, 6, 0));
+ ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2));
+ ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 4, 2));
+ ASSERT_EQ("1.01E+4", convertToString(1.01E+4, 5, 1));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2));
+ ASSERT_EQ("1.01E-2", convertToString(1.01E-2, 5, 1));
+ ASSERT_EQ("0.78539816339744828", convertToString(0.78539816339744830961, 0, 3));
+ ASSERT_EQ("4.9406564584124654E-324", convertToString(4.9406564584124654e-324, 0, 3));
+ ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1));
+ ASSERT_EQ("8.7318340000000001E+2", convertToString(873.1834, 0, 0));
+ ASSERT_EQ("1.7976931348623157E+308", convertToString(1.7976931348623157E+308, 0, 0));
+ ASSERT_EQ("10", convertToString(10.0, 6, 3, false));
+ ASSERT_EQ("1.000000e+01", convertToString(10.0, 6, 0, false));
+ ASSERT_EQ("10100", convertToString(1.01E+4, 5, 2, false));
+ ASSERT_EQ("1.0100e+04", convertToString(1.01E+4, 4, 2, false));
+ ASSERT_EQ("1.01000e+04", convertToString(1.01E+4, 5, 1, false));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 5, 2, false));
+ ASSERT_EQ("0.0101", convertToString(1.01E-2, 4, 2, false));
+ ASSERT_EQ("1.01000e-02", convertToString(1.01E-2, 5, 1, false));
+ ASSERT_EQ("0.78539816339744828",
+ convertToString(0.78539816339744830961, 0, 3, false));
+ ASSERT_EQ("4.94065645841246540e-324",
+ convertToString(4.9406564584124654e-324, 0, 3, false));
+ ASSERT_EQ("873.18340000000001", convertToString(873.1834, 0, 1, false));
+ ASSERT_EQ("8.73183400000000010e+02", convertToString(873.1834, 0, 0, false));
+ ASSERT_EQ("1.79769313486231570e+308",
+ convertToString(1.7976931348623157E+308, 0, 0, false));
+
+ {
+ SmallString<64> Str;
+ APFloat UnnormalZero(APFloat::x87DoubleExtended(), APInt(80, {0, 1}));
+ UnnormalZero.toString(Str);
+ ASSERT_EQ("NaN", Str);
+ }
+}
+
+TEST(APFloatTest, toInteger) {
+ bool isExact = false;
+ APSInt result(5, /*isUnsigned=*/true);
+
+ EXPECT_EQ(APFloat::opOK,
+ APFloat(APFloat::IEEEdouble(), "10")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_TRUE(isExact);
+ EXPECT_EQ(APSInt(APInt(5, 10), true), result);
+
+ EXPECT_EQ(APFloat::opInvalidOp,
+ APFloat(APFloat::IEEEdouble(), "-10")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_FALSE(isExact);
+ EXPECT_EQ(APSInt::getMinValue(5, true), result);
+
+ EXPECT_EQ(APFloat::opInvalidOp,
+ APFloat(APFloat::IEEEdouble(), "32")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_FALSE(isExact);
+ EXPECT_EQ(APSInt::getMaxValue(5, true), result);
+
+ EXPECT_EQ(APFloat::opInexact,
+ APFloat(APFloat::IEEEdouble(), "7.9")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_FALSE(isExact);
+ EXPECT_EQ(APSInt(APInt(5, 7), true), result);
+
+ result.setIsUnsigned(false);
+ EXPECT_EQ(APFloat::opOK,
+ APFloat(APFloat::IEEEdouble(), "-10")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_TRUE(isExact);
+ EXPECT_EQ(APSInt(APInt(5, -10, true), false), result);
+
+ EXPECT_EQ(APFloat::opInvalidOp,
+ APFloat(APFloat::IEEEdouble(), "-17")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_FALSE(isExact);
+ EXPECT_EQ(APSInt::getMinValue(5, false), result);
+
+ EXPECT_EQ(APFloat::opInvalidOp,
+ APFloat(APFloat::IEEEdouble(), "16")
+ .convertToInteger(result, APFloat::rmTowardZero, &isExact));
+ EXPECT_FALSE(isExact);
+ EXPECT_EQ(APSInt::getMaxValue(5, false), result);
+}
+
+static APInt nanbitsFromAPInt(const fltSemantics &Sem, bool SNaN, bool Negative,
+ uint64_t payload) {
+ APInt appayload(64, payload);
+ if (SNaN)
+ return APFloat::getSNaN(Sem, Negative, &appayload).bitcastToAPInt();
+ else
+ return APFloat::getQNaN(Sem, Negative, &appayload).bitcastToAPInt();
+}
+
+TEST(APFloatTest, makeNaN) {
+ const struct {
+ uint64_t expected;
+ const fltSemantics &semantics;
+ bool SNaN;
+ bool Negative;
+ uint64_t payload;
+ } tests[] = {
+ /* expected semantics SNaN Neg payload */
+ { 0x7fc00000ULL, APFloat::IEEEsingle(), false, false, 0x00000000ULL },
+ { 0xffc00000ULL, APFloat::IEEEsingle(), false, true, 0x00000000ULL },
+ { 0x7fc0ae72ULL, APFloat::IEEEsingle(), false, false, 0x0000ae72ULL },
+ { 0x7fffae72ULL, APFloat::IEEEsingle(), false, false, 0xffffae72ULL },
+ { 0x7fdaae72ULL, APFloat::IEEEsingle(), false, false, 0x00daae72ULL },
+ { 0x7fa00000ULL, APFloat::IEEEsingle(), true, false, 0x00000000ULL },
+ { 0xffa00000ULL, APFloat::IEEEsingle(), true, true, 0x00000000ULL },
+ { 0x7f80ae72ULL, APFloat::IEEEsingle(), true, false, 0x0000ae72ULL },
+ { 0x7fbfae72ULL, APFloat::IEEEsingle(), true, false, 0xffffae72ULL },
+ { 0x7f9aae72ULL, APFloat::IEEEsingle(), true, false, 0x001aae72ULL },
+ { 0x7ff8000000000000ULL, APFloat::IEEEdouble(), false, false, 0x0000000000000000ULL },
+ { 0xfff8000000000000ULL, APFloat::IEEEdouble(), false, true, 0x0000000000000000ULL },
+ { 0x7ff800000000ae72ULL, APFloat::IEEEdouble(), false, false, 0x000000000000ae72ULL },
+ { 0x7fffffffffffae72ULL, APFloat::IEEEdouble(), false, false, 0xffffffffffffae72ULL },
+ { 0x7ffdaaaaaaaaae72ULL, APFloat::IEEEdouble(), false, false, 0x000daaaaaaaaae72ULL },
+ { 0x7ff4000000000000ULL, APFloat::IEEEdouble(), true, false, 0x0000000000000000ULL },
+ { 0xfff4000000000000ULL, APFloat::IEEEdouble(), true, true, 0x0000000000000000ULL },
+ { 0x7ff000000000ae72ULL, APFloat::IEEEdouble(), true, false, 0x000000000000ae72ULL },
+ { 0x7ff7ffffffffae72ULL, APFloat::IEEEdouble(), true, false, 0xffffffffffffae72ULL },
+ { 0x7ff1aaaaaaaaae72ULL, APFloat::IEEEdouble(), true, false, 0x0001aaaaaaaaae72ULL },
+ };
+
+ for (const auto &t : tests) {
+ ASSERT_EQ(t.expected, nanbitsFromAPInt(t.semantics, t.SNaN, t.Negative, t.payload));
+ }
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(APFloatTest, SemanticsDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEsingle(), 0.0f).convertToDouble(), "Float semantics are not IEEEdouble");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), 0.0 ).convertToFloat(), "Float semantics are not IEEEsingle");
+}
+
+TEST(APFloatTest, StringDecimalDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ""), "Invalid string length");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+"), "String has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-"), "String has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("\0", 1)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1\0", 2)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1" "\0" "2", 3)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1" "\0" "2e1", 5)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e\0", 3)), "Invalid character in exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e1\0", 4)), "Invalid character in exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("1e1" "\0" "2", 5)), "Invalid character in exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0f"), "Invalid character in significand");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".."), "String contains multiple dots");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "..0"), "String contains multiple dots");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0.0"), "String contains multiple dots");
+}
+
+TEST(APFloatTest, StringDecimalSignificandDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "."), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+."), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-."), "Significand has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "e"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+e"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-e"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "e1"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+e1"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-e1"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".e1"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.e1"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.e1"), "Significand has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".e"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.e"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.e"), "Significand has no digits");
+}
+
+TEST(APFloatTest, StringDecimalExponentDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1e"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1.e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1.e"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+.1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-.1e"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+1.1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-1.1e"), "Exponent has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1e-"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), ".1e-"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "1.0e-"), "Exponent has no digits");
+}
+
+TEST(APFloatTest, StringHexadecimalDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x"), "Invalid string");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x"), "Invalid string");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x"), "Invalid string");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0"), "Hex strings require an exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0."), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0."), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0."), "Hex strings require an exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.0"), "Hex strings require an exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x0.0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x0.0"), "Hex strings require an exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x0.0"), "Hex strings require an exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x\0", 3)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1\0", 4)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1" "\0" "2", 5)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1" "\0" "2p1", 7)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p\0", 5)), "Invalid character in exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p1\0", 6)), "Invalid character in exponent");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), StringRef("0x1p1" "\0" "2", 7)), "Invalid character in exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p0f"), "Invalid character in exponent");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x..p1"), "String contains multiple dots");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x..0p1"), "String contains multiple dots");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.0.0p1"), "String contains multiple dots");
+}
+
+TEST(APFloatTest, StringHexadecimalSignificandDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x."), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x."), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x."), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp+"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp+"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp+"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0xp-"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0xp-"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0xp-"), "Significand has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p+"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p+"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p+"), "Significand has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.p-"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.p-"), "Significand has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.p-"), "Significand has no digits");
+}
+
+TEST(APFloatTest, StringHexadecimalExponentDeath) {
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p+"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1p-"), "Exponent has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p+"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.p-"), "Exponent has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p+"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x.1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x.1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x.1p-"), "Exponent has no digits");
+
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p+"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p+"), "Exponent has no digits");
+
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "0x1.1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "+0x1.1p-"), "Exponent has no digits");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble(), "-0x1.1p-"), "Exponent has no digits");
+}
+#endif
+#endif
+
+TEST(APFloatTest, exactInverse) {
+ APFloat inv(0.0f);
+
+ // Trivial operation.
+ EXPECT_TRUE(APFloat(2.0).getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5)));
+ EXPECT_TRUE(APFloat(2.0f).getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(0.5f)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEquad(), "2.0").getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::IEEEquad(), "0.5")));
+ EXPECT_TRUE(APFloat(APFloat::PPCDoubleDouble(), "2.0").getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::PPCDoubleDouble(), "0.5")));
+ EXPECT_TRUE(APFloat(APFloat::x87DoubleExtended(), "2.0").getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(APFloat::x87DoubleExtended(), "0.5")));
+
+ // FLT_MIN
+ EXPECT_TRUE(APFloat(1.17549435e-38f).getExactInverse(&inv));
+ EXPECT_TRUE(inv.bitwiseIsEqual(APFloat(8.5070592e+37f)));
+
+ // Large float, inverse is a denormal.
+ EXPECT_FALSE(APFloat(1.7014118e38f).getExactInverse(nullptr));
+ // Zero
+ EXPECT_FALSE(APFloat(0.0).getExactInverse(nullptr));
+ // Denormalized float
+ EXPECT_FALSE(APFloat(1.40129846e-45f).getExactInverse(nullptr));
+}
+
+TEST(APFloatTest, roundToIntegral) {
+ APFloat T(-0.5), S(3.14), R(APFloat::getLargest(APFloat::IEEEdouble())), P(0.0);
+
+ P = T;
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_EQ(-0.0, P.convertToDouble());
+ P = T;
+ P.roundToIntegral(APFloat::rmTowardNegative);
+ EXPECT_EQ(-1.0, P.convertToDouble());
+ P = T;
+ P.roundToIntegral(APFloat::rmTowardPositive);
+ EXPECT_EQ(-0.0, P.convertToDouble());
+ P = T;
+ P.roundToIntegral(APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(-0.0, P.convertToDouble());
+
+ P = S;
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_EQ(3.0, P.convertToDouble());
+ P = S;
+ P.roundToIntegral(APFloat::rmTowardNegative);
+ EXPECT_EQ(3.0, P.convertToDouble());
+ P = S;
+ P.roundToIntegral(APFloat::rmTowardPositive);
+ EXPECT_EQ(4.0, P.convertToDouble());
+ P = S;
+ P.roundToIntegral(APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(3.0, P.convertToDouble());
+
+ P = R;
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
+ P = R;
+ P.roundToIntegral(APFloat::rmTowardNegative);
+ EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
+ P = R;
+ P.roundToIntegral(APFloat::rmTowardPositive);
+ EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
+ P = R;
+ P.roundToIntegral(APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(R.convertToDouble(), P.convertToDouble());
+
+ P = APFloat::getZero(APFloat::IEEEdouble());
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_EQ(0.0, P.convertToDouble());
+ P = APFloat::getZero(APFloat::IEEEdouble(), true);
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_EQ(-0.0, P.convertToDouble());
+ P = APFloat::getNaN(APFloat::IEEEdouble());
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_TRUE(std::isnan(P.convertToDouble()));
+ P = APFloat::getInf(APFloat::IEEEdouble());
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() > 0.0);
+ P = APFloat::getInf(APFloat::IEEEdouble(), true);
+ P.roundToIntegral(APFloat::rmTowardZero);
+ EXPECT_TRUE(std::isinf(P.convertToDouble()) && P.convertToDouble() < 0.0);
+}
+
+TEST(APFloatTest, isInteger) {
+ APFloat T(-0.0);
+ EXPECT_TRUE(T.isInteger());
+ T = APFloat(3.14159);
+ EXPECT_FALSE(T.isInteger());
+ T = APFloat::getNaN(APFloat::IEEEdouble());
+ EXPECT_FALSE(T.isInteger());
+ T = APFloat::getInf(APFloat::IEEEdouble());
+ EXPECT_FALSE(T.isInteger());
+ T = APFloat::getInf(APFloat::IEEEdouble(), true);
+ EXPECT_FALSE(T.isInteger());
+ T = APFloat::getLargest(APFloat::IEEEdouble());
+ EXPECT_TRUE(T.isInteger());
+}
+
+TEST(DoubleAPFloatTest, isInteger) {
+ APFloat F1(-0.0);
+ APFloat F2(-0.0);
+ llvm::detail::DoubleAPFloat T(APFloat::PPCDoubleDouble(), std::move(F1),
+ std::move(F2));
+ EXPECT_TRUE(T.isInteger());
+ APFloat F3(3.14159);
+ APFloat F4(-0.0);
+ llvm::detail::DoubleAPFloat T2(APFloat::PPCDoubleDouble(), std::move(F3),
+ std::move(F4));
+ EXPECT_FALSE(T2.isInteger());
+ APFloat F5(-0.0);
+ APFloat F6(3.14159);
+ llvm::detail::DoubleAPFloat T3(APFloat::PPCDoubleDouble(), std::move(F5),
+ std::move(F6));
+ EXPECT_FALSE(T3.isInteger());
+}
+
+TEST(APFloatTest, getLargest) {
+ EXPECT_EQ(3.402823466e+38f, APFloat::getLargest(APFloat::IEEEsingle()).convertToFloat());
+ EXPECT_EQ(1.7976931348623158e+308, APFloat::getLargest(APFloat::IEEEdouble()).convertToDouble());
+}
+
+TEST(APFloatTest, getSmallest) {
+ APFloat test = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat expected = APFloat(APFloat::IEEEsingle(), "0x0.000002p-126");
+ EXPECT_FALSE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ expected = APFloat(APFloat::IEEEsingle(), "-0x0.000002p-126");
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallest(APFloat::IEEEquad(), false);
+ expected = APFloat(APFloat::IEEEquad(), "0x0.0000000000000000000000000001p-16382");
+ EXPECT_FALSE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallest(APFloat::IEEEquad(), true);
+ expected = APFloat(APFloat::IEEEquad(), "-0x0.0000000000000000000000000001p-16382");
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_TRUE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+}
+
+TEST(APFloatTest, getSmallestNormalized) {
+ APFloat test = APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat expected = APFloat(APFloat::IEEEsingle(), "0x1p-126");
+ EXPECT_FALSE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+ expected = APFloat(APFloat::IEEEsingle(), "-0x1p-126");
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), false);
+ expected = APFloat(APFloat::IEEEquad(), "0x1p-16382");
+ EXPECT_FALSE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+
+ test = APFloat::getSmallestNormalized(APFloat::IEEEquad(), true);
+ expected = APFloat(APFloat::IEEEquad(), "-0x1p-16382");
+ EXPECT_TRUE(test.isNegative());
+ EXPECT_TRUE(test.isFiniteNonZero());
+ EXPECT_FALSE(test.isDenormal());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+}
+
+TEST(APFloatTest, getZero) {
+ struct {
+ const fltSemantics *semantics;
+ const bool sign;
+ const unsigned long long bitPattern[2];
+ const unsigned bitPatternLength;
+ } const GetZeroTest[] = {
+ { &APFloat::IEEEhalf(), false, {0, 0}, 1},
+ { &APFloat::IEEEhalf(), true, {0x8000ULL, 0}, 1},
+ { &APFloat::IEEEsingle(), false, {0, 0}, 1},
+ { &APFloat::IEEEsingle(), true, {0x80000000ULL, 0}, 1},
+ { &APFloat::IEEEdouble(), false, {0, 0}, 1},
+ { &APFloat::IEEEdouble(), true, {0x8000000000000000ULL, 0}, 1},
+ { &APFloat::IEEEquad(), false, {0, 0}, 2},
+ { &APFloat::IEEEquad(), true, {0, 0x8000000000000000ULL}, 2},
+ { &APFloat::PPCDoubleDouble(), false, {0, 0}, 2},
+ { &APFloat::PPCDoubleDouble(), true, {0x8000000000000000ULL, 0}, 2},
+ { &APFloat::x87DoubleExtended(), false, {0, 0}, 2},
+ { &APFloat::x87DoubleExtended(), true, {0, 0x8000ULL}, 2},
+ };
+ const unsigned NumGetZeroTests = 12;
+ for (unsigned i = 0; i < NumGetZeroTests; ++i) {
+ APFloat test = APFloat::getZero(*GetZeroTest[i].semantics,
+ GetZeroTest[i].sign);
+ const char *pattern = GetZeroTest[i].sign? "-0x0p+0" : "0x0p+0";
+ APFloat expected = APFloat(*GetZeroTest[i].semantics,
+ pattern);
+ EXPECT_TRUE(test.isZero());
+ EXPECT_TRUE(GetZeroTest[i].sign? test.isNegative() : !test.isNegative());
+ EXPECT_TRUE(test.bitwiseIsEqual(expected));
+ for (unsigned j = 0, je = GetZeroTest[i].bitPatternLength; j < je; ++j) {
+ EXPECT_EQ(GetZeroTest[i].bitPattern[j],
+ test.bitcastToAPInt().getRawData()[j]);
+ }
+ }
+}
+
+TEST(APFloatTest, copySign) {
+ EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual(
+ APFloat::copySign(APFloat(42.0), APFloat(-1.0))));
+ EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual(
+ APFloat::copySign(APFloat(-42.0), APFloat(1.0))));
+ EXPECT_TRUE(APFloat(-42.0).bitwiseIsEqual(
+ APFloat::copySign(APFloat(-42.0), APFloat(-1.0))));
+ EXPECT_TRUE(APFloat(42.0).bitwiseIsEqual(
+ APFloat::copySign(APFloat(42.0), APFloat(1.0))));
+}
+
+TEST(APFloatTest, convert) {
+ bool losesInfo;
+ APFloat test(APFloat::IEEEdouble(), "1.0");
+ test.convert(APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(1.0f, test.convertToFloat());
+ EXPECT_FALSE(losesInfo);
+
+ test = APFloat(APFloat::x87DoubleExtended(), "0x1p-53");
+ test.add(APFloat(APFloat::x87DoubleExtended(), "1.0"), APFloat::rmNearestTiesToEven);
+ test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(1.0, test.convertToDouble());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::IEEEquad(), "0x1p-53");
+ test.add(APFloat(APFloat::IEEEquad(), "1.0"), APFloat::rmNearestTiesToEven);
+ test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(1.0, test.convertToDouble());
+ EXPECT_TRUE(losesInfo);
+
+ test = APFloat(APFloat::x87DoubleExtended(), "0xf.fffffffp+28");
+ test.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &losesInfo);
+ EXPECT_EQ(4294967295.0, test.convertToDouble());
+ EXPECT_FALSE(losesInfo);
+
+ test = APFloat::getSNaN(APFloat::IEEEsingle());
+ APFloat X87SNaN = APFloat::getSNaN(APFloat::x87DoubleExtended());
+ test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven,
+ &losesInfo);
+ EXPECT_TRUE(test.bitwiseIsEqual(X87SNaN));
+ EXPECT_FALSE(losesInfo);
+
+ test = APFloat::getQNaN(APFloat::IEEEsingle());
+ APFloat X87QNaN = APFloat::getQNaN(APFloat::x87DoubleExtended());
+ test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven,
+ &losesInfo);
+ EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN));
+ EXPECT_FALSE(losesInfo);
+
+ test = APFloat::getSNaN(APFloat::x87DoubleExtended());
+ test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven,
+ &losesInfo);
+ EXPECT_TRUE(test.bitwiseIsEqual(X87SNaN));
+ EXPECT_FALSE(losesInfo);
+
+ test = APFloat::getQNaN(APFloat::x87DoubleExtended());
+ test.convert(APFloat::x87DoubleExtended(), APFloat::rmNearestTiesToEven,
+ &losesInfo);
+ EXPECT_TRUE(test.bitwiseIsEqual(X87QNaN));
+ EXPECT_FALSE(losesInfo);
+}
+
+TEST(APFloatTest, PPCDoubleDouble) {
+ APFloat test(APFloat::PPCDoubleDouble(), "1.0");
+ EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
+
+ // LDBL_MAX
+ test = APFloat(APFloat::PPCDoubleDouble(), "1.79769313486231580793728971405301e+308");
+ EXPECT_EQ(0x7fefffffffffffffull, test.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x7c8ffffffffffffeull, test.bitcastToAPInt().getRawData()[1]);
+
+ // LDBL_MIN
+ test = APFloat(APFloat::PPCDoubleDouble(), "2.00416836000897277799610805135016e-292");
+ EXPECT_EQ(0x0360000000000000ull, test.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
+
+ // PR30869
+ {
+ auto Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") +
+ APFloat(APFloat::PPCDoubleDouble(), "1.0");
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+
+ Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") -
+ APFloat(APFloat::PPCDoubleDouble(), "1.0");
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+
+ Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") *
+ APFloat(APFloat::PPCDoubleDouble(), "1.0");
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+
+ Result = APFloat(APFloat::PPCDoubleDouble(), "1.0") /
+ APFloat(APFloat::PPCDoubleDouble(), "1.0");
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+
+ int Exp;
+ Result = frexp(APFloat(APFloat::PPCDoubleDouble(), "1.0"), Exp,
+ APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+
+ Result = scalbn(APFloat(APFloat::PPCDoubleDouble(), "1.0"), 1,
+ APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(&APFloat::PPCDoubleDouble(), &Result.getSemantics());
+ }
+}
+
+TEST(APFloatTest, isNegative) {
+ APFloat t(APFloat::IEEEsingle(), "0x1p+0");
+ EXPECT_FALSE(t.isNegative());
+ t = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ EXPECT_TRUE(t.isNegative());
+
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNegative());
+ EXPECT_TRUE(APFloat::getInf(APFloat::IEEEsingle(), true).isNegative());
+
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNegative());
+ EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), true).isNegative());
+
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNegative());
+ EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), true).isNegative());
+
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNegative());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isNegative());
+}
+
+TEST(APFloatTest, isNormal) {
+ APFloat t(APFloat::IEEEsingle(), "0x1p+0");
+ EXPECT_TRUE(t.isNormal());
+
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNormal());
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNormal());
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNormal());
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNormal());
+ EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNormal());
+}
+
+TEST(APFloatTest, isFinite) {
+ APFloat t(APFloat::IEEEsingle(), "0x1p+0");
+ EXPECT_TRUE(t.isFinite());
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFinite());
+ EXPECT_TRUE(APFloat::getZero(APFloat::IEEEsingle(), false).isFinite());
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFinite());
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFinite());
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFinite());
+}
+
+TEST(APFloatTest, isInfinity) {
+ APFloat t(APFloat::IEEEsingle(), "0x1p+0");
+ EXPECT_FALSE(t.isInfinity());
+ EXPECT_TRUE(APFloat::getInf(APFloat::IEEEsingle(), false).isInfinity());
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isInfinity());
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isInfinity());
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isInfinity());
+ EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isInfinity());
+}
+
+TEST(APFloatTest, isNaN) {
+ APFloat t(APFloat::IEEEsingle(), "0x1p+0");
+ EXPECT_FALSE(t.isNaN());
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isNaN());
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isNaN());
+ EXPECT_TRUE(APFloat::getNaN(APFloat::IEEEsingle(), false).isNaN());
+ EXPECT_TRUE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isNaN());
+ EXPECT_FALSE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isNaN());
+}
+
+TEST(APFloatTest, isFiniteNonZero) {
+ // Test positive/negative normal value.
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p+0").isFiniteNonZero());
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p+0").isFiniteNonZero());
+
+ // Test positive/negative denormal value.
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "0x1p-149").isFiniteNonZero());
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p-149").isFiniteNonZero());
+
+ // Test +/- Infinity.
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), false).isFiniteNonZero());
+ EXPECT_FALSE(APFloat::getInf(APFloat::IEEEsingle(), true).isFiniteNonZero());
+
+ // Test +/- Zero.
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), false).isFiniteNonZero());
+ EXPECT_FALSE(APFloat::getZero(APFloat::IEEEsingle(), true).isFiniteNonZero());
+
+ // Test +/- qNaN. +/- dont mean anything with qNaN but paranoia can't hurt in
+ // this instance.
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), false).isFiniteNonZero());
+ EXPECT_FALSE(APFloat::getNaN(APFloat::IEEEsingle(), true).isFiniteNonZero());
+
+ // Test +/- sNaN. +/- dont mean anything with sNaN but paranoia can't hurt in
+ // this instance.
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), false).isFiniteNonZero());
+ EXPECT_FALSE(APFloat::getSNaN(APFloat::IEEEsingle(), true).isFiniteNonZero());
+}
+
+TEST(APFloatTest, add) {
+ // Test Special Cases against each other and normal values.
+
+ // TODOS/NOTES:
+ // 1. Since we perform only default exception handling all operations with
+ // signaling NaNs should have a result that is a quiet NaN. Currently they
+ // return sNaN.
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
+
+ const unsigned NumTests = 169;
+ struct {
+ APFloat x;
+ APFloat y;
+ const char *result;
+ int status;
+ int category;
+ } SpecialCaseTests[NumTests] = {
+ { PInf, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { PInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { PZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PZero, PNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MZero, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MZero, PNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { QNaN, PInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { QNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { QNaN, PNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { SNaN, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, QNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, PZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { PNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PNormalValue, "0x1p+1", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, PSmallestValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MSmallestValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, PSmallestNormalized, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MSmallestNormalized, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, PZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MNormalValue, "-0x1p+1", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PSmallestValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MSmallestValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PSmallestNormalized, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MSmallestNormalized, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, PZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { PLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PLargestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PSmallestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MSmallestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PSmallestNormalized, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MSmallestNormalized, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, PZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MLargestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, PSmallestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MSmallestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PSmallestNormalized, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MSmallestNormalized, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, PZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { PSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestValue, PNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, MNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PSmallestValue, "0x1p-148", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, PSmallestNormalized, "0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestNormalized, "-0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, PZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestValue, PNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, MNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, MSmallestValue, "-0x1p-148", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PSmallestNormalized, "0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestNormalized, "-0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, PZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestNormalized, PNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, MNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestValue, "0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MSmallestValue, "0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestNormalized, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, PZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+ // See Note 1.
+ { MSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestNormalized, PNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, MNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, PLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, MLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestValue, "-0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MSmallestValue, "-0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, MSmallestNormalized, "-0x1p-125", APFloat::opOK, APFloat::fcNormal }
+ };
+
+ for (size_t i = 0; i < NumTests; ++i) {
+ APFloat x(SpecialCaseTests[i].x);
+ APFloat y(SpecialCaseTests[i].y);
+ APFloat::opStatus status = x.add(y, APFloat::rmNearestTiesToEven);
+
+ APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
+
+ EXPECT_TRUE(result.bitwiseIsEqual(x));
+ EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
+ EXPECT_TRUE((int)x.getCategory() == SpecialCaseTests[i].category);
+ }
+}
+
+TEST(APFloatTest, subtract) {
+ // Test Special Cases against each other and normal values.
+
+ // TODOS/NOTES:
+ // 1. Since we perform only default exception handling all operations with
+ // signaling NaNs should have a result that is a quiet NaN. Currently they
+ // return sNaN.
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
+
+ const unsigned NumTests = 169;
+ struct {
+ APFloat x;
+ APFloat y;
+ const char *result;
+ int status;
+ int category;
+ } SpecialCaseTests[NumTests] = {
+ { PInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MInf, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PZero, PSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PZero, MSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MZero, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MZero, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MZero, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MZero, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MZero, PSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MZero, MSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { QNaN, PInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { QNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { QNaN, PNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { SNaN, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, QNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, PZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MZero, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MNormalValue, "0x1p+1", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, PSmallestValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MSmallestValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, PSmallestNormalized, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PNormalValue, MSmallestNormalized, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, PZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MZero, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MNormalValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MNormalValue, PNormalValue, "-0x1p+1", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PSmallestValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MSmallestValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, PSmallestNormalized, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MNormalValue, MSmallestNormalized, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, PZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MZero, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MLargestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, PSmallestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MSmallestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, PSmallestNormalized, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PLargestValue, MSmallestNormalized, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, PZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MZero, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MLargestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PLargestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PSmallestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MSmallestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, PSmallestNormalized, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MLargestValue, MSmallestNormalized, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, PZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MZero, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestValue, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, MSmallestValue, "0x1p-148", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PSmallestNormalized, "-0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestNormalized, "0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, PZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MZero, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestValue, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestValue, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestValue, PSmallestValue, "-0x1p-148", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, PSmallestNormalized, "-0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestNormalized, "0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, PZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MZero, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestValue, "0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MSmallestValue, "0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, MSmallestNormalized, "0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, PZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MZero, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, QNaN, "-nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestNormalized, SNaN, "-nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestNormalized, PNormalValue, "-0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, MNormalValue, "0x1p+0", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, PLargestValue, "-0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, MLargestValue, "0x1.fffffep+127", APFloat::opInexact, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestValue, "-0x1.000002p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MSmallestValue, "-0x1.fffffcp-127", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestNormalized, "-0x1p-125", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero }
+ };
+
+ for (size_t i = 0; i < NumTests; ++i) {
+ APFloat x(SpecialCaseTests[i].x);
+ APFloat y(SpecialCaseTests[i].y);
+ APFloat::opStatus status = x.subtract(y, APFloat::rmNearestTiesToEven);
+
+ APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
+
+ EXPECT_TRUE(result.bitwiseIsEqual(x));
+ EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
+ EXPECT_TRUE((int)x.getCategory() == SpecialCaseTests[i].category);
+ }
+}
+
+TEST(APFloatTest, multiply) {
+ // Test Special Cases against each other and normal values.
+
+ // TODOS/NOTES:
+ // 1. Since we perform only default exception handling all operations with
+ // signaling NaNs should have a result that is a quiet NaN. Currently they
+ // return sNaN.
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
+ const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;
+
+ const unsigned NumTests = 169;
+ struct {
+ APFloat x;
+ APFloat y;
+ const char *result;
+ int status;
+ int category;
+ } SpecialCaseTests[NumTests] = {
+ { PInf, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PZero, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MZero, PNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { QNaN, PInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { QNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { QNaN, PNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { SNaN, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, QNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PNormalValue, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MNormalValue, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MNormalValue, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PLargestValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MLargestValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PSmallestValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MSmallestValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PSmallestNormalized, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MSmallestNormalized, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PLargestValue, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PLargestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, MLargestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, PSmallestValue, "0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MSmallestValue, "-0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PSmallestNormalized, "0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MSmallestNormalized, "-0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MLargestValue, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PLargestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, MLargestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, PSmallestValue, "-0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MSmallestValue, "0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PSmallestNormalized, "-0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MSmallestNormalized, "0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestValue, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestValue, PNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PLargestValue, "0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MLargestValue, "-0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PSmallestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestValue, MSmallestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestValue, PSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestValue, MSmallestNormalized, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestValue, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestValue, PNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PLargestValue, "-0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MLargestValue, "0x1.fffffep-22", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PSmallestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, MSmallestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, PSmallestNormalized, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, MSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, PInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, MInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PSmallestNormalized, PZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, MZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestNormalized, PNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PLargestValue, "0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MLargestValue, "-0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, MSmallestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, PSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, MSmallestNormalized, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, PInf, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, MInf, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MSmallestNormalized, PZero, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, MZero, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestNormalized, PNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PLargestValue, "-0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MLargestValue, "0x1.fffffep+1", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, MSmallestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, PSmallestNormalized, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, MSmallestNormalized, "0x0p+0", UnderflowStatus, APFloat::fcZero }
+ };
+
+ for (size_t i = 0; i < NumTests; ++i) {
+ APFloat x(SpecialCaseTests[i].x);
+ APFloat y(SpecialCaseTests[i].y);
+ APFloat::opStatus status = x.multiply(y, APFloat::rmNearestTiesToEven);
+
+ APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
+
+ EXPECT_TRUE(result.bitwiseIsEqual(x));
+ EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
+ EXPECT_TRUE((int)x.getCategory() == SpecialCaseTests[i].category);
+ }
+}
+
+TEST(APFloatTest, divide) {
+ // Test Special Cases against each other and normal values.
+
+ // TODOS/NOTES:
+ // 1. Since we perform only default exception handling all operations with
+ // signaling NaNs should have a result that is a quiet NaN. Currently they
+ // return sNaN.
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ const int OverflowStatus = APFloat::opOverflow | APFloat::opInexact;
+ const int UnderflowStatus = APFloat::opUnderflow | APFloat::opInexact;
+
+ const unsigned NumTests = 169;
+ struct {
+ APFloat x;
+ APFloat y;
+ const char *result;
+ int status;
+ int category;
+ } SpecialCaseTests[NumTests] = {
+ { PInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PInf, PZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PInf, PNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, PSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PInf, MSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MInf, PZero, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MZero, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MInf, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MInf, PNormalValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MNormalValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PLargestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MLargestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestValue, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestValue, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, PSmallestNormalized, "-inf", APFloat::opOK, APFloat::fcInfinity },
+ { MInf, MSmallestNormalized, "inf", APFloat::opOK, APFloat::fcInfinity },
+ { PZero, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { PZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PZero, PNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, PSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PZero, MSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { MZero, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MZero, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MZero, PNormalValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MNormalValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PLargestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MLargestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestValue, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestValue, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, PSmallestNormalized, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MZero, MSmallestNormalized, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { QNaN, PInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MInf, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MZero, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { QNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { QNaN, PNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MNormalValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MLargestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestValue, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, PSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+ { QNaN, MSmallestNormalized, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { SNaN, PInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MInf, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MZero, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, QNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MNormalValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MLargestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestValue, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, PSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+ { SNaN, MSmallestNormalized, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PNormalValue, PZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PNormalValue, MZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PNormalValue, PNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, PLargestValue, "0x1p-128", UnderflowStatus, APFloat::fcNormal },
+ { PNormalValue, MLargestValue, "-0x1p-128", UnderflowStatus, APFloat::fcNormal },
+ { PNormalValue, PSmallestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PNormalValue, MSmallestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { PNormalValue, PSmallestNormalized, "0x1p+126", APFloat::opOK, APFloat::fcNormal },
+ { PNormalValue, MSmallestNormalized, "-0x1p+126", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MNormalValue, PZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MNormalValue, MZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MNormalValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MNormalValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MNormalValue, PNormalValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MNormalValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, PLargestValue, "-0x1p-128", UnderflowStatus, APFloat::fcNormal },
+ { MNormalValue, MLargestValue, "0x1p-128", UnderflowStatus, APFloat::fcNormal },
+ { MNormalValue, PSmallestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MNormalValue, MSmallestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { MNormalValue, PSmallestNormalized, "-0x1p+126", APFloat::opOK, APFloat::fcNormal },
+ { MNormalValue, MSmallestNormalized, "0x1p+126", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PLargestValue, PZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PLargestValue, MZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PLargestValue, PNormalValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MNormalValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PLargestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, MLargestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PLargestValue, PSmallestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, MSmallestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, PSmallestNormalized, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PLargestValue, MSmallestNormalized, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MLargestValue, PZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MLargestValue, MZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MLargestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MLargestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MLargestValue, PNormalValue, "-0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MNormalValue, "0x1.fffffep+127", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PLargestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, MLargestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MLargestValue, PSmallestValue, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, MSmallestValue, "inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, PSmallestNormalized, "-inf", OverflowStatus, APFloat::fcInfinity },
+ { MLargestValue, MSmallestNormalized, "inf", OverflowStatus, APFloat::fcInfinity },
+ { PSmallestValue, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestValue, PZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PSmallestValue, MZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestValue, PNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PLargestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestValue, MLargestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestValue, PSmallestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, PSmallestNormalized, "0x1p-23", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestValue, MSmallestNormalized, "-0x1p-23", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestValue, PZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MSmallestValue, MZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MSmallestValue, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestValue, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestValue, PNormalValue, "-0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MNormalValue, "0x1p-149", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PLargestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, MLargestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestValue, PSmallestValue, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestValue, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, PSmallestNormalized, "-0x1p-23", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestValue, MSmallestNormalized, "0x1p-23", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, MInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { PSmallestNormalized, PZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PSmallestNormalized, MZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { PSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { PSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { PSmallestNormalized, PNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PLargestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, MLargestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { PSmallestNormalized, PSmallestValue, "0x1p+23", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MSmallestValue, "-0x1p+23", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, PSmallestNormalized, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { PSmallestNormalized, MSmallestNormalized, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PInf, "-0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, MInf, "0x0p+0", APFloat::opOK, APFloat::fcZero },
+ { MSmallestNormalized, PZero, "-inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MSmallestNormalized, MZero, "inf", APFloat::opDivByZero, APFloat::fcInfinity },
+ { MSmallestNormalized, QNaN, "nan", APFloat::opOK, APFloat::fcNaN },
+#if 0
+// See Note 1.
+ { MSmallestNormalized, SNaN, "nan", APFloat::opInvalidOp, APFloat::fcNaN },
+#endif
+ { MSmallestNormalized, PNormalValue, "-0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MNormalValue, "0x1p-126", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PLargestValue, "-0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, MLargestValue, "0x0p+0", UnderflowStatus, APFloat::fcZero },
+ { MSmallestNormalized, PSmallestValue, "-0x1p+23", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MSmallestValue, "0x1p+23", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, PSmallestNormalized, "-0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ { MSmallestNormalized, MSmallestNormalized, "0x1p+0", APFloat::opOK, APFloat::fcNormal },
+ };
+
+ for (size_t i = 0; i < NumTests; ++i) {
+ APFloat x(SpecialCaseTests[i].x);
+ APFloat y(SpecialCaseTests[i].y);
+ APFloat::opStatus status = x.divide(y, APFloat::rmNearestTiesToEven);
+
+ APFloat result(APFloat::IEEEsingle(), SpecialCaseTests[i].result);
+
+ EXPECT_TRUE(result.bitwiseIsEqual(x));
+ EXPECT_TRUE((int)status == SpecialCaseTests[i].status);
+ EXPECT_TRUE((int)x.getCategory() == SpecialCaseTests[i].category);
+ }
+}
+
+TEST(APFloatTest, operatorOverloads) {
+ // This is mostly testing that these operator overloads compile.
+ APFloat One = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat Two = APFloat(APFloat::IEEEsingle(), "0x2p+0");
+ EXPECT_TRUE(Two.bitwiseIsEqual(One + One));
+ EXPECT_TRUE(One.bitwiseIsEqual(Two - One));
+ EXPECT_TRUE(Two.bitwiseIsEqual(One * Two));
+ EXPECT_TRUE(One.bitwiseIsEqual(Two / Two));
+}
+
+TEST(APFloatTest, abs) {
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat PQNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat MQNaN = APFloat::getNaN(APFloat::IEEEsingle(), true);
+ APFloat PSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+ APFloat MSNaN = APFloat::getSNaN(APFloat::IEEEsingle(), true);
+ APFloat PNormalValue = APFloat(APFloat::IEEEsingle(), "0x1p+0");
+ APFloat MNormalValue = APFloat(APFloat::IEEEsingle(), "-0x1p+0");
+ APFloat PLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), false);
+ APFloat MLargestValue = APFloat::getLargest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), false);
+ APFloat MSmallestValue = APFloat::getSmallest(APFloat::IEEEsingle(), true);
+ APFloat PSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false);
+ APFloat MSmallestNormalized =
+ APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true);
+
+ EXPECT_TRUE(PInf.bitwiseIsEqual(abs(PInf)));
+ EXPECT_TRUE(PInf.bitwiseIsEqual(abs(MInf)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(abs(PZero)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(abs(MZero)));
+ EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(PQNaN)));
+ EXPECT_TRUE(PQNaN.bitwiseIsEqual(abs(MQNaN)));
+ EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(PSNaN)));
+ EXPECT_TRUE(PSNaN.bitwiseIsEqual(abs(MSNaN)));
+ EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(PNormalValue)));
+ EXPECT_TRUE(PNormalValue.bitwiseIsEqual(abs(MNormalValue)));
+ EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(PLargestValue)));
+ EXPECT_TRUE(PLargestValue.bitwiseIsEqual(abs(MLargestValue)));
+ EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(PSmallestValue)));
+ EXPECT_TRUE(PSmallestValue.bitwiseIsEqual(abs(MSmallestValue)));
+ EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(PSmallestNormalized)));
+ EXPECT_TRUE(PSmallestNormalized.bitwiseIsEqual(abs(MSmallestNormalized)));
+}
+
+TEST(APFloatTest, neg) {
+ APFloat One = APFloat(APFloat::IEEEsingle(), "1.0");
+ APFloat NegOne = APFloat(APFloat::IEEEsingle(), "-1.0");
+ APFloat Zero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat NegZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat Inf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat NegInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat QNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat NegQNaN = APFloat::getNaN(APFloat::IEEEsingle(), true);
+
+ EXPECT_TRUE(NegOne.bitwiseIsEqual(neg(One)));
+ EXPECT_TRUE(One.bitwiseIsEqual(neg(NegOne)));
+ EXPECT_TRUE(NegZero.bitwiseIsEqual(neg(Zero)));
+ EXPECT_TRUE(Zero.bitwiseIsEqual(neg(NegZero)));
+ EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf)));
+ EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf)));
+ EXPECT_TRUE(NegInf.bitwiseIsEqual(neg(Inf)));
+ EXPECT_TRUE(Inf.bitwiseIsEqual(neg(NegInf)));
+ EXPECT_TRUE(NegQNaN.bitwiseIsEqual(neg(QNaN)));
+ EXPECT_TRUE(QNaN.bitwiseIsEqual(neg(NegQNaN)));
+}
+
+TEST(APFloatTest, ilogb) {
+ EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false)));
+ EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true)));
+ EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1024")));
+ EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023")));
+ EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023")));
+ EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51")));
+ EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023")));
+ EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble(), "0x0.ffffp-1")));
+ EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023")));
+ EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false)));
+ EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true)));
+
+
+ EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0")));
+ EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0")));
+ EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42")));
+ EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p-42")));
+
+ EXPECT_EQ(APFloat::IEK_Inf,
+ ilogb(APFloat::getInf(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(APFloat::IEK_Inf,
+ ilogb(APFloat::getInf(APFloat::IEEEsingle(), true)));
+ EXPECT_EQ(APFloat::IEK_Zero,
+ ilogb(APFloat::getZero(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(APFloat::IEK_Zero,
+ ilogb(APFloat::getZero(APFloat::IEEEsingle(), true)));
+ EXPECT_EQ(APFloat::IEK_NaN,
+ ilogb(APFloat::getNaN(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(APFloat::IEK_NaN,
+ ilogb(APFloat::getSNaN(APFloat::IEEEsingle(), false)));
+
+ EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), true)));
+
+ EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), true)));
+ EXPECT_EQ(-126,
+ ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false)));
+ EXPECT_EQ(-126,
+ ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true)));
+}
+
+TEST(APFloatTest, scalbn) {
+
+ const APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle(), "0x1p+0")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 0, RM)));
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle(), "0x1p+42")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 42, RM)));
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle(), "0x1p-42")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), -42, RM)));
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEsingle(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEsingle(), true);
+ APFloat PZero = APFloat::getZero(APFloat::IEEEsingle(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEsingle(), true);
+ APFloat QPNaN = APFloat::getNaN(APFloat::IEEEsingle(), false);
+ APFloat QMNaN = APFloat::getNaN(APFloat::IEEEsingle(), true);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEsingle(), false);
+
+ EXPECT_TRUE(PInf.bitwiseIsEqual(scalbn(PInf, 0, RM)));
+ EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0, RM)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0, RM)));
+ EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0, RM)));
+ EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0, RM)));
+ EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0, RM)));
+ EXPECT_FALSE(scalbn(SNaN, 0, RM).isSignaling());
+
+ APFloat ScalbnSNaN = scalbn(SNaN, 1, RM);
+ EXPECT_TRUE(ScalbnSNaN.isNaN() && !ScalbnSNaN.isSignaling());
+
+ // Make sure highest bit of payload is preserved.
+ const APInt Payload(64, (UINT64_C(1) << 50) |
+ (UINT64_C(1) << 49) |
+ (UINT64_C(1234) << 32) |
+ 1);
+
+ APFloat SNaNWithPayload = APFloat::getSNaN(APFloat::IEEEdouble(), false,
+ &Payload);
+ APFloat QuietPayload = scalbn(SNaNWithPayload, 1, RM);
+ EXPECT_TRUE(QuietPayload.isNaN() && !QuietPayload.isSignaling());
+ EXPECT_EQ(Payload, QuietPayload.bitcastToAPInt().getLoBits(51));
+
+ EXPECT_TRUE(PInf.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+0"), 128, RM)));
+ EXPECT_TRUE(MInf.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p+0"), 128, RM)));
+ EXPECT_TRUE(PInf.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "0x1p+127"), 1, RM)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "0x1p-127"), -127, RM)));
+ EXPECT_TRUE(MZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p-127"), -127, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEsingle(), "-0x1p-149").bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "-0x1p-127"), -22, RM)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle(), "0x1p-126"), -24, RM)));
+
+
+ APFloat SmallestF64 = APFloat::getSmallest(APFloat::IEEEdouble(), false);
+ APFloat NegSmallestF64 = APFloat::getSmallest(APFloat::IEEEdouble(), true);
+
+ APFloat LargestF64 = APFloat::getLargest(APFloat::IEEEdouble(), false);
+ APFloat NegLargestF64 = APFloat::getLargest(APFloat::IEEEdouble(), true);
+
+ APFloat SmallestNormalizedF64
+ = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false);
+ APFloat NegSmallestNormalizedF64
+ = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true);
+
+ APFloat LargestDenormalF64(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023");
+ APFloat NegLargestDenormalF64(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023");
+
+
+ EXPECT_TRUE(SmallestF64.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEdouble(), "0x1p-1074"), 0, RM)));
+ EXPECT_TRUE(NegSmallestF64.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEdouble(), "-0x1p-1074"), 0, RM)));
+
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1023")
+ .bitwiseIsEqual(scalbn(SmallestF64, 2097, RM)));
+
+ EXPECT_TRUE(scalbn(SmallestF64, -2097, RM).isPosZero());
+ EXPECT_TRUE(scalbn(SmallestF64, -2098, RM).isPosZero());
+ EXPECT_TRUE(scalbn(SmallestF64, -2099, RM).isPosZero());
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1022")
+ .bitwiseIsEqual(scalbn(SmallestF64, 2096, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+1023")
+ .bitwiseIsEqual(scalbn(SmallestF64, 2097, RM)));
+ EXPECT_TRUE(scalbn(SmallestF64, 2098, RM).isInfinity());
+ EXPECT_TRUE(scalbn(SmallestF64, 2099, RM).isInfinity());
+
+ // Test for integer overflows when adding to exponent.
+ EXPECT_TRUE(scalbn(SmallestF64, -INT_MAX, RM).isPosZero());
+ EXPECT_TRUE(scalbn(LargestF64, INT_MAX, RM).isInfinity());
+
+ EXPECT_TRUE(LargestDenormalF64
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 0, RM)));
+ EXPECT_TRUE(NegLargestDenormalF64
+ .bitwiseIsEqual(scalbn(NegLargestDenormalF64, 0, RM)));
+
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1022")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 1, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1021")
+ .bitwiseIsEqual(scalbn(NegLargestDenormalF64, 2, RM)));
+
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+1")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 1024, RM)));
+ EXPECT_TRUE(scalbn(LargestDenormalF64, -1023, RM).isPosZero());
+ EXPECT_TRUE(scalbn(LargestDenormalF64, -1024, RM).isPosZero());
+ EXPECT_TRUE(scalbn(LargestDenormalF64, -2048, RM).isPosZero());
+ EXPECT_TRUE(scalbn(LargestDenormalF64, 2047, RM).isInfinity());
+ EXPECT_TRUE(scalbn(LargestDenormalF64, 2098, RM).isInfinity());
+ EXPECT_TRUE(scalbn(LargestDenormalF64, 2099, RM).isInfinity());
+
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-2")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 1021, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 1022, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+0")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 1023, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep+1023")
+ .bitwiseIsEqual(scalbn(LargestDenormalF64, 2046, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p+974")
+ .bitwiseIsEqual(scalbn(SmallestF64, 2048, RM)));
+
+ APFloat RandomDenormalF64(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+51");
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-972")
+ .bitwiseIsEqual(scalbn(RandomDenormalF64, -1023, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1")
+ .bitwiseIsEqual(scalbn(RandomDenormalF64, -52, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-2")
+ .bitwiseIsEqual(scalbn(RandomDenormalF64, -53, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+0")
+ .bitwiseIsEqual(scalbn(RandomDenormalF64, -51, RM)));
+
+ EXPECT_TRUE(scalbn(RandomDenormalF64, -2097, RM).isPosZero());
+ EXPECT_TRUE(scalbn(RandomDenormalF64, -2090, RM).isPosZero());
+
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "-0x1p-1073")
+ .bitwiseIsEqual(scalbn(NegLargestF64, -2097, RM)));
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "-0x1p-1024")
+ .bitwiseIsEqual(scalbn(NegLargestF64, -2048, RM)));
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "0x1p-1073")
+ .bitwiseIsEqual(scalbn(LargestF64, -2097, RM)));
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "0x1p-1074")
+ .bitwiseIsEqual(scalbn(LargestF64, -2098, RM)));
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1074")
+ .bitwiseIsEqual(scalbn(NegLargestF64, -2098, RM)));
+ EXPECT_TRUE(scalbn(NegLargestF64, -2099, RM).isNegZero());
+ EXPECT_TRUE(scalbn(LargestF64, 1, RM).isInfinity());
+
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "0x1p+0")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble(), "0x1p+52"), -52, RM)));
+
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEdouble(), "0x1p-103")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEdouble(), "0x1p-51"), -52, RM)));
+}
+
+TEST(APFloatTest, frexp) {
+ const APFloat::roundingMode RM = APFloat::rmNearestTiesToEven;
+
+ APFloat PZero = APFloat::getZero(APFloat::IEEEdouble(), false);
+ APFloat MZero = APFloat::getZero(APFloat::IEEEdouble(), true);
+ APFloat One(1.0);
+ APFloat MOne(-1.0);
+ APFloat Two(2.0);
+ APFloat MTwo(-2.0);
+
+ APFloat LargestDenormal(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1023");
+ APFloat NegLargestDenormal(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1023");
+
+ APFloat Smallest = APFloat::getSmallest(APFloat::IEEEdouble(), false);
+ APFloat NegSmallest = APFloat::getSmallest(APFloat::IEEEdouble(), true);
+
+ APFloat Largest = APFloat::getLargest(APFloat::IEEEdouble(), false);
+ APFloat NegLargest = APFloat::getLargest(APFloat::IEEEdouble(), true);
+
+ APFloat PInf = APFloat::getInf(APFloat::IEEEdouble(), false);
+ APFloat MInf = APFloat::getInf(APFloat::IEEEdouble(), true);
+
+ APFloat QPNaN = APFloat::getNaN(APFloat::IEEEdouble(), false);
+ APFloat QMNaN = APFloat::getNaN(APFloat::IEEEdouble(), true);
+ APFloat SNaN = APFloat::getSNaN(APFloat::IEEEdouble(), false);
+
+ // Make sure highest bit of payload is preserved.
+ const APInt Payload(64, (UINT64_C(1) << 50) |
+ (UINT64_C(1) << 49) |
+ (UINT64_C(1234) << 32) |
+ 1);
+
+ APFloat SNaNWithPayload = APFloat::getSNaN(APFloat::IEEEdouble(), false,
+ &Payload);
+
+ APFloat SmallestNormalized
+ = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), false);
+ APFloat NegSmallestNormalized
+ = APFloat::getSmallestNormalized(APFloat::IEEEdouble(), true);
+
+ int Exp;
+ APFloat Frac(APFloat::IEEEdouble());
+
+
+ Frac = frexp(PZero, Exp, RM);
+ EXPECT_EQ(0, Exp);
+ EXPECT_TRUE(Frac.isPosZero());
+
+ Frac = frexp(MZero, Exp, RM);
+ EXPECT_EQ(0, Exp);
+ EXPECT_TRUE(Frac.isNegZero());
+
+
+ Frac = frexp(One, Exp, RM);
+ EXPECT_EQ(1, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(MOne, Exp, RM);
+ EXPECT_EQ(1, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(LargestDenormal, Exp, RM);
+ EXPECT_EQ(-1022, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(NegLargestDenormal, Exp, RM);
+ EXPECT_EQ(-1022, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.ffffffffffffep-1").bitwiseIsEqual(Frac));
+
+
+ Frac = frexp(Smallest, Exp, RM);
+ EXPECT_EQ(-1073, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(NegSmallest, Exp, RM);
+ EXPECT_EQ(-1073, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1p-1").bitwiseIsEqual(Frac));
+
+
+ Frac = frexp(Largest, Exp, RM);
+ EXPECT_EQ(1024, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(NegLargest, Exp, RM);
+ EXPECT_EQ(1024, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "-0x1.fffffffffffffp-1").bitwiseIsEqual(Frac));
+
+
+ Frac = frexp(PInf, Exp, RM);
+ EXPECT_EQ(INT_MAX, Exp);
+ EXPECT_TRUE(Frac.isInfinity() && !Frac.isNegative());
+
+ Frac = frexp(MInf, Exp, RM);
+ EXPECT_EQ(INT_MAX, Exp);
+ EXPECT_TRUE(Frac.isInfinity() && Frac.isNegative());
+
+ Frac = frexp(QPNaN, Exp, RM);
+ EXPECT_EQ(INT_MIN, Exp);
+ EXPECT_TRUE(Frac.isNaN());
+
+ Frac = frexp(QMNaN, Exp, RM);
+ EXPECT_EQ(INT_MIN, Exp);
+ EXPECT_TRUE(Frac.isNaN());
+
+ Frac = frexp(SNaN, Exp, RM);
+ EXPECT_EQ(INT_MIN, Exp);
+ EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
+
+ Frac = frexp(SNaNWithPayload, Exp, RM);
+ EXPECT_EQ(INT_MIN, Exp);
+ EXPECT_TRUE(Frac.isNaN() && !Frac.isSignaling());
+ EXPECT_EQ(Payload, Frac.bitcastToAPInt().getLoBits(51));
+
+ Frac = frexp(APFloat(APFloat::IEEEdouble(), "0x0.ffffp-1"), Exp, RM);
+ EXPECT_EQ(-1, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(APFloat(APFloat::IEEEdouble(), "0x1p-51"), Exp, RM);
+ EXPECT_EQ(-50, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1p-1").bitwiseIsEqual(Frac));
+
+ Frac = frexp(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp+51"), Exp, RM);
+ EXPECT_EQ(52, Exp);
+ EXPECT_TRUE(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1").bitwiseIsEqual(Frac));
+}
+
+TEST(APFloatTest, mod) {
+ {
+ APFloat f1(APFloat::IEEEdouble(), "1.5");
+ APFloat f2(APFloat::IEEEdouble(), "1.0");
+ APFloat expected(APFloat::IEEEdouble(), "0.5");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0.5");
+ APFloat f2(APFloat::IEEEdouble(), "1.0");
+ APFloat expected(APFloat::IEEEdouble(), "0.5");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1.3333333333333p-2"); // 0.3
+ APFloat f2(APFloat::IEEEdouble(), "0x1.47ae147ae147bp-7"); // 0.01
+ APFloat expected(APFloat::IEEEdouble(),
+ "0x1.47ae147ae1471p-7"); // 0.009999999999999983
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1p64"); // 1.8446744073709552e19
+ APFloat f2(APFloat::IEEEdouble(), "1.5");
+ APFloat expected(APFloat::IEEEdouble(), "1.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0x1p1000");
+ APFloat f2(APFloat::IEEEdouble(), "0x1p-1000");
+ APFloat expected(APFloat::IEEEdouble(), "0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0.0");
+ APFloat f2(APFloat::IEEEdouble(), "1.0");
+ APFloat expected(APFloat::IEEEdouble(), "0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "1.0");
+ APFloat f2(APFloat::IEEEdouble(), "0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
+ EXPECT_TRUE(f1.isNaN());
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "0.0");
+ APFloat f2(APFloat::IEEEdouble(), "0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
+ EXPECT_TRUE(f1.isNaN());
+ }
+ {
+ APFloat f1 = APFloat::getInf(APFloat::IEEEdouble(), false);
+ APFloat f2(APFloat::IEEEdouble(), "1.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opInvalidOp);
+ EXPECT_TRUE(f1.isNaN());
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "-4.0");
+ APFloat f2(APFloat::IEEEdouble(), "-2.0");
+ APFloat expected(APFloat::IEEEdouble(), "-0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+ {
+ APFloat f1(APFloat::IEEEdouble(), "-4.0");
+ APFloat f2(APFloat::IEEEdouble(), "2.0");
+ APFloat expected(APFloat::IEEEdouble(), "-0.0");
+ EXPECT_EQ(f1.mod(f2), APFloat::opOK);
+ EXPECT_TRUE(f1.bitwiseIsEqual(expected));
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleAddSpecial) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
+ APFloat::fltCategory, APFloat::roundingMode>;
+ DataType Data[] = {
+ // (1 + 0) + (-1 + 0) = fcZero
+ std::make_tuple(0x3ff0000000000000ull, 0, 0xbff0000000000000ull, 0,
+ APFloat::fcZero, APFloat::rmNearestTiesToEven),
+ // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x7948000000000000ull, 0ull, APFloat::fcInfinity,
+ APFloat::rmNearestTiesToEven),
+ // TODO: change the 4th 0x75effffffffffffe to 0x75efffffffffffff when
+ // semPPCDoubleDoubleLegacy is gone.
+ // LDBL_MAX + (1.011111... >> (1023 - 106) + (1.1111111...0 >> (1023 -
+ // 160))) = fcNormal
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x7947ffffffffffffull, 0x75effffffffffffeull,
+ APFloat::fcNormal, APFloat::rmNearestTiesToEven),
+ // LDBL_MAX + (1.1 >> (1023 - 106) + 0)) = fcInfinity
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ APFloat::fcInfinity, APFloat::rmNearestTiesToEven),
+ // NaN + (1 + 0) = fcNaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::fcNaN, APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2];
+ APFloat::fltCategory Expected;
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected, RM) = Tp;
+
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.add(A2, RM);
+
+ EXPECT_EQ(Expected, A1.getCategory())
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A2.add(A1, RM);
+
+ EXPECT_EQ(Expected, A2.getCategory())
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ }
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleAdd) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, APFloat::roundingMode>;
+ DataType Data[] = {
+ // (1 + 0) + (1e-105 + 0) = (1 + 1e-105)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3960000000000000ull, 0,
+ 0x3ff0000000000000ull, 0x3960000000000000ull,
+ APFloat::rmNearestTiesToEven),
+ // (1 + 0) + (1e-106 + 0) = (1 + 1e-106)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3950000000000000ull, 0,
+ 0x3ff0000000000000ull, 0x3950000000000000ull,
+ APFloat::rmNearestTiesToEven),
+ // (1 + 1e-106) + (1e-106 + 0) = (1 + 1e-105)
+ std::make_tuple(0x3ff0000000000000ull, 0x3950000000000000ull,
+ 0x3950000000000000ull, 0, 0x3ff0000000000000ull,
+ 0x3960000000000000ull, APFloat::rmNearestTiesToEven),
+ // (1 + 0) + (epsilon + 0) = (1 + epsilon)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x0000000000000001ull, 0,
+ 0x3ff0000000000000ull, 0x0000000000000001ull,
+ APFloat::rmNearestTiesToEven),
+ // TODO: change 0xf950000000000000 to 0xf940000000000000, when
+ // semPPCDoubleDoubleLegacy is gone.
+ // (DBL_MAX - 1 << (1023 - 105)) + (1 << (1023 - 53) + 0) = DBL_MAX +
+ // 1.11111... << (1023 - 52)
+ std::make_tuple(0x7fefffffffffffffull, 0xf950000000000000ull,
+ 0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
+ 0x7c8ffffffffffffeull, APFloat::rmNearestTiesToEven),
+ // TODO: change 0xf950000000000000 to 0xf940000000000000, when
+ // semPPCDoubleDoubleLegacy is gone.
+ // (1 << (1023 - 53) + 0) + (DBL_MAX - 1 << (1023 - 105)) = DBL_MAX +
+ // 1.11111... << (1023 - 52)
+ std::make_tuple(0x7c90000000000000ull, 0, 0x7fefffffffffffffull,
+ 0xf950000000000000ull, 0x7fefffffffffffffull,
+ 0x7c8ffffffffffffeull, APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp;
+
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.add(A2, RM);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A2.add(A1, RM);
+
+ EXPECT_EQ(Expected[0], A2.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ EXPECT_EQ(Expected[1], A2.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) + ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ }
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleSubtract) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, APFloat::roundingMode>;
+ DataType Data[] = {
+ // (1 + 0) - (-1e-105 + 0) = (1 + 1e-105)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0xb960000000000000ull, 0,
+ 0x3ff0000000000000ull, 0x3960000000000000ull,
+ APFloat::rmNearestTiesToEven),
+ // (1 + 0) - (-1e-106 + 0) = (1 + 1e-106)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0xb950000000000000ull, 0,
+ 0x3ff0000000000000ull, 0x3950000000000000ull,
+ APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.subtract(A2, RM);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+ Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) - ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+ Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleMultiplySpecial) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t,
+ APFloat::fltCategory, APFloat::roundingMode>;
+ DataType Data[] = {
+ // fcNaN * fcNaN = fcNaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0,
+ APFloat::fcNaN, APFloat::rmNearestTiesToEven),
+ // fcNaN * fcZero = fcNaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0, 0, APFloat::fcNaN,
+ APFloat::rmNearestTiesToEven),
+ // fcNaN * fcInfinity = fcNaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff0000000000000ull, 0,
+ APFloat::fcNaN, APFloat::rmNearestTiesToEven),
+ // fcNaN * fcNormal = fcNaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::fcNaN, APFloat::rmNearestTiesToEven),
+ // fcInfinity * fcInfinity = fcInfinity
+ std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0,
+ APFloat::fcInfinity, APFloat::rmNearestTiesToEven),
+ // fcInfinity * fcZero = fcNaN
+ std::make_tuple(0x7ff0000000000000ull, 0, 0, 0, APFloat::fcNaN,
+ APFloat::rmNearestTiesToEven),
+ // fcInfinity * fcNormal = fcInfinity
+ std::make_tuple(0x7ff0000000000000ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::fcInfinity, APFloat::rmNearestTiesToEven),
+ // fcZero * fcZero = fcZero
+ std::make_tuple(0, 0, 0, 0, APFloat::fcZero,
+ APFloat::rmNearestTiesToEven),
+ // fcZero * fcNormal = fcZero
+ std::make_tuple(0, 0, 0x3ff0000000000000ull, 0, APFloat::fcZero,
+ APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2];
+ APFloat::fltCategory Expected;
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected, RM) = Tp;
+
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.multiply(A2, RM);
+
+ EXPECT_EQ(Expected, A1.getCategory())
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A2.multiply(A1, RM);
+
+ EXPECT_EQ(Expected, A2.getCategory())
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ }
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleMultiply) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, APFloat::roundingMode>;
+ DataType Data[] = {
+ // 1/3 * 3 = 1.0
+ std::make_tuple(0x3fd5555555555555ull, 0x3c75555555555556ull,
+ 0x4008000000000000ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::rmNearestTiesToEven),
+ // (1 + epsilon) * (1 + 0) = fcZero
+ std::make_tuple(0x3ff0000000000000ull, 0x0000000000000001ull,
+ 0x3ff0000000000000ull, 0, 0x3ff0000000000000ull,
+ 0x0000000000000001ull, APFloat::rmNearestTiesToEven),
+ // (1 + epsilon) * (1 + epsilon) = 1 + 2 * epsilon
+ std::make_tuple(0x3ff0000000000000ull, 0x0000000000000001ull,
+ 0x3ff0000000000000ull, 0x0000000000000001ull,
+ 0x3ff0000000000000ull, 0x0000000000000002ull,
+ APFloat::rmNearestTiesToEven),
+ // -(1 + epsilon) * (1 + epsilon) = -1
+ std::make_tuple(0xbff0000000000000ull, 0x0000000000000001ull,
+ 0x3ff0000000000000ull, 0x0000000000000001ull,
+ 0xbff0000000000000ull, 0, APFloat::rmNearestTiesToEven),
+ // (0.5 + 0) * (1 + 2 * epsilon) = 0.5 + epsilon
+ std::make_tuple(0x3fe0000000000000ull, 0, 0x3ff0000000000000ull,
+ 0x0000000000000002ull, 0x3fe0000000000000ull,
+ 0x0000000000000001ull, APFloat::rmNearestTiesToEven),
+ // (0.5 + 0) * (1 + epsilon) = 0.5
+ std::make_tuple(0x3fe0000000000000ull, 0, 0x3ff0000000000000ull,
+ 0x0000000000000001ull, 0x3fe0000000000000ull, 0,
+ APFloat::rmNearestTiesToEven),
+ // __LDBL_MAX__ * (1 + 1 << 106) = inf
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x3ff0000000000000ull, 0x3950000000000000ull,
+ 0x7ff0000000000000ull, 0, APFloat::rmNearestTiesToEven),
+ // __LDBL_MAX__ * (1 + 1 << 107) > __LDBL_MAX__, but not inf, yes =_=|||
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x3ff0000000000000ull, 0x3940000000000000ull,
+ 0x7fefffffffffffffull, 0x7c8fffffffffffffull,
+ APFloat::rmNearestTiesToEven),
+ // __LDBL_MAX__ * (1 + 1 << 108) = __LDBL_MAX__
+ std::make_tuple(0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ 0x3ff0000000000000ull, 0x3930000000000000ull,
+ 0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp;
+
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.multiply(A2, RM);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+ {
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A2.multiply(A1, RM);
+
+ EXPECT_EQ(Expected[0], A2.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ EXPECT_EQ(Expected[1], A2.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) * ({2:x} + {3:x})", Op2[0], Op2[1],
+ Op1[0], Op1[1])
+ .str();
+ }
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleDivide) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, APFloat::roundingMode>;
+ // TODO: Only a sanity check for now. Add more edge cases when the
+ // double-double algorithm is implemented.
+ DataType Data[] = {
+ // 1 / 3 = 1/3
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x4008000000000000ull, 0,
+ 0x3fd5555555555555ull, 0x3c75555555555556ull,
+ APFloat::rmNearestTiesToEven),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ APFloat::roundingMode RM;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1], RM) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.divide(A2, RM);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("({0:x} + {1:x}) / ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+ Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("({0:x} + {1:x}) / ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+ Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleRemainder) {
+ using DataType =
+ std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>;
+ DataType Data[] = {
+ // remainder(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
+ std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull,
+ 0x3ff4000000000000ull, 0x3ca4000000000000ull,
+ 0x3fe0000000000000ull, 0x3c90000000000000ull),
+ // remainder(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (-0.5 - 0.5 << 53)
+ std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull,
+ 0x3ffc000000000000ull, 0x3cac000000000000ull,
+ 0xbfe0000000000000ull, 0xbc90000000000000ull),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1]) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.remainder(A2);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("remainder({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("remainder(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0],
+ Op1[1], Op2[0], Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleMod) {
+ using DataType =
+ std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, uint64_t, uint64_t>;
+ DataType Data[] = {
+ // mod(3.0 + 3.0 << 53, 1.25 + 1.25 << 53) = (0.5 + 0.5 << 53)
+ std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull,
+ 0x3ff4000000000000ull, 0x3ca4000000000000ull,
+ 0x3fe0000000000000ull, 0x3c90000000000000ull),
+ // mod(3.0 + 3.0 << 53, 1.75 + 1.75 << 53) = (1.25 + 1.25 << 53)
+ // 0xbc98000000000000 doesn't seem right, but it's what we currently have.
+ // TODO: investigate
+ std::make_tuple(0x4008000000000000ull, 0x3cb8000000000000ull,
+ 0x3ffc000000000000ull, 0x3cac000000000000ull,
+ 0x3ff4000000000001ull, 0xbc98000000000000ull),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2], Expected[2];
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected[0], Expected[1]) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ A1.mod(A2);
+
+ EXPECT_EQ(Expected[0], A1.bitcastToAPInt().getRawData()[0])
+ << formatv("fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ EXPECT_EQ(Expected[1], A1.bitcastToAPInt().getRawData()[1])
+ << formatv("fmod(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleFMA) {
+ // Sanity check for now.
+ APFloat A(APFloat::PPCDoubleDouble(), "2");
+ A.fusedMultiplyAdd(APFloat(APFloat::PPCDoubleDouble(), "3"),
+ APFloat(APFloat::PPCDoubleDouble(), "4"),
+ APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(APFloat::cmpEqual,
+ APFloat(APFloat::PPCDoubleDouble(), "10").compare(A));
+}
+
+TEST(APFloatTest, PPCDoubleDoubleRoundToIntegral) {
+ {
+ APFloat A(APFloat::PPCDoubleDouble(), "1.5");
+ A.roundToIntegral(APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(APFloat::cmpEqual,
+ APFloat(APFloat::PPCDoubleDouble(), "2").compare(A));
+ }
+ {
+ APFloat A(APFloat::PPCDoubleDouble(), "2.5");
+ A.roundToIntegral(APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(APFloat::cmpEqual,
+ APFloat(APFloat::PPCDoubleDouble(), "2").compare(A));
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleCompare) {
+ using DataType =
+ std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, APFloat::cmpResult>;
+
+ DataType Data[] = {
+ // (1 + 0) = (1 + 0)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::cmpEqual),
+ // (1 + 0) < (1.00...1 + 0)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, 0,
+ APFloat::cmpLessThan),
+ // (1.00...1 + 0) > (1 + 0)
+ std::make_tuple(0x3ff0000000000001ull, 0, 0x3ff0000000000000ull, 0,
+ APFloat::cmpGreaterThan),
+ // (1 + 0) < (1 + epsilon)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull,
+ 0x0000000000000001ull, APFloat::cmpLessThan),
+ // NaN != NaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0,
+ APFloat::cmpUnordered),
+ // (1 + 0) != NaN
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x7ff8000000000000ull, 0,
+ APFloat::cmpUnordered),
+ // Inf = Inf
+ std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0,
+ APFloat::cmpEqual),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2];
+ APFloat::cmpResult Expected;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ EXPECT_EQ(Expected, A1.compare(A2))
+ << formatv("compare(({0:x} + {1:x}), ({2:x} + {3:x}))", Op1[0], Op1[1],
+ Op2[0], Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleBitwiseIsEqual) {
+ using DataType = std::tuple<uint64_t, uint64_t, uint64_t, uint64_t, bool>;
+
+ DataType Data[] = {
+ // (1 + 0) = (1 + 0)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000000ull, 0, true),
+ // (1 + 0) != (1.00...1 + 0)
+ std::make_tuple(0x3ff0000000000000ull, 0, 0x3ff0000000000001ull, 0,
+ false),
+ // NaN = NaN
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull, 0, true),
+ // NaN != NaN with a different bit pattern
+ std::make_tuple(0x7ff8000000000000ull, 0, 0x7ff8000000000000ull,
+ 0x3ff0000000000000ull, false),
+ // Inf = Inf
+ std::make_tuple(0x7ff0000000000000ull, 0, 0x7ff0000000000000ull, 0, true),
+ };
+
+ for (auto Tp : Data) {
+ uint64_t Op1[2], Op2[2];
+ bool Expected;
+ std::tie(Op1[0], Op1[1], Op2[0], Op2[1], Expected) = Tp;
+
+ APFloat A1(APFloat::PPCDoubleDouble(), APInt(128, 2, Op1));
+ APFloat A2(APFloat::PPCDoubleDouble(), APInt(128, 2, Op2));
+ EXPECT_EQ(Expected, A1.bitwiseIsEqual(A2))
+ << formatv("({0:x} + {1:x}) = ({2:x} + {3:x})", Op1[0], Op1[1], Op2[0],
+ Op2[1])
+ .str();
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleHashValue) {
+ uint64_t Data1[] = {0x3ff0000000000001ull, 0x0000000000000001ull};
+ uint64_t Data2[] = {0x3ff0000000000001ull, 0};
+ // The hash values are *hopefully* different.
+ EXPECT_NE(
+ hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data1))),
+ hash_value(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data2))));
+}
+
+TEST(APFloatTest, PPCDoubleDoubleChangeSign) {
+ uint64_t Data[] = {
+ 0x400f000000000000ull, 0xbcb0000000000000ull,
+ };
+ APFloat Float(APFloat::PPCDoubleDouble(), APInt(128, 2, Data));
+ {
+ APFloat Actual =
+ APFloat::copySign(Float, APFloat(APFloat::IEEEdouble(), "1"));
+ EXPECT_EQ(0x400f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0xbcb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]);
+ }
+ {
+ APFloat Actual =
+ APFloat::copySign(Float, APFloat(APFloat::IEEEdouble(), "-1"));
+ EXPECT_EQ(0xc00f000000000000ull, Actual.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x3cb0000000000000ull, Actual.bitcastToAPInt().getRawData()[1]);
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleFactories) {
+ {
+ uint64_t Data[] = {
+ 0, 0,
+ };
+ EXPECT_EQ(APInt(128, 2, Data),
+ APFloat::getZero(APFloat::PPCDoubleDouble()).bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0x7fefffffffffffffull, 0x7c8ffffffffffffeull,
+ };
+ EXPECT_EQ(APInt(128, 2, Data),
+ APFloat::getLargest(APFloat::PPCDoubleDouble()).bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0x0000000000000001ull, 0,
+ };
+ EXPECT_EQ(
+ APInt(128, 2, Data),
+ APFloat::getSmallest(APFloat::PPCDoubleDouble()).bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {0x0360000000000000ull, 0};
+ EXPECT_EQ(APInt(128, 2, Data),
+ APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble())
+ .bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0x8000000000000000ull, 0x0000000000000000ull,
+ };
+ EXPECT_EQ(
+ APInt(128, 2, Data),
+ APFloat::getZero(APFloat::PPCDoubleDouble(), true).bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0xffefffffffffffffull, 0xfc8ffffffffffffeull,
+ };
+ EXPECT_EQ(
+ APInt(128, 2, Data),
+ APFloat::getLargest(APFloat::PPCDoubleDouble(), true).bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0x8000000000000001ull, 0x0000000000000000ull,
+ };
+ EXPECT_EQ(APInt(128, 2, Data),
+ APFloat::getSmallest(APFloat::PPCDoubleDouble(), true)
+ .bitcastToAPInt());
+ }
+ {
+ uint64_t Data[] = {
+ 0x8360000000000000ull, 0x0000000000000000ull,
+ };
+ EXPECT_EQ(APInt(128, 2, Data),
+ APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble(), true)
+ .bitcastToAPInt());
+ }
+ EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isSmallest());
+ EXPECT_TRUE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isLargest());
+}
+
+TEST(APFloatTest, PPCDoubleDoubleIsDenormal) {
+ EXPECT_TRUE(APFloat::getSmallest(APFloat::PPCDoubleDouble()).isDenormal());
+ EXPECT_FALSE(APFloat::getLargest(APFloat::PPCDoubleDouble()).isDenormal());
+ EXPECT_FALSE(
+ APFloat::getSmallestNormalized(APFloat::PPCDoubleDouble()).isDenormal());
+ {
+ // (4 + 3) is not normalized
+ uint64_t Data[] = {
+ 0x4010000000000000ull, 0x4008000000000000ull,
+ };
+ EXPECT_TRUE(
+ APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Data)).isDenormal());
+ }
+}
+
+TEST(APFloatTest, PPCDoubleDoubleScalbn) {
+ // 3.0 + 3.0 << 53
+ uint64_t Input[] = {
+ 0x4008000000000000ull, 0x3cb8000000000000ull,
+ };
+ APFloat Result =
+ scalbn(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), 1,
+ APFloat::rmNearestTiesToEven);
+ // 6.0 + 6.0 << 53
+ EXPECT_EQ(0x4018000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x3cc8000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
+}
+
+TEST(APFloatTest, PPCDoubleDoubleFrexp) {
+ // 3.0 + 3.0 << 53
+ uint64_t Input[] = {
+ 0x4008000000000000ull, 0x3cb8000000000000ull,
+ };
+ int Exp;
+ // 0.75 + 0.75 << 53
+ APFloat Result =
+ frexp(APFloat(APFloat::PPCDoubleDouble(), APInt(128, 2, Input)), Exp,
+ APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(2, Exp);
+ EXPECT_EQ(0x3fe8000000000000ull, Result.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x3c98000000000000ull, Result.bitcastToAPInt().getRawData()[1]);
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/APIntTest.cpp b/src/llvm-project/llvm/unittests/ADT/APIntTest.cpp
new file mode 100644
index 0000000..8b876f3
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/APIntTest.cpp
@@ -0,0 +1,2470 @@
+//===- llvm/unittest/ADT/APInt.cpp - APInt unit tests ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "gtest/gtest.h"
+#include <array>
+
+using namespace llvm;
+
+namespace {
+
+TEST(APIntTest, ValueInit) {
+ APInt Zero = APInt();
+ EXPECT_TRUE(!Zero);
+ EXPECT_TRUE(!Zero.zext(64));
+ EXPECT_TRUE(!Zero.sext(64));
+}
+
+// Test that APInt shift left works when bitwidth > 64 and shiftamt == 0
+TEST(APIntTest, ShiftLeftByZero) {
+ APInt One = APInt::getNullValue(65) + 1;
+ APInt Shl = One.shl(0);
+ EXPECT_TRUE(Shl[0]);
+ EXPECT_FALSE(Shl[1]);
+}
+
+TEST(APIntTest, i64_ArithmeticRightShiftNegative) {
+ const APInt neg_one(64, static_cast<uint64_t>(-1), true);
+ EXPECT_EQ(neg_one, neg_one.ashr(7));
+}
+
+TEST(APIntTest, i128_NegativeCount) {
+ APInt Minus3(128, static_cast<uint64_t>(-3), true);
+ EXPECT_EQ(126u, Minus3.countLeadingOnes());
+ EXPECT_EQ(-3, Minus3.getSExtValue());
+
+ APInt Minus1(128, static_cast<uint64_t>(-1), true);
+ EXPECT_EQ(0u, Minus1.countLeadingZeros());
+ EXPECT_EQ(128u, Minus1.countLeadingOnes());
+ EXPECT_EQ(128u, Minus1.getActiveBits());
+ EXPECT_EQ(0u, Minus1.countTrailingZeros());
+ EXPECT_EQ(128u, Minus1.countTrailingOnes());
+ EXPECT_EQ(128u, Minus1.countPopulation());
+ EXPECT_EQ(-1, Minus1.getSExtValue());
+}
+
+TEST(APIntTest, i33_Count) {
+ APInt i33minus2(33, static_cast<uint64_t>(-2), true);
+ EXPECT_EQ(0u, i33minus2.countLeadingZeros());
+ EXPECT_EQ(32u, i33minus2.countLeadingOnes());
+ EXPECT_EQ(33u, i33minus2.getActiveBits());
+ EXPECT_EQ(1u, i33minus2.countTrailingZeros());
+ EXPECT_EQ(32u, i33minus2.countPopulation());
+ EXPECT_EQ(-2, i33minus2.getSExtValue());
+ EXPECT_EQ(((uint64_t)-2)&((1ull<<33) -1), i33minus2.getZExtValue());
+}
+
+TEST(APIntTest, i61_Count) {
+ APInt i61(61, 1 << 15);
+ EXPECT_EQ(45u, i61.countLeadingZeros());
+ EXPECT_EQ(0u, i61.countLeadingOnes());
+ EXPECT_EQ(16u, i61.getActiveBits());
+ EXPECT_EQ(15u, i61.countTrailingZeros());
+ EXPECT_EQ(1u, i61.countPopulation());
+ EXPECT_EQ(static_cast<int64_t>(1 << 15), i61.getSExtValue());
+ EXPECT_EQ(static_cast<uint64_t>(1 << 15), i61.getZExtValue());
+
+ i61.setBits(8, 19);
+ EXPECT_EQ(42u, i61.countLeadingZeros());
+ EXPECT_EQ(0u, i61.countLeadingOnes());
+ EXPECT_EQ(19u, i61.getActiveBits());
+ EXPECT_EQ(8u, i61.countTrailingZeros());
+ EXPECT_EQ(11u, i61.countPopulation());
+ EXPECT_EQ(static_cast<int64_t>((1 << 19) - (1 << 8)), i61.getSExtValue());
+ EXPECT_EQ(static_cast<uint64_t>((1 << 19) - (1 << 8)), i61.getZExtValue());
+}
+
+TEST(APIntTest, i65_Count) {
+ APInt i65(65, 0, true);
+ EXPECT_EQ(65u, i65.countLeadingZeros());
+ EXPECT_EQ(0u, i65.countLeadingOnes());
+ EXPECT_EQ(0u, i65.getActiveBits());
+ EXPECT_EQ(1u, i65.getActiveWords());
+ EXPECT_EQ(65u, i65.countTrailingZeros());
+ EXPECT_EQ(0u, i65.countPopulation());
+
+ APInt i65minus(65, 0, true);
+ i65minus.setBit(64);
+ EXPECT_EQ(0u, i65minus.countLeadingZeros());
+ EXPECT_EQ(1u, i65minus.countLeadingOnes());
+ EXPECT_EQ(65u, i65minus.getActiveBits());
+ EXPECT_EQ(64u, i65minus.countTrailingZeros());
+ EXPECT_EQ(1u, i65minus.countPopulation());
+}
+
+TEST(APIntTest, i128_PositiveCount) {
+ APInt u128max = APInt::getAllOnesValue(128);
+ EXPECT_EQ(128u, u128max.countLeadingOnes());
+ EXPECT_EQ(0u, u128max.countLeadingZeros());
+ EXPECT_EQ(128u, u128max.getActiveBits());
+ EXPECT_EQ(0u, u128max.countTrailingZeros());
+ EXPECT_EQ(128u, u128max.countTrailingOnes());
+ EXPECT_EQ(128u, u128max.countPopulation());
+
+ APInt u64max(128, static_cast<uint64_t>(-1), false);
+ EXPECT_EQ(64u, u64max.countLeadingZeros());
+ EXPECT_EQ(0u, u64max.countLeadingOnes());
+ EXPECT_EQ(64u, u64max.getActiveBits());
+ EXPECT_EQ(0u, u64max.countTrailingZeros());
+ EXPECT_EQ(64u, u64max.countTrailingOnes());
+ EXPECT_EQ(64u, u64max.countPopulation());
+ EXPECT_EQ((uint64_t)~0ull, u64max.getZExtValue());
+
+ APInt zero(128, 0, true);
+ EXPECT_EQ(128u, zero.countLeadingZeros());
+ EXPECT_EQ(0u, zero.countLeadingOnes());
+ EXPECT_EQ(0u, zero.getActiveBits());
+ EXPECT_EQ(128u, zero.countTrailingZeros());
+ EXPECT_EQ(0u, zero.countTrailingOnes());
+ EXPECT_EQ(0u, zero.countPopulation());
+ EXPECT_EQ(0u, zero.getSExtValue());
+ EXPECT_EQ(0u, zero.getZExtValue());
+
+ APInt one(128, 1, true);
+ EXPECT_EQ(127u, one.countLeadingZeros());
+ EXPECT_EQ(0u, one.countLeadingOnes());
+ EXPECT_EQ(1u, one.getActiveBits());
+ EXPECT_EQ(0u, one.countTrailingZeros());
+ EXPECT_EQ(1u, one.countTrailingOnes());
+ EXPECT_EQ(1u, one.countPopulation());
+ EXPECT_EQ(1, one.getSExtValue());
+ EXPECT_EQ(1u, one.getZExtValue());
+
+ APInt s128(128, 2, true);
+ EXPECT_EQ(126u, s128.countLeadingZeros());
+ EXPECT_EQ(0u, s128.countLeadingOnes());
+ EXPECT_EQ(2u, s128.getActiveBits());
+ EXPECT_EQ(1u, s128.countTrailingZeros());
+ EXPECT_EQ(0u, s128.countTrailingOnes());
+ EXPECT_EQ(1u, s128.countPopulation());
+ EXPECT_EQ(2, s128.getSExtValue());
+ EXPECT_EQ(2u, s128.getZExtValue());
+
+ // NOP Test
+ s128.setBits(42, 42);
+ EXPECT_EQ(126u, s128.countLeadingZeros());
+ EXPECT_EQ(0u, s128.countLeadingOnes());
+ EXPECT_EQ(2u, s128.getActiveBits());
+ EXPECT_EQ(1u, s128.countTrailingZeros());
+ EXPECT_EQ(0u, s128.countTrailingOnes());
+ EXPECT_EQ(1u, s128.countPopulation());
+ EXPECT_EQ(2, s128.getSExtValue());
+ EXPECT_EQ(2u, s128.getZExtValue());
+
+ s128.setBits(3, 32);
+ EXPECT_EQ(96u, s128.countLeadingZeros());
+ EXPECT_EQ(0u, s128.countLeadingOnes());
+ EXPECT_EQ(32u, s128.getActiveBits());
+ EXPECT_EQ(33u, s128.getMinSignedBits());
+ EXPECT_EQ(1u, s128.countTrailingZeros());
+ EXPECT_EQ(0u, s128.countTrailingOnes());
+ EXPECT_EQ(30u, s128.countPopulation());
+ EXPECT_EQ(static_cast<uint32_t>((~0u << 3) | 2), s128.getZExtValue());
+
+ s128.setBits(62, 128);
+ EXPECT_EQ(0u, s128.countLeadingZeros());
+ EXPECT_EQ(66u, s128.countLeadingOnes());
+ EXPECT_EQ(128u, s128.getActiveBits());
+ EXPECT_EQ(63u, s128.getMinSignedBits());
+ EXPECT_EQ(1u, s128.countTrailingZeros());
+ EXPECT_EQ(0u, s128.countTrailingOnes());
+ EXPECT_EQ(96u, s128.countPopulation());
+ EXPECT_EQ(static_cast<int64_t>((3ull << 62) |
+ static_cast<uint32_t>((~0u << 3) | 2)),
+ s128.getSExtValue());
+}
+
+TEST(APIntTest, i256) {
+ APInt s256(256, 15, true);
+ EXPECT_EQ(252u, s256.countLeadingZeros());
+ EXPECT_EQ(0u, s256.countLeadingOnes());
+ EXPECT_EQ(4u, s256.getActiveBits());
+ EXPECT_EQ(0u, s256.countTrailingZeros());
+ EXPECT_EQ(4u, s256.countTrailingOnes());
+ EXPECT_EQ(4u, s256.countPopulation());
+ EXPECT_EQ(15, s256.getSExtValue());
+ EXPECT_EQ(15u, s256.getZExtValue());
+
+ s256.setBits(62, 66);
+ EXPECT_EQ(190u, s256.countLeadingZeros());
+ EXPECT_EQ(0u, s256.countLeadingOnes());
+ EXPECT_EQ(66u, s256.getActiveBits());
+ EXPECT_EQ(67u, s256.getMinSignedBits());
+ EXPECT_EQ(0u, s256.countTrailingZeros());
+ EXPECT_EQ(4u, s256.countTrailingOnes());
+ EXPECT_EQ(8u, s256.countPopulation());
+
+ s256.setBits(60, 256);
+ EXPECT_EQ(0u, s256.countLeadingZeros());
+ EXPECT_EQ(196u, s256.countLeadingOnes());
+ EXPECT_EQ(256u, s256.getActiveBits());
+ EXPECT_EQ(61u, s256.getMinSignedBits());
+ EXPECT_EQ(0u, s256.countTrailingZeros());
+ EXPECT_EQ(4u, s256.countTrailingOnes());
+ EXPECT_EQ(200u, s256.countPopulation());
+ EXPECT_EQ(static_cast<int64_t>((~0ull << 60) | 15), s256.getSExtValue());
+}
+
+TEST(APIntTest, i1) {
+ const APInt neg_two(1, static_cast<uint64_t>(-2), true);
+ const APInt neg_one(1, static_cast<uint64_t>(-1), true);
+ const APInt zero(1, 0);
+ const APInt one(1, 1);
+ const APInt two(1, 2);
+
+ EXPECT_EQ(0, neg_two.getSExtValue());
+ EXPECT_EQ(-1, neg_one.getSExtValue());
+ EXPECT_EQ(1u, neg_one.getZExtValue());
+ EXPECT_EQ(0u, zero.getZExtValue());
+ EXPECT_EQ(-1, one.getSExtValue());
+ EXPECT_EQ(1u, one.getZExtValue());
+ EXPECT_EQ(0u, two.getZExtValue());
+ EXPECT_EQ(0, two.getSExtValue());
+
+ // Basic equalities for 1-bit values.
+ EXPECT_EQ(zero, two);
+ EXPECT_EQ(zero, neg_two);
+ EXPECT_EQ(one, neg_one);
+ EXPECT_EQ(two, neg_two);
+
+ // Min/max signed values.
+ EXPECT_TRUE(zero.isMaxSignedValue());
+ EXPECT_FALSE(one.isMaxSignedValue());
+ EXPECT_FALSE(zero.isMinSignedValue());
+ EXPECT_TRUE(one.isMinSignedValue());
+
+ // Additions.
+ EXPECT_EQ(two, one + one);
+ EXPECT_EQ(zero, neg_one + one);
+ EXPECT_EQ(neg_two, neg_one + neg_one);
+
+ // Subtractions.
+ EXPECT_EQ(neg_two, neg_one - one);
+ EXPECT_EQ(two, one - neg_one);
+ EXPECT_EQ(zero, one - one);
+
+ // And
+ EXPECT_EQ(zero, zero & zero);
+ EXPECT_EQ(zero, one & zero);
+ EXPECT_EQ(zero, zero & one);
+ EXPECT_EQ(one, one & one);
+ EXPECT_EQ(zero, zero & zero);
+ EXPECT_EQ(zero, neg_one & zero);
+ EXPECT_EQ(zero, zero & neg_one);
+ EXPECT_EQ(neg_one, neg_one & neg_one);
+
+ // Or
+ EXPECT_EQ(zero, zero | zero);
+ EXPECT_EQ(one, one | zero);
+ EXPECT_EQ(one, zero | one);
+ EXPECT_EQ(one, one | one);
+ EXPECT_EQ(zero, zero | zero);
+ EXPECT_EQ(neg_one, neg_one | zero);
+ EXPECT_EQ(neg_one, zero | neg_one);
+ EXPECT_EQ(neg_one, neg_one | neg_one);
+
+ // Xor
+ EXPECT_EQ(zero, zero ^ zero);
+ EXPECT_EQ(one, one ^ zero);
+ EXPECT_EQ(one, zero ^ one);
+ EXPECT_EQ(zero, one ^ one);
+ EXPECT_EQ(zero, zero ^ zero);
+ EXPECT_EQ(neg_one, neg_one ^ zero);
+ EXPECT_EQ(neg_one, zero ^ neg_one);
+ EXPECT_EQ(zero, neg_one ^ neg_one);
+
+ // Shifts.
+ EXPECT_EQ(zero, one << one);
+ EXPECT_EQ(one, one << zero);
+ EXPECT_EQ(zero, one.shl(1));
+ EXPECT_EQ(one, one.shl(0));
+ EXPECT_EQ(zero, one.lshr(1));
+ EXPECT_EQ(one, one.ashr(1));
+
+ // Rotates.
+ EXPECT_EQ(one, one.rotl(0));
+ EXPECT_EQ(one, one.rotl(1));
+ EXPECT_EQ(one, one.rotr(0));
+ EXPECT_EQ(one, one.rotr(1));
+
+ // Multiplies.
+ EXPECT_EQ(neg_one, neg_one * one);
+ EXPECT_EQ(neg_one, one * neg_one);
+ EXPECT_EQ(one, neg_one * neg_one);
+ EXPECT_EQ(one, one * one);
+
+ // Divides.
+ EXPECT_EQ(neg_one, one.sdiv(neg_one));
+ EXPECT_EQ(neg_one, neg_one.sdiv(one));
+ EXPECT_EQ(one, neg_one.sdiv(neg_one));
+ EXPECT_EQ(one, one.sdiv(one));
+
+ EXPECT_EQ(neg_one, one.udiv(neg_one));
+ EXPECT_EQ(neg_one, neg_one.udiv(one));
+ EXPECT_EQ(one, neg_one.udiv(neg_one));
+ EXPECT_EQ(one, one.udiv(one));
+
+ // Remainders.
+ EXPECT_EQ(zero, neg_one.srem(one));
+ EXPECT_EQ(zero, neg_one.urem(one));
+ EXPECT_EQ(zero, one.srem(neg_one));
+
+ // sdivrem
+ {
+ APInt q(8, 0);
+ APInt r(8, 0);
+ APInt one(8, 1);
+ APInt two(8, 2);
+ APInt nine(8, 9);
+ APInt four(8, 4);
+
+ EXPECT_EQ(nine.srem(two), one);
+ EXPECT_EQ(nine.srem(-two), one);
+ EXPECT_EQ((-nine).srem(two), -one);
+ EXPECT_EQ((-nine).srem(-two), -one);
+
+ APInt::sdivrem(nine, two, q, r);
+ EXPECT_EQ(four, q);
+ EXPECT_EQ(one, r);
+ APInt::sdivrem(-nine, two, q, r);
+ EXPECT_EQ(-four, q);
+ EXPECT_EQ(-one, r);
+ APInt::sdivrem(nine, -two, q, r);
+ EXPECT_EQ(-four, q);
+ EXPECT_EQ(one, r);
+ APInt::sdivrem(-nine, -two, q, r);
+ EXPECT_EQ(four, q);
+ EXPECT_EQ(-one, r);
+ }
+}
+
+TEST(APIntTest, compare) {
+ std::array<APInt, 5> testVals{{
+ APInt{16, 2},
+ APInt{16, 1},
+ APInt{16, 0},
+ APInt{16, (uint64_t)-1, true},
+ APInt{16, (uint64_t)-2, true},
+ }};
+
+ for (auto &arg1 : testVals)
+ for (auto &arg2 : testVals) {
+ auto uv1 = arg1.getZExtValue();
+ auto uv2 = arg2.getZExtValue();
+ auto sv1 = arg1.getSExtValue();
+ auto sv2 = arg2.getSExtValue();
+
+ EXPECT_EQ(uv1 < uv2, arg1.ult(arg2));
+ EXPECT_EQ(uv1 <= uv2, arg1.ule(arg2));
+ EXPECT_EQ(uv1 > uv2, arg1.ugt(arg2));
+ EXPECT_EQ(uv1 >= uv2, arg1.uge(arg2));
+
+ EXPECT_EQ(sv1 < sv2, arg1.slt(arg2));
+ EXPECT_EQ(sv1 <= sv2, arg1.sle(arg2));
+ EXPECT_EQ(sv1 > sv2, arg1.sgt(arg2));
+ EXPECT_EQ(sv1 >= sv2, arg1.sge(arg2));
+
+ EXPECT_EQ(uv1 < uv2, arg1.ult(uv2));
+ EXPECT_EQ(uv1 <= uv2, arg1.ule(uv2));
+ EXPECT_EQ(uv1 > uv2, arg1.ugt(uv2));
+ EXPECT_EQ(uv1 >= uv2, arg1.uge(uv2));
+
+ EXPECT_EQ(sv1 < sv2, arg1.slt(sv2));
+ EXPECT_EQ(sv1 <= sv2, arg1.sle(sv2));
+ EXPECT_EQ(sv1 > sv2, arg1.sgt(sv2));
+ EXPECT_EQ(sv1 >= sv2, arg1.sge(sv2));
+ }
+}
+
+TEST(APIntTest, compareWithRawIntegers) {
+ EXPECT_TRUE(!APInt(8, 1).uge(256));
+ EXPECT_TRUE(!APInt(8, 1).ugt(256));
+ EXPECT_TRUE( APInt(8, 1).ule(256));
+ EXPECT_TRUE( APInt(8, 1).ult(256));
+ EXPECT_TRUE(!APInt(8, 1).sge(256));
+ EXPECT_TRUE(!APInt(8, 1).sgt(256));
+ EXPECT_TRUE( APInt(8, 1).sle(256));
+ EXPECT_TRUE( APInt(8, 1).slt(256));
+ EXPECT_TRUE(!(APInt(8, 0) == 256));
+ EXPECT_TRUE( APInt(8, 0) != 256);
+ EXPECT_TRUE(!(APInt(8, 1) == 256));
+ EXPECT_TRUE( APInt(8, 1) != 256);
+
+ auto uint64max = UINT64_MAX;
+ auto int64max = INT64_MAX;
+ auto int64min = INT64_MIN;
+
+ auto u64 = APInt{128, uint64max};
+ auto s64 = APInt{128, static_cast<uint64_t>(int64max), true};
+ auto big = u64 + 1;
+
+ EXPECT_TRUE( u64.uge(uint64max));
+ EXPECT_TRUE(!u64.ugt(uint64max));
+ EXPECT_TRUE( u64.ule(uint64max));
+ EXPECT_TRUE(!u64.ult(uint64max));
+ EXPECT_TRUE( u64.sge(int64max));
+ EXPECT_TRUE( u64.sgt(int64max));
+ EXPECT_TRUE(!u64.sle(int64max));
+ EXPECT_TRUE(!u64.slt(int64max));
+ EXPECT_TRUE( u64.sge(int64min));
+ EXPECT_TRUE( u64.sgt(int64min));
+ EXPECT_TRUE(!u64.sle(int64min));
+ EXPECT_TRUE(!u64.slt(int64min));
+
+ EXPECT_TRUE(u64 == uint64max);
+ EXPECT_TRUE(u64 != int64max);
+ EXPECT_TRUE(u64 != int64min);
+
+ EXPECT_TRUE(!s64.uge(uint64max));
+ EXPECT_TRUE(!s64.ugt(uint64max));
+ EXPECT_TRUE( s64.ule(uint64max));
+ EXPECT_TRUE( s64.ult(uint64max));
+ EXPECT_TRUE( s64.sge(int64max));
+ EXPECT_TRUE(!s64.sgt(int64max));
+ EXPECT_TRUE( s64.sle(int64max));
+ EXPECT_TRUE(!s64.slt(int64max));
+ EXPECT_TRUE( s64.sge(int64min));
+ EXPECT_TRUE( s64.sgt(int64min));
+ EXPECT_TRUE(!s64.sle(int64min));
+ EXPECT_TRUE(!s64.slt(int64min));
+
+ EXPECT_TRUE(s64 != uint64max);
+ EXPECT_TRUE(s64 == int64max);
+ EXPECT_TRUE(s64 != int64min);
+
+ EXPECT_TRUE( big.uge(uint64max));
+ EXPECT_TRUE( big.ugt(uint64max));
+ EXPECT_TRUE(!big.ule(uint64max));
+ EXPECT_TRUE(!big.ult(uint64max));
+ EXPECT_TRUE( big.sge(int64max));
+ EXPECT_TRUE( big.sgt(int64max));
+ EXPECT_TRUE(!big.sle(int64max));
+ EXPECT_TRUE(!big.slt(int64max));
+ EXPECT_TRUE( big.sge(int64min));
+ EXPECT_TRUE( big.sgt(int64min));
+ EXPECT_TRUE(!big.sle(int64min));
+ EXPECT_TRUE(!big.slt(int64min));
+
+ EXPECT_TRUE(big != uint64max);
+ EXPECT_TRUE(big != int64max);
+ EXPECT_TRUE(big != int64min);
+}
+
+TEST(APIntTest, compareWithInt64Min) {
+ int64_t edge = INT64_MIN;
+ int64_t edgeP1 = edge + 1;
+ int64_t edgeM1 = INT64_MAX;
+ auto a = APInt{64, static_cast<uint64_t>(edge), true};
+
+ EXPECT_TRUE(!a.slt(edge));
+ EXPECT_TRUE( a.sle(edge));
+ EXPECT_TRUE(!a.sgt(edge));
+ EXPECT_TRUE( a.sge(edge));
+ EXPECT_TRUE( a.slt(edgeP1));
+ EXPECT_TRUE( a.sle(edgeP1));
+ EXPECT_TRUE(!a.sgt(edgeP1));
+ EXPECT_TRUE(!a.sge(edgeP1));
+ EXPECT_TRUE( a.slt(edgeM1));
+ EXPECT_TRUE( a.sle(edgeM1));
+ EXPECT_TRUE(!a.sgt(edgeM1));
+ EXPECT_TRUE(!a.sge(edgeM1));
+}
+
+TEST(APIntTest, compareWithHalfInt64Max) {
+ uint64_t edge = 0x4000000000000000;
+ uint64_t edgeP1 = edge + 1;
+ uint64_t edgeM1 = edge - 1;
+ auto a = APInt{64, edge};
+
+ EXPECT_TRUE(!a.ult(edge));
+ EXPECT_TRUE( a.ule(edge));
+ EXPECT_TRUE(!a.ugt(edge));
+ EXPECT_TRUE( a.uge(edge));
+ EXPECT_TRUE( a.ult(edgeP1));
+ EXPECT_TRUE( a.ule(edgeP1));
+ EXPECT_TRUE(!a.ugt(edgeP1));
+ EXPECT_TRUE(!a.uge(edgeP1));
+ EXPECT_TRUE(!a.ult(edgeM1));
+ EXPECT_TRUE(!a.ule(edgeM1));
+ EXPECT_TRUE( a.ugt(edgeM1));
+ EXPECT_TRUE( a.uge(edgeM1));
+
+ EXPECT_TRUE(!a.slt(edge));
+ EXPECT_TRUE( a.sle(edge));
+ EXPECT_TRUE(!a.sgt(edge));
+ EXPECT_TRUE( a.sge(edge));
+ EXPECT_TRUE( a.slt(edgeP1));
+ EXPECT_TRUE( a.sle(edgeP1));
+ EXPECT_TRUE(!a.sgt(edgeP1));
+ EXPECT_TRUE(!a.sge(edgeP1));
+ EXPECT_TRUE(!a.slt(edgeM1));
+ EXPECT_TRUE(!a.sle(edgeM1));
+ EXPECT_TRUE( a.sgt(edgeM1));
+ EXPECT_TRUE( a.sge(edgeM1));
+}
+
+TEST(APIntTest, compareLargeIntegers) {
+ // Make sure all the combinations of signed comparisons work with big ints.
+ auto One = APInt{128, static_cast<uint64_t>(1), true};
+ auto Two = APInt{128, static_cast<uint64_t>(2), true};
+ auto MinusOne = APInt{128, static_cast<uint64_t>(-1), true};
+ auto MinusTwo = APInt{128, static_cast<uint64_t>(-2), true};
+
+ EXPECT_TRUE(!One.slt(One));
+ EXPECT_TRUE(!Two.slt(One));
+ EXPECT_TRUE(MinusOne.slt(One));
+ EXPECT_TRUE(MinusTwo.slt(One));
+
+ EXPECT_TRUE(One.slt(Two));
+ EXPECT_TRUE(!Two.slt(Two));
+ EXPECT_TRUE(MinusOne.slt(Two));
+ EXPECT_TRUE(MinusTwo.slt(Two));
+
+ EXPECT_TRUE(!One.slt(MinusOne));
+ EXPECT_TRUE(!Two.slt(MinusOne));
+ EXPECT_TRUE(!MinusOne.slt(MinusOne));
+ EXPECT_TRUE(MinusTwo.slt(MinusOne));
+
+ EXPECT_TRUE(!One.slt(MinusTwo));
+ EXPECT_TRUE(!Two.slt(MinusTwo));
+ EXPECT_TRUE(!MinusOne.slt(MinusTwo));
+ EXPECT_TRUE(!MinusTwo.slt(MinusTwo));
+}
+
+TEST(APIntTest, binaryOpsWithRawIntegers) {
+ // Single word check.
+ uint64_t E1 = 0x2CA7F46BF6569915ULL;
+ APInt A1(64, E1);
+
+ EXPECT_EQ(A1 & E1, E1);
+ EXPECT_EQ(A1 & 0, 0);
+ EXPECT_EQ(A1 & 1, 1);
+ EXPECT_EQ(A1 & 5, 5);
+ EXPECT_EQ(A1 & UINT64_MAX, E1);
+
+ EXPECT_EQ(A1 | E1, E1);
+ EXPECT_EQ(A1 | 0, E1);
+ EXPECT_EQ(A1 | 1, E1);
+ EXPECT_EQ(A1 | 2, E1 | 2);
+ EXPECT_EQ(A1 | UINT64_MAX, UINT64_MAX);
+
+ EXPECT_EQ(A1 ^ E1, 0);
+ EXPECT_EQ(A1 ^ 0, E1);
+ EXPECT_EQ(A1 ^ 1, E1 ^ 1);
+ EXPECT_EQ(A1 ^ 7, E1 ^ 7);
+ EXPECT_EQ(A1 ^ UINT64_MAX, ~E1);
+
+ // Multiword check.
+ uint64_t N = 0xEB6EB136591CBA21ULL;
+ APInt::WordType E2[4] = {
+ N,
+ 0x7B9358BD6A33F10AULL,
+ 0x7E7FFA5EADD8846ULL,
+ 0x305F341CA00B613DULL
+ };
+ APInt A2(APInt::APINT_BITS_PER_WORD*4, E2);
+
+ EXPECT_EQ(A2 & N, N);
+ EXPECT_EQ(A2 & 0, 0);
+ EXPECT_EQ(A2 & 1, 1);
+ EXPECT_EQ(A2 & 5, 1);
+ EXPECT_EQ(A2 & UINT64_MAX, N);
+
+ EXPECT_EQ(A2 | N, A2);
+ EXPECT_EQ(A2 | 0, A2);
+ EXPECT_EQ(A2 | 1, A2);
+ EXPECT_EQ(A2 | 2, A2 + 2);
+ EXPECT_EQ(A2 | UINT64_MAX, A2 - N + UINT64_MAX);
+
+ EXPECT_EQ(A2 ^ N, A2 - N);
+ EXPECT_EQ(A2 ^ 0, A2);
+ EXPECT_EQ(A2 ^ 1, A2 - 1);
+ EXPECT_EQ(A2 ^ 7, A2 + 5);
+ EXPECT_EQ(A2 ^ UINT64_MAX, A2 - N + ~N);
+}
+
+TEST(APIntTest, rvalue_arithmetic) {
+ // Test all combinations of lvalue/rvalue lhs/rhs of add/sub
+
+ // Lamdba to return an APInt by value, but also provide the raw value of the
+ // allocated data.
+ auto getRValue = [](const char *HexString, uint64_t const *&RawData) {
+ APInt V(129, HexString, 16);
+ RawData = V.getRawData();
+ return V;
+ };
+
+ APInt One(129, "1", 16);
+ APInt Two(129, "2", 16);
+ APInt Three(129, "3", 16);
+ APInt MinusOne = -One;
+
+ const uint64_t *RawDataL = nullptr;
+ const uint64_t *RawDataR = nullptr;
+
+ {
+ // 1 + 1 = 2
+ APInt AddLL = One + One;
+ EXPECT_EQ(AddLL, Two);
+
+ APInt AddLR = One + getRValue("1", RawDataR);
+ EXPECT_EQ(AddLR, Two);
+ EXPECT_EQ(AddLR.getRawData(), RawDataR);
+
+ APInt AddRL = getRValue("1", RawDataL) + One;
+ EXPECT_EQ(AddRL, Two);
+ EXPECT_EQ(AddRL.getRawData(), RawDataL);
+
+ APInt AddRR = getRValue("1", RawDataL) + getRValue("1", RawDataR);
+ EXPECT_EQ(AddRR, Two);
+ EXPECT_EQ(AddRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt AddLK = One + 1;
+ EXPECT_EQ(AddLK, Two);
+
+ APInt AddKL = 1 + One;
+ EXPECT_EQ(AddKL, Two);
+
+ // RValue's and constants
+ APInt AddRK = getRValue("1", RawDataL) + 1;
+ EXPECT_EQ(AddRK, Two);
+ EXPECT_EQ(AddRK.getRawData(), RawDataL);
+
+ APInt AddKR = 1 + getRValue("1", RawDataR);
+ EXPECT_EQ(AddKR, Two);
+ EXPECT_EQ(AddKR.getRawData(), RawDataR);
+ }
+
+ {
+ // 0x0,FFFF...FFFF + 0x2 = 0x100...0001
+ APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
+ APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);
+
+ APInt AddLL = AllOnes + Two;
+ EXPECT_EQ(AddLL, HighOneLowOne);
+
+ APInt AddLR = AllOnes + getRValue("2", RawDataR);
+ EXPECT_EQ(AddLR, HighOneLowOne);
+ EXPECT_EQ(AddLR.getRawData(), RawDataR);
+
+ APInt AddRL = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + Two;
+ EXPECT_EQ(AddRL, HighOneLowOne);
+ EXPECT_EQ(AddRL.getRawData(), RawDataL);
+
+ APInt AddRR = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) +
+ getRValue("2", RawDataR);
+ EXPECT_EQ(AddRR, HighOneLowOne);
+ EXPECT_EQ(AddRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt AddLK = AllOnes + 2;
+ EXPECT_EQ(AddLK, HighOneLowOne);
+
+ APInt AddKL = 2 + AllOnes;
+ EXPECT_EQ(AddKL, HighOneLowOne);
+
+ // RValue's and constants
+ APInt AddRK = getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataL) + 2;
+ EXPECT_EQ(AddRK, HighOneLowOne);
+ EXPECT_EQ(AddRK.getRawData(), RawDataL);
+
+ APInt AddKR = 2 + getRValue("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+ EXPECT_EQ(AddKR, HighOneLowOne);
+ EXPECT_EQ(AddKR.getRawData(), RawDataR);
+ }
+
+ {
+ // 2 - 1 = 1
+ APInt SubLL = Two - One;
+ EXPECT_EQ(SubLL, One);
+
+ APInt SubLR = Two - getRValue("1", RawDataR);
+ EXPECT_EQ(SubLR, One);
+ EXPECT_EQ(SubLR.getRawData(), RawDataR);
+
+ APInt SubRL = getRValue("2", RawDataL) - One;
+ EXPECT_EQ(SubRL, One);
+ EXPECT_EQ(SubRL.getRawData(), RawDataL);
+
+ APInt SubRR = getRValue("2", RawDataL) - getRValue("1", RawDataR);
+ EXPECT_EQ(SubRR, One);
+ EXPECT_EQ(SubRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt SubLK = Two - 1;
+ EXPECT_EQ(SubLK, One);
+
+ APInt SubKL = 2 - One;
+ EXPECT_EQ(SubKL, One);
+
+ // RValue's and constants
+ APInt SubRK = getRValue("2", RawDataL) - 1;
+ EXPECT_EQ(SubRK, One);
+ EXPECT_EQ(SubRK.getRawData(), RawDataL);
+
+ APInt SubKR = 2 - getRValue("1", RawDataR);
+ EXPECT_EQ(SubKR, One);
+ EXPECT_EQ(SubKR.getRawData(), RawDataR);
+ }
+
+ {
+ // 0x100...0001 - 0x0,FFFF...FFFF = 0x2
+ APInt AllOnes(129, "0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16);
+ APInt HighOneLowOne(129, "100000000000000000000000000000001", 16);
+
+ APInt SubLL = HighOneLowOne - AllOnes;
+ EXPECT_EQ(SubLL, Two);
+
+ APInt SubLR = HighOneLowOne -
+ getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+ EXPECT_EQ(SubLR, Two);
+ EXPECT_EQ(SubLR.getRawData(), RawDataR);
+
+ APInt SubRL = getRValue("100000000000000000000000000000001", RawDataL) -
+ AllOnes;
+ EXPECT_EQ(SubRL, Two);
+ EXPECT_EQ(SubRL.getRawData(), RawDataL);
+
+ APInt SubRR = getRValue("100000000000000000000000000000001", RawDataL) -
+ getRValue("0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+ EXPECT_EQ(SubRR, Two);
+ EXPECT_EQ(SubRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF
+ APInt SubLK = HighOneLowOne - 2;
+ EXPECT_EQ(SubLK, AllOnes);
+
+ // 2 - (-1) = 3
+ APInt SubKL = 2 - MinusOne;
+ EXPECT_EQ(SubKL, Three);
+
+ // RValue's and constants
+ // 0x100...0001 - 0x2 = 0x0,FFFF...FFFF
+ APInt SubRK = getRValue("100000000000000000000000000000001", RawDataL) - 2;
+ EXPECT_EQ(SubRK, AllOnes);
+ EXPECT_EQ(SubRK.getRawData(), RawDataL);
+
+ APInt SubKR = 2 - getRValue("1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", RawDataR);
+ EXPECT_EQ(SubKR, Three);
+ EXPECT_EQ(SubKR.getRawData(), RawDataR);
+ }
+}
+
+TEST(APIntTest, rvalue_bitwise) {
+ // Test all combinations of lvalue/rvalue lhs/rhs of and/or/xor
+
+ // Lamdba to return an APInt by value, but also provide the raw value of the
+ // allocated data.
+ auto getRValue = [](const char *HexString, uint64_t const *&RawData) {
+ APInt V(129, HexString, 16);
+ RawData = V.getRawData();
+ return V;
+ };
+
+ APInt Ten(129, "A", 16);
+ APInt Twelve(129, "C", 16);
+
+ const uint64_t *RawDataL = nullptr;
+ const uint64_t *RawDataR = nullptr;
+
+ {
+ // 12 & 10 = 8
+ APInt AndLL = Ten & Twelve;
+ EXPECT_EQ(AndLL, 0x8);
+
+ APInt AndLR = Ten & getRValue("C", RawDataR);
+ EXPECT_EQ(AndLR, 0x8);
+ EXPECT_EQ(AndLR.getRawData(), RawDataR);
+
+ APInt AndRL = getRValue("A", RawDataL) & Twelve;
+ EXPECT_EQ(AndRL, 0x8);
+ EXPECT_EQ(AndRL.getRawData(), RawDataL);
+
+ APInt AndRR = getRValue("A", RawDataL) & getRValue("C", RawDataR);
+ EXPECT_EQ(AndRR, 0x8);
+ EXPECT_EQ(AndRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt AndLK = Ten & 0xc;
+ EXPECT_EQ(AndLK, 0x8);
+
+ APInt AndKL = 0xa & Twelve;
+ EXPECT_EQ(AndKL, 0x8);
+
+ // RValue's and constants
+ APInt AndRK = getRValue("A", RawDataL) & 0xc;
+ EXPECT_EQ(AndRK, 0x8);
+ EXPECT_EQ(AndRK.getRawData(), RawDataL);
+
+ APInt AndKR = 0xa & getRValue("C", RawDataR);
+ EXPECT_EQ(AndKR, 0x8);
+ EXPECT_EQ(AndKR.getRawData(), RawDataR);
+ }
+
+ {
+ // 12 | 10 = 14
+ APInt OrLL = Ten | Twelve;
+ EXPECT_EQ(OrLL, 0xe);
+
+ APInt OrLR = Ten | getRValue("C", RawDataR);
+ EXPECT_EQ(OrLR, 0xe);
+ EXPECT_EQ(OrLR.getRawData(), RawDataR);
+
+ APInt OrRL = getRValue("A", RawDataL) | Twelve;
+ EXPECT_EQ(OrRL, 0xe);
+ EXPECT_EQ(OrRL.getRawData(), RawDataL);
+
+ APInt OrRR = getRValue("A", RawDataL) | getRValue("C", RawDataR);
+ EXPECT_EQ(OrRR, 0xe);
+ EXPECT_EQ(OrRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt OrLK = Ten | 0xc;
+ EXPECT_EQ(OrLK, 0xe);
+
+ APInt OrKL = 0xa | Twelve;
+ EXPECT_EQ(OrKL, 0xe);
+
+ // RValue's and constants
+ APInt OrRK = getRValue("A", RawDataL) | 0xc;
+ EXPECT_EQ(OrRK, 0xe);
+ EXPECT_EQ(OrRK.getRawData(), RawDataL);
+
+ APInt OrKR = 0xa | getRValue("C", RawDataR);
+ EXPECT_EQ(OrKR, 0xe);
+ EXPECT_EQ(OrKR.getRawData(), RawDataR);
+ }
+
+ {
+ // 12 ^ 10 = 6
+ APInt XorLL = Ten ^ Twelve;
+ EXPECT_EQ(XorLL, 0x6);
+
+ APInt XorLR = Ten ^ getRValue("C", RawDataR);
+ EXPECT_EQ(XorLR, 0x6);
+ EXPECT_EQ(XorLR.getRawData(), RawDataR);
+
+ APInt XorRL = getRValue("A", RawDataL) ^ Twelve;
+ EXPECT_EQ(XorRL, 0x6);
+ EXPECT_EQ(XorRL.getRawData(), RawDataL);
+
+ APInt XorRR = getRValue("A", RawDataL) ^ getRValue("C", RawDataR);
+ EXPECT_EQ(XorRR, 0x6);
+ EXPECT_EQ(XorRR.getRawData(), RawDataR);
+
+ // LValue's and constants
+ APInt XorLK = Ten ^ 0xc;
+ EXPECT_EQ(XorLK, 0x6);
+
+ APInt XorKL = 0xa ^ Twelve;
+ EXPECT_EQ(XorKL, 0x6);
+
+ // RValue's and constants
+ APInt XorRK = getRValue("A", RawDataL) ^ 0xc;
+ EXPECT_EQ(XorRK, 0x6);
+ EXPECT_EQ(XorRK.getRawData(), RawDataL);
+
+ APInt XorKR = 0xa ^ getRValue("C", RawDataR);
+ EXPECT_EQ(XorKR, 0x6);
+ EXPECT_EQ(XorKR.getRawData(), RawDataR);
+ }
+}
+
+TEST(APIntTest, rvalue_invert) {
+ // Lamdba to return an APInt by value, but also provide the raw value of the
+ // allocated data.
+ auto getRValue = [](const char *HexString, uint64_t const *&RawData) {
+ APInt V(129, HexString, 16);
+ RawData = V.getRawData();
+ return V;
+ };
+
+ APInt One(129, 1);
+ APInt NegativeTwo(129, -2ULL, true);
+
+ const uint64_t *RawData = nullptr;
+
+ {
+ // ~1 = -2
+ APInt NegL = ~One;
+ EXPECT_EQ(NegL, NegativeTwo);
+
+ APInt NegR = ~getRValue("1", RawData);
+ EXPECT_EQ(NegR, NegativeTwo);
+ EXPECT_EQ(NegR.getRawData(), RawData);
+ }
+}
+
+// Tests different div/rem varaints using scheme (a * b + c) / a
+void testDiv(APInt a, APInt b, APInt c) {
+ ASSERT_TRUE(a.uge(b)); // Must: a >= b
+ ASSERT_TRUE(a.ugt(c)); // Must: a > c
+
+ auto p = a * b + c;
+
+ auto q = p.udiv(a);
+ auto r = p.urem(a);
+ EXPECT_EQ(b, q);
+ EXPECT_EQ(c, r);
+ APInt::udivrem(p, a, q, r);
+ EXPECT_EQ(b, q);
+ EXPECT_EQ(c, r);
+ q = p.sdiv(a);
+ r = p.srem(a);
+ EXPECT_EQ(b, q);
+ EXPECT_EQ(c, r);
+ APInt::sdivrem(p, a, q, r);
+ EXPECT_EQ(b, q);
+ EXPECT_EQ(c, r);
+
+ if (b.ugt(c)) { // Test also symmetric case
+ q = p.udiv(b);
+ r = p.urem(b);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ APInt::udivrem(p, b, q, r);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ q = p.sdiv(b);
+ r = p.srem(b);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ APInt::sdivrem(p, b, q, r);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ }
+}
+
+TEST(APIntTest, divrem_big1) {
+ // Tests KnuthDiv rare step D6
+ testDiv({256, "1ffffffffffffffff", 16},
+ {256, "1ffffffffffffffff", 16},
+ {256, 0});
+}
+
+TEST(APIntTest, divrem_big2) {
+ // Tests KnuthDiv rare step D6
+ testDiv({1024, "112233ceff"
+ "cecece000000ffffffffffffffffffff"
+ "ffffffffffffffffffffffffffffffff"
+ "ffffffffffffffffffffffffffffffff"
+ "ffffffffffffffffffffffffffffff33", 16},
+ {1024, "111111ffffffffffffffff"
+ "ffffffffffffffffffffffffffffffff"
+ "fffffffffffffffffffffffffffffccf"
+ "ffffffffffffffffffffffffffffff00", 16},
+ {1024, 7919});
+}
+
+TEST(APIntTest, divrem_big3) {
+ // Tests KnuthDiv case without shift
+ testDiv({256, "80000001ffffffffffffffff", 16},
+ {256, "ffffffffffffff0000000", 16},
+ {256, 4219});
+}
+
+TEST(APIntTest, divrem_big4) {
+ // Tests heap allocation in divide() enfoced by huge numbers
+ testDiv(APInt{4096, 5}.shl(2001),
+ APInt{4096, 1}.shl(2000),
+ APInt{4096, 4219*13});
+}
+
+TEST(APIntTest, divrem_big5) {
+ // Tests one word divisor case of divide()
+ testDiv(APInt{1024, 19}.shl(811),
+ APInt{1024, 4356013}, // one word
+ APInt{1024, 1});
+}
+
+TEST(APIntTest, divrem_big6) {
+ // Tests some rare "borrow" cases in D4 step
+ testDiv(APInt{512, "ffffffffffffffff00000000000000000000000001", 16},
+ APInt{512, "10000000000000001000000000000001", 16},
+ APInt{512, "10000000000000000000000000000000", 16});
+}
+
+TEST(APIntTest, divrem_big7) {
+ // Yet another test for KnuthDiv rare step D6.
+ testDiv({224, "800000008000000200000005", 16},
+ {224, "fffffffd", 16},
+ {224, "80000000800000010000000f", 16});
+}
+
+void testDiv(APInt a, uint64_t b, APInt c) {
+ auto p = a * b + c;
+
+ APInt q;
+ uint64_t r;
+ // Unsigned division will only work if our original number wasn't negative.
+ if (!a.isNegative()) {
+ q = p.udiv(b);
+ r = p.urem(b);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ APInt::udivrem(p, b, q, r);
+ EXPECT_EQ(a, q);
+ EXPECT_EQ(c, r);
+ }
+ q = p.sdiv(b);
+ r = p.srem(b);
+ EXPECT_EQ(a, q);
+ if (c.isNegative())
+ EXPECT_EQ(-c, -r); // Need to negate so the uint64_t compare will work.
+ else
+ EXPECT_EQ(c, r);
+ int64_t sr;
+ APInt::sdivrem(p, b, q, sr);
+ EXPECT_EQ(a, q);
+ if (c.isNegative())
+ EXPECT_EQ(-c, -sr); // Need to negate so the uint64_t compare will work.
+ else
+ EXPECT_EQ(c, sr);
+}
+
+TEST(APIntTest, divremuint) {
+ // Single word APInt
+ testDiv(APInt{64, 9},
+ 2,
+ APInt{64, 1});
+
+ // Single word negative APInt
+ testDiv(-APInt{64, 9},
+ 2,
+ -APInt{64, 1});
+
+ // Multiword dividend with only one significant word.
+ testDiv(APInt{256, 9},
+ 2,
+ APInt{256, 1});
+
+ // Negative dividend.
+ testDiv(-APInt{256, 9},
+ 2,
+ -APInt{256, 1});
+
+ // Multiword dividend
+ testDiv(APInt{1024, 19}.shl(811),
+ 4356013, // one word
+ APInt{1024, 1});
+}
+
+TEST(APIntTest, divrem_simple) {
+ // Test simple cases.
+ APInt A(65, 2), B(65, 2);
+ APInt Q, R;
+
+ // X / X
+ APInt::sdivrem(A, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 1));
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(A, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 1));
+ EXPECT_EQ(R, APInt(65, 0));
+
+ // 0 / X
+ APInt O(65, 0);
+ APInt::sdivrem(O, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 0));
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(O, B, Q, R);
+ EXPECT_EQ(Q, APInt(65, 0));
+ EXPECT_EQ(R, APInt(65, 0));
+
+ // X / 1
+ APInt I(65, 1);
+ APInt::sdivrem(A, I, Q, R);
+ EXPECT_EQ(Q, A);
+ EXPECT_EQ(R, APInt(65, 0));
+ APInt::udivrem(A, I, Q, R);
+ EXPECT_EQ(Q, A);
+ EXPECT_EQ(R, APInt(65, 0));
+}
+
+TEST(APIntTest, fromString) {
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 2));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 2));
+ EXPECT_EQ(APInt(32, 2), APInt(32, "10", 2));
+ EXPECT_EQ(APInt(32, 3), APInt(32, "11", 2));
+ EXPECT_EQ(APInt(32, 4), APInt(32, "100", 2));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "+0", 2));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "+1", 2));
+ EXPECT_EQ(APInt(32, 2), APInt(32, "+10", 2));
+ EXPECT_EQ(APInt(32, 3), APInt(32, "+11", 2));
+ EXPECT_EQ(APInt(32, 4), APInt(32, "+100", 2));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 2));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 2));
+ EXPECT_EQ(APInt(32, uint64_t(-2LL)), APInt(32, "-10", 2));
+ EXPECT_EQ(APInt(32, uint64_t(-3LL)), APInt(32, "-11", 2));
+ EXPECT_EQ(APInt(32, uint64_t(-4LL)), APInt(32, "-100", 2));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 8));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 8));
+ EXPECT_EQ(APInt(32, 7), APInt(32, "7", 8));
+ EXPECT_EQ(APInt(32, 8), APInt(32, "10", 8));
+ EXPECT_EQ(APInt(32, 15), APInt(32, "17", 8));
+ EXPECT_EQ(APInt(32, 16), APInt(32, "20", 8));
+
+ EXPECT_EQ(APInt(32, +0), APInt(32, "+0", 8));
+ EXPECT_EQ(APInt(32, +1), APInt(32, "+1", 8));
+ EXPECT_EQ(APInt(32, +7), APInt(32, "+7", 8));
+ EXPECT_EQ(APInt(32, +8), APInt(32, "+10", 8));
+ EXPECT_EQ(APInt(32, +15), APInt(32, "+17", 8));
+ EXPECT_EQ(APInt(32, +16), APInt(32, "+20", 8));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 8));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 8));
+ EXPECT_EQ(APInt(32, uint64_t(-7LL)), APInt(32, "-7", 8));
+ EXPECT_EQ(APInt(32, uint64_t(-8LL)), APInt(32, "-10", 8));
+ EXPECT_EQ(APInt(32, uint64_t(-15LL)), APInt(32, "-17", 8));
+ EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-20", 8));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 10));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 10));
+ EXPECT_EQ(APInt(32, 9), APInt(32, "9", 10));
+ EXPECT_EQ(APInt(32, 10), APInt(32, "10", 10));
+ EXPECT_EQ(APInt(32, 19), APInt(32, "19", 10));
+ EXPECT_EQ(APInt(32, 20), APInt(32, "20", 10));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 10));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 10));
+ EXPECT_EQ(APInt(32, uint64_t(-9LL)), APInt(32, "-9", 10));
+ EXPECT_EQ(APInt(32, uint64_t(-10LL)), APInt(32, "-10", 10));
+ EXPECT_EQ(APInt(32, uint64_t(-19LL)), APInt(32, "-19", 10));
+ EXPECT_EQ(APInt(32, uint64_t(-20LL)), APInt(32, "-20", 10));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 16));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 16));
+ EXPECT_EQ(APInt(32, 15), APInt(32, "F", 16));
+ EXPECT_EQ(APInt(32, 16), APInt(32, "10", 16));
+ EXPECT_EQ(APInt(32, 31), APInt(32, "1F", 16));
+ EXPECT_EQ(APInt(32, 32), APInt(32, "20", 16));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 16));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 16));
+ EXPECT_EQ(APInt(32, uint64_t(-15LL)), APInt(32, "-F", 16));
+ EXPECT_EQ(APInt(32, uint64_t(-16LL)), APInt(32, "-10", 16));
+ EXPECT_EQ(APInt(32, uint64_t(-31LL)), APInt(32, "-1F", 16));
+ EXPECT_EQ(APInt(32, uint64_t(-32LL)), APInt(32, "-20", 16));
+
+ EXPECT_EQ(APInt(32, 0), APInt(32, "0", 36));
+ EXPECT_EQ(APInt(32, 1), APInt(32, "1", 36));
+ EXPECT_EQ(APInt(32, 35), APInt(32, "Z", 36));
+ EXPECT_EQ(APInt(32, 36), APInt(32, "10", 36));
+ EXPECT_EQ(APInt(32, 71), APInt(32, "1Z", 36));
+ EXPECT_EQ(APInt(32, 72), APInt(32, "20", 36));
+
+ EXPECT_EQ(APInt(32, uint64_t(-0LL)), APInt(32, "-0", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-1LL)), APInt(32, "-1", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-35LL)), APInt(32, "-Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-36LL)), APInt(32, "-10", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-71LL)), APInt(32, "-1Z", 36));
+ EXPECT_EQ(APInt(32, uint64_t(-72LL)), APInt(32, "-20", 36));
+}
+
+TEST(APIntTest, SaturatingMath) {
+ APInt AP_10 = APInt(8, 10);
+ APInt AP_100 = APInt(8, 100);
+ APInt AP_200 = APInt(8, 200);
+
+ EXPECT_EQ(APInt(8, 200), AP_100.uadd_sat(AP_100));
+ EXPECT_EQ(APInt(8, 255), AP_100.uadd_sat(AP_200));
+ EXPECT_EQ(APInt(8, 255), APInt(8, 255).uadd_sat(APInt(8, 255)));
+
+ EXPECT_EQ(APInt(8, 110), AP_10.sadd_sat(AP_100));
+ EXPECT_EQ(APInt(8, 127), AP_100.sadd_sat(AP_100));
+ EXPECT_EQ(APInt(8, -128), (-AP_100).sadd_sat(-AP_100));
+ EXPECT_EQ(APInt(8, -128), APInt(8, -128).sadd_sat(APInt(8, -128)));
+
+ EXPECT_EQ(APInt(8, 90), AP_100.usub_sat(AP_10));
+ EXPECT_EQ(APInt(8, 0), AP_100.usub_sat(AP_200));
+ EXPECT_EQ(APInt(8, 0), APInt(8, 0).usub_sat(APInt(8, 255)));
+
+ EXPECT_EQ(APInt(8, -90), AP_10.ssub_sat(AP_100));
+ EXPECT_EQ(APInt(8, 127), AP_100.ssub_sat(-AP_100));
+ EXPECT_EQ(APInt(8, -128), (-AP_100).ssub_sat(AP_100));
+ EXPECT_EQ(APInt(8, -128), APInt(8, -128).ssub_sat(APInt(8, 127)));
+}
+
+TEST(APIntTest, FromArray) {
+ EXPECT_EQ(APInt(32, uint64_t(1)), APInt(32, ArrayRef<uint64_t>(1)));
+}
+
+TEST(APIntTest, StringBitsNeeded2) {
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "0", 2));
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "1", 2));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "10", 2));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "11", 2));
+ EXPECT_EQ(3U, APInt::getBitsNeeded("100", 2));
+
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "+0", 2));
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "+1", 2));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "+10", 2));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "+11", 2));
+ EXPECT_EQ(3U, APInt::getBitsNeeded("+100", 2));
+
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "-0", 2));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "-1", 2));
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "-10", 2));
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "-11", 2));
+ EXPECT_EQ(4U, APInt::getBitsNeeded("-100", 2));
+}
+
+TEST(APIntTest, StringBitsNeeded8) {
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "0", 8));
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "7", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("10", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("17", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("20", 8));
+
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "+0", 8));
+ EXPECT_EQ(3U, APInt::getBitsNeeded( "+7", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("+10", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("+17", 8));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("+20", 8));
+
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "-0", 8));
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "-7", 8));
+ EXPECT_EQ(7U, APInt::getBitsNeeded("-10", 8));
+ EXPECT_EQ(7U, APInt::getBitsNeeded("-17", 8));
+ EXPECT_EQ(7U, APInt::getBitsNeeded("-20", 8));
+}
+
+TEST(APIntTest, StringBitsNeeded10) {
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "0", 10));
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "3", 10));
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "9", 10));
+ EXPECT_EQ(4U, APInt::getBitsNeeded("10", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded("19", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded("20", 10));
+
+ EXPECT_EQ(1U, APInt::getBitsNeeded( "+0", 10));
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "+9", 10));
+ EXPECT_EQ(4U, APInt::getBitsNeeded("+10", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded("+19", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded("+20", 10));
+
+ EXPECT_EQ(2U, APInt::getBitsNeeded( "-0", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded( "-9", 10));
+ EXPECT_EQ(5U, APInt::getBitsNeeded("-10", 10));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("-19", 10));
+ EXPECT_EQ(6U, APInt::getBitsNeeded("-20", 10));
+}
+
+TEST(APIntTest, StringBitsNeeded16) {
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "0", 16));
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "F", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("10", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("1F", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("20", 16));
+
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "+0", 16));
+ EXPECT_EQ(4U, APInt::getBitsNeeded( "+F", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("+10", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("+1F", 16));
+ EXPECT_EQ(8U, APInt::getBitsNeeded("+20", 16));
+
+ EXPECT_EQ(5U, APInt::getBitsNeeded( "-0", 16));
+ EXPECT_EQ(5U, APInt::getBitsNeeded( "-F", 16));
+ EXPECT_EQ(9U, APInt::getBitsNeeded("-10", 16));
+ EXPECT_EQ(9U, APInt::getBitsNeeded("-1F", 16));
+ EXPECT_EQ(9U, APInt::getBitsNeeded("-20", 16));
+}
+
+TEST(APIntTest, toString) {
+ SmallString<16> S;
+ bool isSigned;
+
+ APInt(8, 0).toString(S, 2, true, true);
+ EXPECT_EQ(S.str().str(), "0b0");
+ S.clear();
+ APInt(8, 0).toString(S, 8, true, true);
+ EXPECT_EQ(S.str().str(), "00");
+ S.clear();
+ APInt(8, 0).toString(S, 10, true, true);
+ EXPECT_EQ(S.str().str(), "0");
+ S.clear();
+ APInt(8, 0).toString(S, 16, true, true);
+ EXPECT_EQ(S.str().str(), "0x0");
+ S.clear();
+ APInt(8, 0).toString(S, 36, true, false);
+ EXPECT_EQ(S.str().str(), "0");
+ S.clear();
+
+ isSigned = false;
+ APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
+ EXPECT_EQ(S.str().str(), "0b11111111");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 8, isSigned, true);
+ EXPECT_EQ(S.str().str(), "0377");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 10, isSigned, true);
+ EXPECT_EQ(S.str().str(), "255");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
+ EXPECT_EQ(S.str().str(), "0xFF");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, false);
+ EXPECT_EQ(S.str().str(), "73");
+ S.clear();
+
+ isSigned = true;
+ APInt(8, 255, isSigned).toString(S, 2, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-0b1");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 8, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-01");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 10, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-1");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 16, isSigned, true);
+ EXPECT_EQ(S.str().str(), "-0x1");
+ S.clear();
+ APInt(8, 255, isSigned).toString(S, 36, isSigned, false);
+ EXPECT_EQ(S.str().str(), "-1");
+ S.clear();
+}
+
+TEST(APIntTest, Log2) {
+ EXPECT_EQ(APInt(15, 7).logBase2(), 2U);
+ EXPECT_EQ(APInt(15, 7).ceilLogBase2(), 3U);
+ EXPECT_EQ(APInt(15, 7).exactLogBase2(), -1);
+ EXPECT_EQ(APInt(15, 8).logBase2(), 3U);
+ EXPECT_EQ(APInt(15, 8).ceilLogBase2(), 3U);
+ EXPECT_EQ(APInt(15, 8).exactLogBase2(), 3);
+ EXPECT_EQ(APInt(15, 9).logBase2(), 3U);
+ EXPECT_EQ(APInt(15, 9).ceilLogBase2(), 4U);
+ EXPECT_EQ(APInt(15, 9).exactLogBase2(), -1);
+}
+
+TEST(APIntTest, magic) {
+ EXPECT_EQ(APInt(32, 3).magic().m, APInt(32, "55555556", 16));
+ EXPECT_EQ(APInt(32, 3).magic().s, 0U);
+ EXPECT_EQ(APInt(32, 5).magic().m, APInt(32, "66666667", 16));
+ EXPECT_EQ(APInt(32, 5).magic().s, 1U);
+ EXPECT_EQ(APInt(32, 7).magic().m, APInt(32, "92492493", 16));
+ EXPECT_EQ(APInt(32, 7).magic().s, 2U);
+}
+
+TEST(APIntTest, magicu) {
+ EXPECT_EQ(APInt(32, 3).magicu().m, APInt(32, "AAAAAAAB", 16));
+ EXPECT_EQ(APInt(32, 3).magicu().s, 1U);
+ EXPECT_EQ(APInt(32, 5).magicu().m, APInt(32, "CCCCCCCD", 16));
+ EXPECT_EQ(APInt(32, 5).magicu().s, 2U);
+ EXPECT_EQ(APInt(32, 7).magicu().m, APInt(32, "24924925", 16));
+ EXPECT_EQ(APInt(32, 7).magicu().s, 3U);
+ EXPECT_EQ(APInt(64, 25).magicu(1).m, APInt(64, "A3D70A3D70A3D70B", 16));
+ EXPECT_EQ(APInt(64, 25).magicu(1).s, 4U);
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(APIntTest, StringDeath) {
+ EXPECT_DEATH(APInt(0, "", 0), "Bitwidth too small");
+ EXPECT_DEATH(APInt(32, "", 0), "Invalid string length");
+ EXPECT_DEATH(APInt(32, "0", 0), "Radix should be 2, 8, 10, 16, or 36!");
+ EXPECT_DEATH(APInt(32, "", 10), "Invalid string length");
+ EXPECT_DEATH(APInt(32, "-", 10), "String is only a sign, needs a value.");
+ EXPECT_DEATH(APInt(1, "1234", 10), "Insufficient bit width");
+ EXPECT_DEATH(APInt(32, "\0", 10), "Invalid string length");
+ EXPECT_DEATH(APInt(32, StringRef("1\02", 3), 10), "Invalid character in digit string");
+ EXPECT_DEATH(APInt(32, "1L", 10), "Invalid character in digit string");
+}
+#endif
+#endif
+
+TEST(APIntTest, mul_clear) {
+ APInt ValA(65, -1ULL);
+ APInt ValB(65, 4);
+ APInt ValC(65, 0);
+ ValC = ValA * ValB;
+ ValA *= ValB;
+ EXPECT_EQ(ValA.toString(10, false), ValC.toString(10, false));
+}
+
+TEST(APIntTest, Rotate) {
+ EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotl(0));
+ EXPECT_EQ(APInt(8, 2), APInt(8, 1).rotl(1));
+ EXPECT_EQ(APInt(8, 4), APInt(8, 1).rotl(2));
+ EXPECT_EQ(APInt(8, 16), APInt(8, 1).rotl(4));
+ EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotl(8));
+
+ EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotl(0));
+ EXPECT_EQ(APInt(8, 32), APInt(8, 16).rotl(1));
+ EXPECT_EQ(APInt(8, 64), APInt(8, 16).rotl(2));
+ EXPECT_EQ(APInt(8, 1), APInt(8, 16).rotl(4));
+ EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotl(8));
+
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(33));
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(APInt(32, 33)));
+
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(33));
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(APInt(32, 33)));
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(APInt(33, 33)));
+ EXPECT_EQ(APInt(32, (1 << 8)), APInt(32, 1).rotl(APInt(32, 40)));
+ EXPECT_EQ(APInt(32, (1 << 30)), APInt(32, 1).rotl(APInt(31, 30)));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotl(APInt(31, 31)));
+
+ EXPECT_EQ(APInt(32, 1), APInt(32, 1).rotl(APInt(1, 0)));
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(APInt(1, 1)));
+
+ EXPECT_EQ(APInt(32, 16), APInt(32, 1).rotl(APInt(3, 4)));
+
+ EXPECT_EQ(APInt(32, 1), APInt(32, 1).rotl(APInt(64, 64)));
+ EXPECT_EQ(APInt(32, 2), APInt(32, 1).rotl(APInt(64, 65)));
+
+ EXPECT_EQ(APInt(7, 24), APInt(7, 3).rotl(APInt(7, 3)));
+ EXPECT_EQ(APInt(7, 24), APInt(7, 3).rotl(APInt(7, 10)));
+ EXPECT_EQ(APInt(7, 24), APInt(7, 3).rotl(APInt(5, 10)));
+ EXPECT_EQ(APInt(7, 6), APInt(7, 3).rotl(APInt(12, 120)));
+
+ EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotr(0));
+ EXPECT_EQ(APInt(8, 8), APInt(8, 16).rotr(1));
+ EXPECT_EQ(APInt(8, 4), APInt(8, 16).rotr(2));
+ EXPECT_EQ(APInt(8, 1), APInt(8, 16).rotr(4));
+ EXPECT_EQ(APInt(8, 16), APInt(8, 16).rotr(8));
+
+ EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotr(0));
+ EXPECT_EQ(APInt(8, 128), APInt(8, 1).rotr(1));
+ EXPECT_EQ(APInt(8, 64), APInt(8, 1).rotr(2));
+ EXPECT_EQ(APInt(8, 16), APInt(8, 1).rotr(4));
+ EXPECT_EQ(APInt(8, 1), APInt(8, 1).rotr(8));
+
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(33));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(APInt(32, 33)));
+
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(33));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(APInt(32, 33)));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(APInt(33, 33)));
+ EXPECT_EQ(APInt(32, (1 << 24)), APInt(32, 1).rotr(APInt(32, 40)));
+
+ EXPECT_EQ(APInt(32, (1 << 2)), APInt(32, 1).rotr(APInt(31, 30)));
+ EXPECT_EQ(APInt(32, (1 << 1)), APInt(32, 1).rotr(APInt(31, 31)));
+
+ EXPECT_EQ(APInt(32, 1), APInt(32, 1).rotr(APInt(1, 0)));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(APInt(1, 1)));
+
+ EXPECT_EQ(APInt(32, (1 << 28)), APInt(32, 1).rotr(APInt(3, 4)));
+
+ EXPECT_EQ(APInt(32, 1), APInt(32, 1).rotr(APInt(64, 64)));
+ EXPECT_EQ(APInt(32, (1 << 31)), APInt(32, 1).rotr(APInt(64, 65)));
+
+ EXPECT_EQ(APInt(7, 48), APInt(7, 3).rotr(APInt(7, 3)));
+ EXPECT_EQ(APInt(7, 48), APInt(7, 3).rotr(APInt(7, 10)));
+ EXPECT_EQ(APInt(7, 48), APInt(7, 3).rotr(APInt(5, 10)));
+ EXPECT_EQ(APInt(7, 65), APInt(7, 3).rotr(APInt(12, 120)));
+
+ APInt Big(256, "00004000800000000000000000003fff8000000000000003", 16);
+ APInt Rot(256, "3fff80000000000000030000000000000000000040008000", 16);
+ EXPECT_EQ(Rot, Big.rotr(144));
+
+ EXPECT_EQ(APInt(32, 8), APInt(32, 1).rotl(Big));
+ EXPECT_EQ(APInt(32, (1 << 29)), APInt(32, 1).rotr(Big));
+}
+
+TEST(APIntTest, Splat) {
+ APInt ValA(8, 0x01);
+ EXPECT_EQ(ValA, APInt::getSplat(8, ValA));
+ EXPECT_EQ(APInt(64, 0x0101010101010101ULL), APInt::getSplat(64, ValA));
+
+ APInt ValB(3, 5);
+ EXPECT_EQ(APInt(4, 0xD), APInt::getSplat(4, ValB));
+ EXPECT_EQ(APInt(15, 0xDB6D), APInt::getSplat(15, ValB));
+}
+
+TEST(APIntTest, tcDecrement) {
+ // Test single word decrement.
+
+ // No out borrow.
+ {
+ APInt::WordType singleWord = ~APInt::WordType(0) << (APInt::APINT_BITS_PER_WORD - 1);
+ APInt::WordType carry = APInt::tcDecrement(&singleWord, 1);
+ EXPECT_EQ(carry, APInt::WordType(0));
+ EXPECT_EQ(singleWord, ~APInt::WordType(0) >> 1);
+ }
+
+ // With out borrow.
+ {
+ APInt::WordType singleWord = 0;
+ APInt::WordType carry = APInt::tcDecrement(&singleWord, 1);
+ EXPECT_EQ(carry, APInt::WordType(1));
+ EXPECT_EQ(singleWord, ~APInt::WordType(0));
+ }
+
+ // Test multiword decrement.
+
+ // No across word borrow, no out borrow.
+ {
+ APInt::WordType test[4] = {0x1, 0x1, 0x1, 0x1};
+ APInt::WordType expected[4] = {0x0, 0x1, 0x1, 0x1};
+ APInt::tcDecrement(test, 4);
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 1 across word borrow, no out borrow.
+ {
+ APInt::WordType test[4] = {0x0, 0xF, 0x1, 0x1};
+ APInt::WordType expected[4] = {~APInt::WordType(0), 0xE, 0x1, 0x1};
+ APInt::WordType carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, APInt::WordType(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 2 across word borrow, no out borrow.
+ {
+ APInt::WordType test[4] = {0x0, 0x0, 0xC, 0x1};
+ APInt::WordType expected[4] = {~APInt::WordType(0), ~APInt::WordType(0), 0xB, 0x1};
+ APInt::WordType carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, APInt::WordType(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 3 across word borrow, no out borrow.
+ {
+ APInt::WordType test[4] = {0x0, 0x0, 0x0, 0x1};
+ APInt::WordType expected[4] = {~APInt::WordType(0), ~APInt::WordType(0), ~APInt::WordType(0), 0x0};
+ APInt::WordType carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, APInt::WordType(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 3 across word borrow, with out borrow.
+ {
+ APInt::WordType test[4] = {0x0, 0x0, 0x0, 0x0};
+ APInt::WordType expected[4] = {~APInt::WordType(0), ~APInt::WordType(0), ~APInt::WordType(0), ~APInt::WordType(0)};
+ APInt::WordType carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, APInt::WordType(1));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+}
+
+TEST(APIntTest, arrayAccess) {
+ // Single word check.
+ uint64_t E1 = 0x2CA7F46BF6569915ULL;
+ APInt A1(64, E1);
+ for (unsigned i = 0, e = 64; i < e; ++i) {
+ EXPECT_EQ(bool(E1 & (1ULL << i)),
+ A1[i]);
+ }
+
+ // Multiword check.
+ APInt::WordType E2[4] = {
+ 0xEB6EB136591CBA21ULL,
+ 0x7B9358BD6A33F10AULL,
+ 0x7E7FFA5EADD8846ULL,
+ 0x305F341CA00B613DULL
+ };
+ APInt A2(APInt::APINT_BITS_PER_WORD*4, E2);
+ for (unsigned i = 0; i < 4; ++i) {
+ for (unsigned j = 0; j < APInt::APINT_BITS_PER_WORD; ++j) {
+ EXPECT_EQ(bool(E2[i] & (1ULL << j)),
+ A2[i*APInt::APINT_BITS_PER_WORD + j]);
+ }
+ }
+}
+
+TEST(APIntTest, LargeAPIntConstruction) {
+ // Check that we can properly construct very large APInt. It is very
+ // unlikely that people will ever do this, but it is a legal input,
+ // so we should not crash on it.
+ APInt A9(UINT32_MAX, 0);
+ EXPECT_FALSE(A9.getBoolValue());
+}
+
+TEST(APIntTest, nearestLogBase2) {
+ // Single word check.
+
+ // Test round up.
+ uint64_t I1 = 0x1800001;
+ APInt A1(64, I1);
+ EXPECT_EQ(A1.nearestLogBase2(), A1.ceilLogBase2());
+
+ // Test round down.
+ uint64_t I2 = 0x1000011;
+ APInt A2(64, I2);
+ EXPECT_EQ(A2.nearestLogBase2(), A2.logBase2());
+
+ // Test ties round up.
+ uint64_t I3 = 0x1800000;
+ APInt A3(64, I3);
+ EXPECT_EQ(A3.nearestLogBase2(), A3.ceilLogBase2());
+
+ // Multiple word check.
+
+ // Test round up.
+ APInt::WordType I4[4] = {0x0, 0xF, 0x18, 0x0};
+ APInt A4(APInt::APINT_BITS_PER_WORD*4, I4);
+ EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2());
+
+ // Test round down.
+ APInt::WordType I5[4] = {0x0, 0xF, 0x10, 0x0};
+ APInt A5(APInt::APINT_BITS_PER_WORD*4, I5);
+ EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2());
+
+ // Test ties round up.
+ uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18};
+ APInt A6(APInt::APINT_BITS_PER_WORD*4, I6);
+ EXPECT_EQ(A6.nearestLogBase2(), A6.ceilLogBase2());
+
+ // Test BitWidth == 1 special cases.
+ APInt A7(1, 1);
+ EXPECT_EQ(A7.nearestLogBase2(), 0ULL);
+ APInt A8(1, 0);
+ EXPECT_EQ(A8.nearestLogBase2(), UINT32_MAX);
+
+ // Test the zero case when we have a bit width large enough such
+ // that the bit width is larger than UINT32_MAX-1.
+ APInt A9(UINT32_MAX, 0);
+ EXPECT_EQ(A9.nearestLogBase2(), UINT32_MAX);
+}
+
+TEST(APIntTest, IsSplat) {
+ APInt A(32, 0x01010101);
+ EXPECT_FALSE(A.isSplat(1));
+ EXPECT_FALSE(A.isSplat(2));
+ EXPECT_FALSE(A.isSplat(4));
+ EXPECT_TRUE(A.isSplat(8));
+ EXPECT_TRUE(A.isSplat(16));
+ EXPECT_TRUE(A.isSplat(32));
+
+ APInt B(24, 0xAAAAAA);
+ EXPECT_FALSE(B.isSplat(1));
+ EXPECT_TRUE(B.isSplat(2));
+ EXPECT_TRUE(B.isSplat(4));
+ EXPECT_TRUE(B.isSplat(8));
+ EXPECT_TRUE(B.isSplat(24));
+
+ APInt C(24, 0xABAAAB);
+ EXPECT_FALSE(C.isSplat(1));
+ EXPECT_FALSE(C.isSplat(2));
+ EXPECT_FALSE(C.isSplat(4));
+ EXPECT_FALSE(C.isSplat(8));
+ EXPECT_TRUE(C.isSplat(24));
+
+ APInt D(32, 0xABBAABBA);
+ EXPECT_FALSE(D.isSplat(1));
+ EXPECT_FALSE(D.isSplat(2));
+ EXPECT_FALSE(D.isSplat(4));
+ EXPECT_FALSE(D.isSplat(8));
+ EXPECT_TRUE(D.isSplat(16));
+ EXPECT_TRUE(D.isSplat(32));
+
+ APInt E(32, 0);
+ EXPECT_TRUE(E.isSplat(1));
+ EXPECT_TRUE(E.isSplat(2));
+ EXPECT_TRUE(E.isSplat(4));
+ EXPECT_TRUE(E.isSplat(8));
+ EXPECT_TRUE(E.isSplat(16));
+ EXPECT_TRUE(E.isSplat(32));
+}
+
+TEST(APIntTest, isMask) {
+ EXPECT_FALSE(APInt(32, 0x01010101).isMask());
+ EXPECT_FALSE(APInt(32, 0xf0000000).isMask());
+ EXPECT_FALSE(APInt(32, 0xffff0000).isMask());
+ EXPECT_FALSE(APInt(32, 0xff << 1).isMask());
+
+ for (int N : { 1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256 }) {
+ EXPECT_FALSE(APInt(N, 0).isMask());
+
+ APInt One(N, 1);
+ for (int I = 1; I <= N; ++I) {
+ APInt MaskVal = One.shl(I) - 1;
+ EXPECT_TRUE(MaskVal.isMask());
+ EXPECT_TRUE(MaskVal.isMask(I));
+ }
+ }
+}
+
+TEST(APIntTest, isShiftedMask) {
+ EXPECT_FALSE(APInt(32, 0x01010101).isShiftedMask());
+ EXPECT_TRUE(APInt(32, 0xf0000000).isShiftedMask());
+ EXPECT_TRUE(APInt(32, 0xffff0000).isShiftedMask());
+ EXPECT_TRUE(APInt(32, 0xff << 1).isShiftedMask());
+
+ for (int N : { 1, 2, 3, 4, 7, 8, 16, 32, 64, 127, 128, 129, 256 }) {
+ EXPECT_FALSE(APInt(N, 0).isShiftedMask());
+
+ APInt One(N, 1);
+ for (int I = 1; I < N; ++I) {
+ APInt MaskVal = One.shl(I) - 1;
+ EXPECT_TRUE(MaskVal.isShiftedMask());
+ }
+ for (int I = 1; I < N - 1; ++I) {
+ APInt MaskVal = One.shl(I);
+ EXPECT_TRUE(MaskVal.isShiftedMask());
+ }
+ for (int I = 1; I < N; ++I) {
+ APInt MaskVal = APInt::getHighBitsSet(N, I);
+ EXPECT_TRUE(MaskVal.isShiftedMask());
+ }
+ }
+}
+
+// Test that self-move works, but only when we're using MSVC.
+#if defined(_MSC_VER)
+#if defined(__clang__)
+// Disable the pragma warning from versions of Clang without -Wself-move
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+// Disable the warning that triggers on exactly what is being tested.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wself-move"
+#endif
+TEST(APIntTest, SelfMoveAssignment) {
+ APInt X(32, 0xdeadbeef);
+ X = std::move(X);
+ EXPECT_EQ(32u, X.getBitWidth());
+ EXPECT_EQ(0xdeadbeefULL, X.getLimitedValue());
+
+ uint64_t Bits[] = {0xdeadbeefdeadbeefULL, 0xdeadbeefdeadbeefULL};
+ APInt Y(128, Bits);
+ Y = std::move(Y);
+ EXPECT_EQ(128u, Y.getBitWidth());
+ EXPECT_EQ(~0ULL, Y.getLimitedValue());
+ const uint64_t *Raw = Y.getRawData();
+ EXPECT_EQ(2u, Y.getNumWords());
+ EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[0]);
+ EXPECT_EQ(0xdeadbeefdeadbeefULL, Raw[1]);
+}
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#pragma clang diagnostic pop
+#endif
+#endif // _MSC_VER
+
+TEST(APIntTest, reverseBits) {
+ EXPECT_EQ(1, APInt(1, 1).reverseBits());
+ EXPECT_EQ(0, APInt(1, 0).reverseBits());
+
+ EXPECT_EQ(3, APInt(2, 3).reverseBits());
+ EXPECT_EQ(3, APInt(2, 3).reverseBits());
+
+ EXPECT_EQ(0xb, APInt(4, 0xd).reverseBits());
+ EXPECT_EQ(0xd, APInt(4, 0xb).reverseBits());
+ EXPECT_EQ(0xf, APInt(4, 0xf).reverseBits());
+
+ EXPECT_EQ(0x30, APInt(7, 0x6).reverseBits());
+ EXPECT_EQ(0x5a, APInt(7, 0x2d).reverseBits());
+
+ EXPECT_EQ(0x0f, APInt(8, 0xf0).reverseBits());
+ EXPECT_EQ(0xf0, APInt(8, 0x0f).reverseBits());
+
+ EXPECT_EQ(0x0f0f, APInt(16, 0xf0f0).reverseBits());
+ EXPECT_EQ(0xf0f0, APInt(16, 0x0f0f).reverseBits());
+
+ EXPECT_EQ(0x0f0f0f0f, APInt(32, 0xf0f0f0f0).reverseBits());
+ EXPECT_EQ(0xf0f0f0f0, APInt(32, 0x0f0f0f0f).reverseBits());
+
+ EXPECT_EQ(0x402880a0 >> 1, APInt(31, 0x05011402).reverseBits());
+
+ EXPECT_EQ(0x0f0f0f0f, APInt(32, 0xf0f0f0f0).reverseBits());
+ EXPECT_EQ(0xf0f0f0f0, APInt(32, 0x0f0f0f0f).reverseBits());
+
+ EXPECT_EQ(0x0f0f0f0f0f0f0f0f, APInt(64, 0xf0f0f0f0f0f0f0f0).reverseBits());
+ EXPECT_EQ(0xf0f0f0f0f0f0f0f0, APInt(64, 0x0f0f0f0f0f0f0f0f).reverseBits());
+
+ for (unsigned N : { 1, 8, 16, 24, 31, 32, 33,
+ 63, 64, 65, 127, 128, 257, 1024 }) {
+ for (unsigned I = 0; I < N; ++I) {
+ APInt X = APInt::getOneBitSet(N, I);
+ APInt Y = APInt::getOneBitSet(N, N - (I + 1));
+ EXPECT_EQ(Y, X.reverseBits());
+ EXPECT_EQ(X, Y.reverseBits());
+ }
+ }
+}
+
+TEST(APIntTest, insertBits) {
+ APInt iSrc(31, 0x00123456);
+
+ // Direct copy.
+ APInt i31(31, 0x76543210ull);
+ i31.insertBits(iSrc, 0);
+ EXPECT_EQ(static_cast<int64_t>(0x00123456ull), i31.getSExtValue());
+
+ // Single word src/dst insertion.
+ APInt i63(63, 0x01234567FFFFFFFFull);
+ i63.insertBits(iSrc, 4);
+ EXPECT_EQ(static_cast<int64_t>(0x012345600123456Full), i63.getSExtValue());
+
+ // Insert single word src into one word of dst.
+ APInt i120(120, UINT64_MAX, true);
+ i120.insertBits(iSrc, 8);
+ EXPECT_EQ(static_cast<int64_t>(0xFFFFFF80123456FFull), i120.getSExtValue());
+
+ // Insert single word src into two words of dst.
+ APInt i127(127, UINT64_MAX, true);
+ i127.insertBits(iSrc, 48);
+ EXPECT_EQ(i127.extractBits(64, 0).getZExtValue(), 0x3456FFFFFFFFFFFFull);
+ EXPECT_EQ(i127.extractBits(63, 64).getZExtValue(), 0x7FFFFFFFFFFF8012ull);
+
+ // Insert on word boundaries.
+ APInt i128(128, 0);
+ i128.insertBits(APInt(64, UINT64_MAX, true), 0);
+ i128.insertBits(APInt(64, UINT64_MAX, true), 64);
+ EXPECT_EQ(-1, i128.getSExtValue());
+
+ APInt i256(256, UINT64_MAX, true);
+ i256.insertBits(APInt(65, 0), 0);
+ i256.insertBits(APInt(69, 0), 64);
+ i256.insertBits(APInt(128, 0), 128);
+ EXPECT_EQ(0u, i256.getSExtValue());
+
+ APInt i257(257, 0);
+ i257.insertBits(APInt(96, UINT64_MAX, true), 64);
+ EXPECT_EQ(i257.extractBits(64, 0).getZExtValue(), 0x0000000000000000ull);
+ EXPECT_EQ(i257.extractBits(64, 64).getZExtValue(), 0xFFFFFFFFFFFFFFFFull);
+ EXPECT_EQ(i257.extractBits(64, 128).getZExtValue(), 0x00000000FFFFFFFFull);
+ EXPECT_EQ(i257.extractBits(65, 192).getZExtValue(), 0x0000000000000000ull);
+
+ // General insertion.
+ APInt i260(260, UINT64_MAX, true);
+ i260.insertBits(APInt(129, 1ull << 48), 15);
+ EXPECT_EQ(i260.extractBits(64, 0).getZExtValue(), 0x8000000000007FFFull);
+ EXPECT_EQ(i260.extractBits(64, 64).getZExtValue(), 0x0000000000000000ull);
+ EXPECT_EQ(i260.extractBits(64, 128).getZExtValue(), 0xFFFFFFFFFFFF0000ull);
+ EXPECT_EQ(i260.extractBits(64, 192).getZExtValue(), 0xFFFFFFFFFFFFFFFFull);
+ EXPECT_EQ(i260.extractBits(4, 256).getZExtValue(), 0x000000000000000Full);
+}
+
+TEST(APIntTest, extractBits) {
+ APInt i32(32, 0x1234567);
+ EXPECT_EQ(0x3456, i32.extractBits(16, 4));
+
+ APInt i257(257, 0xFFFFFFFFFF0000FFull, true);
+ EXPECT_EQ(0xFFu, i257.extractBits(16, 0));
+ EXPECT_EQ((0xFFu >> 1), i257.extractBits(16, 1));
+ EXPECT_EQ(-1, i257.extractBits(32, 64).getSExtValue());
+ EXPECT_EQ(-1, i257.extractBits(128, 128).getSExtValue());
+ EXPECT_EQ(-1, i257.extractBits(66, 191).getSExtValue());
+ EXPECT_EQ(static_cast<int64_t>(0xFFFFFFFFFF80007Full),
+ i257.extractBits(128, 1).getSExtValue());
+ EXPECT_EQ(static_cast<int64_t>(0xFFFFFFFFFF80007Full),
+ i257.extractBits(129, 1).getSExtValue());
+
+ EXPECT_EQ(APInt(48, 0),
+ APInt(144, "281474976710655", 10).extractBits(48, 48));
+ EXPECT_EQ(APInt(48, 0x0000ffffffffffffull),
+ APInt(144, "281474976710655", 10).extractBits(48, 0));
+ EXPECT_EQ(APInt(48, 0x00007fffffffffffull),
+ APInt(144, "281474976710655", 10).extractBits(48, 1));
+}
+
+TEST(APIntTest, getLowBitsSet) {
+ APInt i128lo64 = APInt::getLowBitsSet(128, 64);
+ EXPECT_EQ(0u, i128lo64.countLeadingOnes());
+ EXPECT_EQ(64u, i128lo64.countLeadingZeros());
+ EXPECT_EQ(64u, i128lo64.getActiveBits());
+ EXPECT_EQ(0u, i128lo64.countTrailingZeros());
+ EXPECT_EQ(64u, i128lo64.countTrailingOnes());
+ EXPECT_EQ(64u, i128lo64.countPopulation());
+}
+
+TEST(APIntTest, getBitsSet) {
+ APInt i64hi1lo1 = APInt::getBitsSet(64, 1, 63);
+ EXPECT_EQ(0u, i64hi1lo1.countLeadingOnes());
+ EXPECT_EQ(1u, i64hi1lo1.countLeadingZeros());
+ EXPECT_EQ(63u, i64hi1lo1.getActiveBits());
+ EXPECT_EQ(1u, i64hi1lo1.countTrailingZeros());
+ EXPECT_EQ(0u, i64hi1lo1.countTrailingOnes());
+ EXPECT_EQ(62u, i64hi1lo1.countPopulation());
+
+ APInt i127hi1lo1 = APInt::getBitsSet(127, 1, 126);
+ EXPECT_EQ(0u, i127hi1lo1.countLeadingOnes());
+ EXPECT_EQ(1u, i127hi1lo1.countLeadingZeros());
+ EXPECT_EQ(126u, i127hi1lo1.getActiveBits());
+ EXPECT_EQ(1u, i127hi1lo1.countTrailingZeros());
+ EXPECT_EQ(0u, i127hi1lo1.countTrailingOnes());
+ EXPECT_EQ(125u, i127hi1lo1.countPopulation());
+}
+
+TEST(APIntTest, getHighBitsSet) {
+ APInt i64hi32 = APInt::getHighBitsSet(64, 32);
+ EXPECT_EQ(32u, i64hi32.countLeadingOnes());
+ EXPECT_EQ(0u, i64hi32.countLeadingZeros());
+ EXPECT_EQ(64u, i64hi32.getActiveBits());
+ EXPECT_EQ(32u, i64hi32.countTrailingZeros());
+ EXPECT_EQ(0u, i64hi32.countTrailingOnes());
+ EXPECT_EQ(32u, i64hi32.countPopulation());
+}
+
+TEST(APIntTest, getBitsSetFrom) {
+ APInt i64hi31 = APInt::getBitsSetFrom(64, 33);
+ EXPECT_EQ(31u, i64hi31.countLeadingOnes());
+ EXPECT_EQ(0u, i64hi31.countLeadingZeros());
+ EXPECT_EQ(64u, i64hi31.getActiveBits());
+ EXPECT_EQ(33u, i64hi31.countTrailingZeros());
+ EXPECT_EQ(0u, i64hi31.countTrailingOnes());
+ EXPECT_EQ(31u, i64hi31.countPopulation());
+}
+
+TEST(APIntTest, setLowBits) {
+ APInt i64lo32(64, 0);
+ i64lo32.setLowBits(32);
+ EXPECT_EQ(0u, i64lo32.countLeadingOnes());
+ EXPECT_EQ(32u, i64lo32.countLeadingZeros());
+ EXPECT_EQ(32u, i64lo32.getActiveBits());
+ EXPECT_EQ(0u, i64lo32.countTrailingZeros());
+ EXPECT_EQ(32u, i64lo32.countTrailingOnes());
+ EXPECT_EQ(32u, i64lo32.countPopulation());
+
+ APInt i128lo64(128, 0);
+ i128lo64.setLowBits(64);
+ EXPECT_EQ(0u, i128lo64.countLeadingOnes());
+ EXPECT_EQ(64u, i128lo64.countLeadingZeros());
+ EXPECT_EQ(64u, i128lo64.getActiveBits());
+ EXPECT_EQ(0u, i128lo64.countTrailingZeros());
+ EXPECT_EQ(64u, i128lo64.countTrailingOnes());
+ EXPECT_EQ(64u, i128lo64.countPopulation());
+
+ APInt i128lo24(128, 0);
+ i128lo24.setLowBits(24);
+ EXPECT_EQ(0u, i128lo24.countLeadingOnes());
+ EXPECT_EQ(104u, i128lo24.countLeadingZeros());
+ EXPECT_EQ(24u, i128lo24.getActiveBits());
+ EXPECT_EQ(0u, i128lo24.countTrailingZeros());
+ EXPECT_EQ(24u, i128lo24.countTrailingOnes());
+ EXPECT_EQ(24u, i128lo24.countPopulation());
+
+ APInt i128lo104(128, 0);
+ i128lo104.setLowBits(104);
+ EXPECT_EQ(0u, i128lo104.countLeadingOnes());
+ EXPECT_EQ(24u, i128lo104.countLeadingZeros());
+ EXPECT_EQ(104u, i128lo104.getActiveBits());
+ EXPECT_EQ(0u, i128lo104.countTrailingZeros());
+ EXPECT_EQ(104u, i128lo104.countTrailingOnes());
+ EXPECT_EQ(104u, i128lo104.countPopulation());
+
+ APInt i128lo0(128, 0);
+ i128lo0.setLowBits(0);
+ EXPECT_EQ(0u, i128lo0.countLeadingOnes());
+ EXPECT_EQ(128u, i128lo0.countLeadingZeros());
+ EXPECT_EQ(0u, i128lo0.getActiveBits());
+ EXPECT_EQ(128u, i128lo0.countTrailingZeros());
+ EXPECT_EQ(0u, i128lo0.countTrailingOnes());
+ EXPECT_EQ(0u, i128lo0.countPopulation());
+
+ APInt i80lo79(80, 0);
+ i80lo79.setLowBits(79);
+ EXPECT_EQ(0u, i80lo79.countLeadingOnes());
+ EXPECT_EQ(1u, i80lo79.countLeadingZeros());
+ EXPECT_EQ(79u, i80lo79.getActiveBits());
+ EXPECT_EQ(0u, i80lo79.countTrailingZeros());
+ EXPECT_EQ(79u, i80lo79.countTrailingOnes());
+ EXPECT_EQ(79u, i80lo79.countPopulation());
+}
+
+TEST(APIntTest, setHighBits) {
+ APInt i64hi32(64, 0);
+ i64hi32.setHighBits(32);
+ EXPECT_EQ(32u, i64hi32.countLeadingOnes());
+ EXPECT_EQ(0u, i64hi32.countLeadingZeros());
+ EXPECT_EQ(64u, i64hi32.getActiveBits());
+ EXPECT_EQ(32u, i64hi32.countTrailingZeros());
+ EXPECT_EQ(0u, i64hi32.countTrailingOnes());
+ EXPECT_EQ(32u, i64hi32.countPopulation());
+
+ APInt i128hi64(128, 0);
+ i128hi64.setHighBits(64);
+ EXPECT_EQ(64u, i128hi64.countLeadingOnes());
+ EXPECT_EQ(0u, i128hi64.countLeadingZeros());
+ EXPECT_EQ(128u, i128hi64.getActiveBits());
+ EXPECT_EQ(64u, i128hi64.countTrailingZeros());
+ EXPECT_EQ(0u, i128hi64.countTrailingOnes());
+ EXPECT_EQ(64u, i128hi64.countPopulation());
+
+ APInt i128hi24(128, 0);
+ i128hi24.setHighBits(24);
+ EXPECT_EQ(24u, i128hi24.countLeadingOnes());
+ EXPECT_EQ(0u, i128hi24.countLeadingZeros());
+ EXPECT_EQ(128u, i128hi24.getActiveBits());
+ EXPECT_EQ(104u, i128hi24.countTrailingZeros());
+ EXPECT_EQ(0u, i128hi24.countTrailingOnes());
+ EXPECT_EQ(24u, i128hi24.countPopulation());
+
+ APInt i128hi104(128, 0);
+ i128hi104.setHighBits(104);
+ EXPECT_EQ(104u, i128hi104.countLeadingOnes());
+ EXPECT_EQ(0u, i128hi104.countLeadingZeros());
+ EXPECT_EQ(128u, i128hi104.getActiveBits());
+ EXPECT_EQ(24u, i128hi104.countTrailingZeros());
+ EXPECT_EQ(0u, i128hi104.countTrailingOnes());
+ EXPECT_EQ(104u, i128hi104.countPopulation());
+
+ APInt i128hi0(128, 0);
+ i128hi0.setHighBits(0);
+ EXPECT_EQ(0u, i128hi0.countLeadingOnes());
+ EXPECT_EQ(128u, i128hi0.countLeadingZeros());
+ EXPECT_EQ(0u, i128hi0.getActiveBits());
+ EXPECT_EQ(128u, i128hi0.countTrailingZeros());
+ EXPECT_EQ(0u, i128hi0.countTrailingOnes());
+ EXPECT_EQ(0u, i128hi0.countPopulation());
+
+ APInt i80hi1(80, 0);
+ i80hi1.setHighBits(1);
+ EXPECT_EQ(1u, i80hi1.countLeadingOnes());
+ EXPECT_EQ(0u, i80hi1.countLeadingZeros());
+ EXPECT_EQ(80u, i80hi1.getActiveBits());
+ EXPECT_EQ(79u, i80hi1.countTrailingZeros());
+ EXPECT_EQ(0u, i80hi1.countTrailingOnes());
+ EXPECT_EQ(1u, i80hi1.countPopulation());
+
+ APInt i32hi16(32, 0);
+ i32hi16.setHighBits(16);
+ EXPECT_EQ(16u, i32hi16.countLeadingOnes());
+ EXPECT_EQ(0u, i32hi16.countLeadingZeros());
+ EXPECT_EQ(32u, i32hi16.getActiveBits());
+ EXPECT_EQ(16u, i32hi16.countTrailingZeros());
+ EXPECT_EQ(0u, i32hi16.countTrailingOnes());
+ EXPECT_EQ(16u, i32hi16.countPopulation());
+}
+
+TEST(APIntTest, setBitsFrom) {
+ APInt i64from63(64, 0);
+ i64from63.setBitsFrom(63);
+ EXPECT_EQ(1u, i64from63.countLeadingOnes());
+ EXPECT_EQ(0u, i64from63.countLeadingZeros());
+ EXPECT_EQ(64u, i64from63.getActiveBits());
+ EXPECT_EQ(63u, i64from63.countTrailingZeros());
+ EXPECT_EQ(0u, i64from63.countTrailingOnes());
+ EXPECT_EQ(1u, i64from63.countPopulation());
+}
+
+TEST(APIntTest, setAllBits) {
+ APInt i32(32, 0);
+ i32.setAllBits();
+ EXPECT_EQ(32u, i32.countLeadingOnes());
+ EXPECT_EQ(0u, i32.countLeadingZeros());
+ EXPECT_EQ(32u, i32.getActiveBits());
+ EXPECT_EQ(0u, i32.countTrailingZeros());
+ EXPECT_EQ(32u, i32.countTrailingOnes());
+ EXPECT_EQ(32u, i32.countPopulation());
+
+ APInt i64(64, 0);
+ i64.setAllBits();
+ EXPECT_EQ(64u, i64.countLeadingOnes());
+ EXPECT_EQ(0u, i64.countLeadingZeros());
+ EXPECT_EQ(64u, i64.getActiveBits());
+ EXPECT_EQ(0u, i64.countTrailingZeros());
+ EXPECT_EQ(64u, i64.countTrailingOnes());
+ EXPECT_EQ(64u, i64.countPopulation());
+
+ APInt i96(96, 0);
+ i96.setAllBits();
+ EXPECT_EQ(96u, i96.countLeadingOnes());
+ EXPECT_EQ(0u, i96.countLeadingZeros());
+ EXPECT_EQ(96u, i96.getActiveBits());
+ EXPECT_EQ(0u, i96.countTrailingZeros());
+ EXPECT_EQ(96u, i96.countTrailingOnes());
+ EXPECT_EQ(96u, i96.countPopulation());
+
+ APInt i128(128, 0);
+ i128.setAllBits();
+ EXPECT_EQ(128u, i128.countLeadingOnes());
+ EXPECT_EQ(0u, i128.countLeadingZeros());
+ EXPECT_EQ(128u, i128.getActiveBits());
+ EXPECT_EQ(0u, i128.countTrailingZeros());
+ EXPECT_EQ(128u, i128.countTrailingOnes());
+ EXPECT_EQ(128u, i128.countPopulation());
+}
+
+TEST(APIntTest, getLoBits) {
+ APInt i32(32, 0xfa);
+ i32.setHighBits(1);
+ EXPECT_EQ(0xa, i32.getLoBits(4));
+ APInt i128(128, 0xfa);
+ i128.setHighBits(1);
+ EXPECT_EQ(0xa, i128.getLoBits(4));
+}
+
+TEST(APIntTest, getHiBits) {
+ APInt i32(32, 0xfa);
+ i32.setHighBits(2);
+ EXPECT_EQ(0xc, i32.getHiBits(4));
+ APInt i128(128, 0xfa);
+ i128.setHighBits(2);
+ EXPECT_EQ(0xc, i128.getHiBits(4));
+}
+
+TEST(APIntTest, GCD) {
+ using APIntOps::GreatestCommonDivisor;
+
+ for (unsigned Bits : {1, 2, 32, 63, 64, 65}) {
+ // Test some corner cases near zero.
+ APInt Zero(Bits, 0), One(Bits, 1);
+ EXPECT_EQ(GreatestCommonDivisor(Zero, Zero), Zero);
+ EXPECT_EQ(GreatestCommonDivisor(Zero, One), One);
+ EXPECT_EQ(GreatestCommonDivisor(One, Zero), One);
+ EXPECT_EQ(GreatestCommonDivisor(One, One), One);
+
+ if (Bits > 1) {
+ APInt Two(Bits, 2);
+ EXPECT_EQ(GreatestCommonDivisor(Zero, Two), Two);
+ EXPECT_EQ(GreatestCommonDivisor(One, Two), One);
+ EXPECT_EQ(GreatestCommonDivisor(Two, Two), Two);
+
+ // Test some corner cases near the highest representable value.
+ APInt Max(Bits, 0);
+ Max.setAllBits();
+ EXPECT_EQ(GreatestCommonDivisor(Zero, Max), Max);
+ EXPECT_EQ(GreatestCommonDivisor(One, Max), One);
+ EXPECT_EQ(GreatestCommonDivisor(Two, Max), One);
+ EXPECT_EQ(GreatestCommonDivisor(Max, Max), Max);
+
+ APInt MaxOver2 = Max.udiv(Two);
+ EXPECT_EQ(GreatestCommonDivisor(MaxOver2, Max), One);
+ // Max - 1 == Max / 2 * 2, because Max is odd.
+ EXPECT_EQ(GreatestCommonDivisor(MaxOver2, Max - 1), MaxOver2);
+ }
+ }
+
+ // Compute the 20th Mersenne prime.
+ const unsigned BitWidth = 4450;
+ APInt HugePrime = APInt::getLowBitsSet(BitWidth, 4423);
+
+ // 9931 and 123456 are coprime.
+ APInt A = HugePrime * APInt(BitWidth, 9931);
+ APInt B = HugePrime * APInt(BitWidth, 123456);
+ APInt C = GreatestCommonDivisor(A, B);
+ EXPECT_EQ(C, HugePrime);
+}
+
+TEST(APIntTest, LogicalRightShift) {
+ APInt i256(APInt::getHighBitsSet(256, 2));
+
+ i256.lshrInPlace(1);
+ EXPECT_EQ(1U, i256.countLeadingZeros());
+ EXPECT_EQ(253U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256.lshrInPlace(62);
+ EXPECT_EQ(63U, i256.countLeadingZeros());
+ EXPECT_EQ(191U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256.lshrInPlace(65);
+ EXPECT_EQ(128U, i256.countLeadingZeros());
+ EXPECT_EQ(126U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256.lshrInPlace(64);
+ EXPECT_EQ(192U, i256.countLeadingZeros());
+ EXPECT_EQ(62U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256.lshrInPlace(63);
+ EXPECT_EQ(255U, i256.countLeadingZeros());
+ EXPECT_EQ(0U, i256.countTrailingZeros());
+ EXPECT_EQ(1U, i256.countPopulation());
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt neg_one(128, static_cast<uint64_t>(-1), true);
+ EXPECT_EQ(0, neg_one.lshr(128));
+}
+
+TEST(APIntTest, ArithmeticRightShift) {
+ APInt i72(APInt::getHighBitsSet(72, 1));
+ i72.ashrInPlace(46);
+ EXPECT_EQ(47U, i72.countLeadingOnes());
+ EXPECT_EQ(25U, i72.countTrailingZeros());
+ EXPECT_EQ(47U, i72.countPopulation());
+
+ i72 = APInt::getHighBitsSet(72, 1);
+ i72.ashrInPlace(64);
+ EXPECT_EQ(65U, i72.countLeadingOnes());
+ EXPECT_EQ(7U, i72.countTrailingZeros());
+ EXPECT_EQ(65U, i72.countPopulation());
+
+ APInt i128(APInt::getHighBitsSet(128, 1));
+ i128.ashrInPlace(64);
+ EXPECT_EQ(65U, i128.countLeadingOnes());
+ EXPECT_EQ(63U, i128.countTrailingZeros());
+ EXPECT_EQ(65U, i128.countPopulation());
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt signmin32(APInt::getSignedMinValue(32));
+ EXPECT_TRUE(signmin32.ashr(32).isAllOnesValue());
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt umax32(APInt::getSignedMaxValue(32));
+ EXPECT_EQ(0, umax32.ashr(32));
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt signmin128(APInt::getSignedMinValue(128));
+ EXPECT_TRUE(signmin128.ashr(128).isAllOnesValue());
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt umax128(APInt::getSignedMaxValue(128));
+ EXPECT_EQ(0, umax128.ashr(128));
+}
+
+TEST(APIntTest, LeftShift) {
+ APInt i256(APInt::getLowBitsSet(256, 2));
+
+ i256 <<= 1;
+ EXPECT_EQ(253U, i256.countLeadingZeros());
+ EXPECT_EQ(1U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256 <<= 62;
+ EXPECT_EQ(191U, i256.countLeadingZeros());
+ EXPECT_EQ(63U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256 <<= 65;
+ EXPECT_EQ(126U, i256.countLeadingZeros());
+ EXPECT_EQ(128U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256 <<= 64;
+ EXPECT_EQ(62U, i256.countLeadingZeros());
+ EXPECT_EQ(192U, i256.countTrailingZeros());
+ EXPECT_EQ(2U, i256.countPopulation());
+
+ i256 <<= 63;
+ EXPECT_EQ(0U, i256.countLeadingZeros());
+ EXPECT_EQ(255U, i256.countTrailingZeros());
+ EXPECT_EQ(1U, i256.countPopulation());
+
+ // Ensure we handle large shifts of multi-word.
+ const APInt neg_one(128, static_cast<uint64_t>(-1), true);
+ EXPECT_EQ(0, neg_one.shl(128));
+}
+
+TEST(APIntTest, isSubsetOf) {
+ APInt i32_1(32, 1);
+ APInt i32_2(32, 2);
+ APInt i32_3(32, 3);
+ EXPECT_FALSE(i32_3.isSubsetOf(i32_1));
+ EXPECT_TRUE(i32_1.isSubsetOf(i32_3));
+ EXPECT_FALSE(i32_2.isSubsetOf(i32_1));
+ EXPECT_FALSE(i32_1.isSubsetOf(i32_2));
+ EXPECT_TRUE(i32_3.isSubsetOf(i32_3));
+
+ APInt i128_1(128, 1);
+ APInt i128_2(128, 2);
+ APInt i128_3(128, 3);
+ EXPECT_FALSE(i128_3.isSubsetOf(i128_1));
+ EXPECT_TRUE(i128_1.isSubsetOf(i128_3));
+ EXPECT_FALSE(i128_2.isSubsetOf(i128_1));
+ EXPECT_FALSE(i128_1.isSubsetOf(i128_2));
+ EXPECT_TRUE(i128_3.isSubsetOf(i128_3));
+
+ i128_1 <<= 64;
+ i128_2 <<= 64;
+ i128_3 <<= 64;
+ EXPECT_FALSE(i128_3.isSubsetOf(i128_1));
+ EXPECT_TRUE(i128_1.isSubsetOf(i128_3));
+ EXPECT_FALSE(i128_2.isSubsetOf(i128_1));
+ EXPECT_FALSE(i128_1.isSubsetOf(i128_2));
+ EXPECT_TRUE(i128_3.isSubsetOf(i128_3));
+}
+
+TEST(APIntTest, sext) {
+ EXPECT_EQ(0, APInt(1, 0).sext(64));
+ EXPECT_EQ(~uint64_t(0), APInt(1, 1).sext(64));
+
+ APInt i32_max(APInt::getSignedMaxValue(32).sext(63));
+ EXPECT_EQ(32U, i32_max.countLeadingZeros());
+ EXPECT_EQ(0U, i32_max.countTrailingZeros());
+ EXPECT_EQ(31U, i32_max.countPopulation());
+
+ APInt i32_min(APInt::getSignedMinValue(32).sext(63));
+ EXPECT_EQ(32U, i32_min.countLeadingOnes());
+ EXPECT_EQ(31U, i32_min.countTrailingZeros());
+ EXPECT_EQ(32U, i32_min.countPopulation());
+
+ APInt i32_neg1(APInt(32, ~uint64_t(0)).sext(63));
+ EXPECT_EQ(63U, i32_neg1.countLeadingOnes());
+ EXPECT_EQ(0U, i32_neg1.countTrailingZeros());
+ EXPECT_EQ(63U, i32_neg1.countPopulation());
+}
+
+TEST(APIntTest, multiply) {
+ APInt i64(64, 1234);
+
+ EXPECT_EQ(7006652, i64 * 5678);
+ EXPECT_EQ(7006652, 5678 * i64);
+
+ APInt i128 = APInt::getOneBitSet(128, 64);
+ APInt i128_1234(128, 1234);
+ i128_1234 <<= 64;
+ EXPECT_EQ(i128_1234, i128 * 1234);
+ EXPECT_EQ(i128_1234, 1234 * i128);
+
+ APInt i96 = APInt::getOneBitSet(96, 64);
+ i96 *= ~0ULL;
+ EXPECT_EQ(32U, i96.countLeadingOnes());
+ EXPECT_EQ(32U, i96.countPopulation());
+ EXPECT_EQ(64U, i96.countTrailingZeros());
+}
+
+TEST(APIntTest, RoundingUDiv) {
+ for (uint64_t Ai = 1; Ai <= 255; Ai++) {
+ APInt A(8, Ai);
+ APInt Zero(8, 0);
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::UP));
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::DOWN));
+ EXPECT_EQ(0, APIntOps::RoundingUDiv(Zero, A, APInt::Rounding::TOWARD_ZERO));
+
+ for (uint64_t Bi = 1; Bi <= 255; Bi++) {
+ APInt B(8, Bi);
+ {
+ APInt Quo = APIntOps::RoundingUDiv(A, B, APInt::Rounding::UP);
+ auto Prod = Quo.zext(16) * B.zext(16);
+ EXPECT_TRUE(Prod.uge(Ai));
+ if (Prod.ugt(Ai)) {
+ EXPECT_TRUE(((Quo - 1).zext(16) * B.zext(16)).ult(Ai));
+ }
+ }
+ {
+ APInt Quo = A.udiv(B);
+ EXPECT_EQ(Quo, APIntOps::RoundingUDiv(A, B, APInt::Rounding::TOWARD_ZERO));
+ EXPECT_EQ(Quo, APIntOps::RoundingUDiv(A, B, APInt::Rounding::DOWN));
+ }
+ }
+ }
+}
+
+TEST(APIntTest, RoundingSDiv) {
+ for (int64_t Ai = -128; Ai <= 127; Ai++) {
+ APInt A(8, Ai);
+
+ if (Ai != 0) {
+ APInt Zero(8, 0);
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::UP));
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::DOWN));
+ EXPECT_EQ(0, APIntOps::RoundingSDiv(Zero, A, APInt::Rounding::TOWARD_ZERO));
+ }
+
+ for (uint64_t Bi = -128; Bi <= 127; Bi++) {
+ if (Bi == 0)
+ continue;
+
+ APInt B(8, Bi);
+ {
+ APInt Quo = APIntOps::RoundingSDiv(A, B, APInt::Rounding::UP);
+ auto Prod = Quo.sext(16) * B.sext(16);
+ EXPECT_TRUE(Prod.uge(A));
+ if (Prod.ugt(A)) {
+ EXPECT_TRUE(((Quo - 1).sext(16) * B.sext(16)).ult(A));
+ }
+ }
+ {
+ APInt Quo = APIntOps::RoundingSDiv(A, B, APInt::Rounding::DOWN);
+ auto Prod = Quo.sext(16) * B.sext(16);
+ EXPECT_TRUE(Prod.ule(A));
+ if (Prod.ult(A)) {
+ EXPECT_TRUE(((Quo + 1).sext(16) * B.sext(16)).ugt(A));
+ }
+ }
+ {
+ APInt Quo = A.sdiv(B);
+ EXPECT_EQ(Quo, APIntOps::RoundingSDiv(A, B, APInt::Rounding::TOWARD_ZERO));
+ }
+ }
+ }
+}
+
+TEST(APIntTest, SolveQuadraticEquationWrap) {
+ // Verify that "Solution" is the first non-negative integer that solves
+ // Ax^2 + Bx + C = "0 or overflow", i.e. that it is a correct solution
+ // as calculated by SolveQuadraticEquationWrap.
+ auto Validate = [] (int A, int B, int C, unsigned Width, int Solution) {
+ int Mask = (1 << Width) - 1;
+
+ // Solution should be non-negative.
+ EXPECT_GE(Solution, 0);
+
+ auto OverflowBits = [] (int64_t V, unsigned W) {
+ return V & -(1 << W);
+ };
+
+ int64_t Over0 = OverflowBits(C, Width);
+
+ auto IsZeroOrOverflow = [&] (int X) {
+ int64_t ValueAtX = A*X*X + B*X + C;
+ int64_t OverX = OverflowBits(ValueAtX, Width);
+ return (ValueAtX & Mask) == 0 || OverX != Over0;
+ };
+
+ auto EquationToString = [&] (const char *X_str) {
+ return (Twine(A) + Twine(X_str) + Twine("^2 + ") + Twine(B) +
+ Twine(X_str) + Twine(" + ") + Twine(C) + Twine(", bitwidth: ") +
+ Twine(Width)).str();
+ };
+
+ auto IsSolution = [&] (const char *X_str, int X) {
+ if (IsZeroOrOverflow(X))
+ return ::testing::AssertionSuccess()
+ << X << " is a solution of " << EquationToString(X_str);
+ return ::testing::AssertionFailure()
+ << X << " is not an expected solution of "
+ << EquationToString(X_str);
+ };
+
+ auto IsNotSolution = [&] (const char *X_str, int X) {
+ if (!IsZeroOrOverflow(X))
+ return ::testing::AssertionSuccess()
+ << X << " is not a solution of " << EquationToString(X_str);
+ return ::testing::AssertionFailure()
+ << X << " is an unexpected solution of "
+ << EquationToString(X_str);
+ };
+
+ // This is the important part: make sure that there is no solution that
+ // is less than the calculated one.
+ if (Solution > 0) {
+ for (int X = 1; X < Solution-1; ++X)
+ EXPECT_PRED_FORMAT1(IsNotSolution, X);
+ }
+
+ // Verify that the calculated solution is indeed a solution.
+ EXPECT_PRED_FORMAT1(IsSolution, Solution);
+ };
+
+ // Generate all possible quadratic equations with Width-bit wide integer
+ // coefficients, get the solution from SolveQuadraticEquationWrap, and
+ // verify that the solution is correct.
+ auto Iterate = [&] (unsigned Width) {
+ assert(1 < Width && Width < 32);
+ int Low = -(1 << (Width-1));
+ int High = (1 << (Width-1));
+
+ for (int A = Low; A != High; ++A) {
+ if (A == 0)
+ continue;
+ for (int B = Low; B != High; ++B) {
+ for (int C = Low; C != High; ++C) {
+ Optional<APInt> S = APIntOps::SolveQuadraticEquationWrap(
+ APInt(Width, A), APInt(Width, B),
+ APInt(Width, C), Width);
+ if (S.hasValue())
+ Validate(A, B, C, Width, S->getSExtValue());
+ }
+ }
+ }
+ };
+
+ // Test all widths in [2..6].
+ for (unsigned i = 2; i <= 6; ++i)
+ Iterate(i);
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/APSIntTest.cpp b/src/llvm-project/llvm/unittests/ADT/APSIntTest.cpp
new file mode 100644
index 0000000..a9b3071
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/APSIntTest.cpp
@@ -0,0 +1,163 @@
+//===- llvm/unittest/ADT/APSIntTest.cpp - APSInt unit tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/APSInt.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(APSIntTest, MoveTest) {
+ APSInt A(32, true);
+ EXPECT_TRUE(A.isUnsigned());
+
+ APSInt B(128, false);
+ A = B;
+ EXPECT_FALSE(A.isUnsigned());
+
+ APSInt C(B);
+ EXPECT_FALSE(C.isUnsigned());
+
+ APInt Wide(256, 0);
+ const uint64_t *Bits = Wide.getRawData();
+ APSInt D(std::move(Wide));
+ EXPECT_TRUE(D.isUnsigned());
+ EXPECT_EQ(Bits, D.getRawData()); // Verify that "Wide" was really moved.
+
+ A = APSInt(64, true);
+ EXPECT_TRUE(A.isUnsigned());
+
+ Wide = APInt(128, 1);
+ Bits = Wide.getRawData();
+ A = std::move(Wide);
+ EXPECT_TRUE(A.isUnsigned());
+ EXPECT_EQ(Bits, A.getRawData()); // Verify that "Wide" was really moved.
+}
+
+TEST(APSIntTest, get) {
+ EXPECT_TRUE(APSInt::get(7).isSigned());
+ EXPECT_EQ(64u, APSInt::get(7).getBitWidth());
+ EXPECT_EQ(7u, APSInt::get(7).getZExtValue());
+ EXPECT_EQ(7, APSInt::get(7).getSExtValue());
+ EXPECT_TRUE(APSInt::get(-7).isSigned());
+ EXPECT_EQ(64u, APSInt::get(-7).getBitWidth());
+ EXPECT_EQ(-7, APSInt::get(-7).getSExtValue());
+ EXPECT_EQ(UINT64_C(0) - 7, APSInt::get(-7).getZExtValue());
+}
+
+TEST(APSIntTest, getUnsigned) {
+ EXPECT_TRUE(APSInt::getUnsigned(7).isUnsigned());
+ EXPECT_EQ(64u, APSInt::getUnsigned(7).getBitWidth());
+ EXPECT_EQ(7u, APSInt::getUnsigned(7).getZExtValue());
+ EXPECT_EQ(7, APSInt::getUnsigned(7).getSExtValue());
+ EXPECT_TRUE(APSInt::getUnsigned(-7).isUnsigned());
+ EXPECT_EQ(64u, APSInt::getUnsigned(-7).getBitWidth());
+ EXPECT_EQ(-7, APSInt::getUnsigned(-7).getSExtValue());
+ EXPECT_EQ(UINT64_C(0) - 7, APSInt::getUnsigned(-7).getZExtValue());
+}
+
+TEST(APSIntTest, getExtValue) {
+ EXPECT_TRUE(APSInt(APInt(3, 7), true).isUnsigned());
+ EXPECT_TRUE(APSInt(APInt(3, 7), false).isSigned());
+ EXPECT_TRUE(APSInt(APInt(4, 7), true).isUnsigned());
+ EXPECT_TRUE(APSInt(APInt(4, 7), false).isSigned());
+ EXPECT_TRUE(APSInt(APInt(4, -7), true).isUnsigned());
+ EXPECT_TRUE(APSInt(APInt(4, -7), false).isSigned());
+ EXPECT_EQ(7, APSInt(APInt(3, 7), true).getExtValue());
+ EXPECT_EQ(-1, APSInt(APInt(3, 7), false).getExtValue());
+ EXPECT_EQ(7, APSInt(APInt(4, 7), true).getExtValue());
+ EXPECT_EQ(7, APSInt(APInt(4, 7), false).getExtValue());
+ EXPECT_EQ(9, APSInt(APInt(4, -7), true).getExtValue());
+ EXPECT_EQ(-7, APSInt(APInt(4, -7), false).getExtValue());
+}
+
+TEST(APSIntTest, compareValues) {
+ auto U = [](uint64_t V) { return APSInt::getUnsigned(V); };
+ auto S = [](int64_t V) { return APSInt::get(V); };
+
+ // Bit-width matches and is-signed.
+ EXPECT_TRUE(APSInt::compareValues(S(7), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8), S(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(7), S(7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8), S(-7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-8)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-8), S(-7)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7)) == 0);
+
+ // Bit-width matches and not is-signed.
+ EXPECT_TRUE(APSInt::compareValues(U(7), U(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), U(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7), U(7)) == 0);
+
+ // Bit-width matches and mixed signs.
+ EXPECT_TRUE(APSInt::compareValues(U(7), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), S(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7), S(7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), S(-7)) > 0);
+
+ // Bit-width mismatch and is-signed.
+ EXPECT_TRUE(APSInt::compareValues(S(7).trunc(32), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8).trunc(32), S(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(7).trunc(32), S(7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8).trunc(32), S(-7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-8)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-8).trunc(32), S(-7)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7).trunc(32), S(-7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(7), S(8).trunc(32)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8), S(7).trunc(32)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(7), S(7).trunc(32)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(8).trunc(32)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(8), S(-7).trunc(32)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7).trunc(32)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-8).trunc(32)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-8), S(-7).trunc(32)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(S(-7), S(-7).trunc(32)) == 0);
+
+ // Bit-width mismatch and not is-signed.
+ EXPECT_TRUE(APSInt::compareValues(U(7), U(8).trunc(32)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), U(7).trunc(32)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7), U(7).trunc(32)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), U(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), U(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), U(7)) == 0);
+
+ // Bit-width mismatch and mixed signs.
+ EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), S(8)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), S(7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7).trunc(32), S(7)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8).trunc(32), S(-7)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7), S(8).trunc(32)) < 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), S(7).trunc(32)) > 0);
+ EXPECT_TRUE(APSInt::compareValues(U(7), S(7).trunc(32)) == 0);
+ EXPECT_TRUE(APSInt::compareValues(U(8), S(-7).trunc(32)) > 0);
+}
+
+TEST(APSIntTest, FromString) {
+ EXPECT_EQ(APSInt("1").getExtValue(), 1);
+ EXPECT_EQ(APSInt("-1").getExtValue(), -1);
+ EXPECT_EQ(APSInt("0").getExtValue(), 0);
+ EXPECT_EQ(APSInt("56789").getExtValue(), 56789);
+ EXPECT_EQ(APSInt("-1234").getExtValue(), -1234);
+}
+
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
+
+TEST(APSIntTest, StringDeath) {
+ EXPECT_DEATH(APSInt(""), "Invalid string length");
+ EXPECT_DEATH(APSInt("1a"), "Invalid character in digit string");
+}
+
+#endif
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/AnyTest.cpp b/src/llvm-project/llvm/unittests/ADT/AnyTest.cpp
new file mode 100644
index 0000000..658f6b6
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/AnyTest.cpp
@@ -0,0 +1,175 @@
+//===- llvm/unittest/Support/AnyTest.cpp - Any tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Any.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+namespace {
+
+// Make sure we can construct, copy-construct, move-construct, and assign Any's.
+TEST(AnyTest, ConstructionAndAssignment) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{8};
+ llvm::Any D{"hello"};
+ llvm::Any E{3.7};
+
+ // An empty Any is not anything.
+ EXPECT_FALSE(A.hasValue());
+ EXPECT_FALSE(any_isa<int>(A));
+
+ // An int is an int but not something else.
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_TRUE(any_isa<int>(B));
+ EXPECT_FALSE(any_isa<float>(B));
+
+ EXPECT_TRUE(C.hasValue());
+ EXPECT_TRUE(any_isa<int>(C));
+
+ // A const char * is a const char * but not an int.
+ EXPECT_TRUE(D.hasValue());
+ EXPECT_TRUE(any_isa<const char *>(D));
+ EXPECT_FALSE(any_isa<int>(D));
+
+ // A double is a double but not a float.
+ EXPECT_TRUE(E.hasValue());
+ EXPECT_TRUE(any_isa<double>(E));
+ EXPECT_FALSE(any_isa<float>(E));
+
+ // After copy constructing from an int, the new item and old item are both
+ // ints.
+ llvm::Any F(B);
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_TRUE(F.hasValue());
+ EXPECT_TRUE(any_isa<int>(F));
+ EXPECT_TRUE(any_isa<int>(B));
+
+ // After move constructing from an int, the new item is an int and the old one
+ // isn't.
+ llvm::Any G(std::move(C));
+ EXPECT_FALSE(C.hasValue());
+ EXPECT_TRUE(G.hasValue());
+ EXPECT_TRUE(any_isa<int>(G));
+ EXPECT_FALSE(any_isa<int>(C));
+
+ // After copy-assigning from an int, the new item and old item are both ints.
+ A = F;
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_TRUE(F.hasValue());
+ EXPECT_TRUE(any_isa<int>(A));
+ EXPECT_TRUE(any_isa<int>(F));
+
+ // After move-assigning from an int, the new item and old item are both ints.
+ B = std::move(G);
+ EXPECT_TRUE(B.hasValue());
+ EXPECT_FALSE(G.hasValue());
+ EXPECT_TRUE(any_isa<int>(B));
+ EXPECT_FALSE(any_isa<int>(G));
+}
+
+TEST(AnyTest, GoodAnyCast) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{8};
+ llvm::Any D{"hello"};
+ llvm::Any E{'x'};
+
+ // Check each value twice to make sure it isn't damaged by the cast.
+ EXPECT_EQ(7, llvm::any_cast<int>(B));
+ EXPECT_EQ(7, llvm::any_cast<int>(B));
+
+ EXPECT_STREQ("hello", llvm::any_cast<const char *>(D));
+ EXPECT_STREQ("hello", llvm::any_cast<const char *>(D));
+
+ EXPECT_EQ('x', llvm::any_cast<char>(E));
+ EXPECT_EQ('x', llvm::any_cast<char>(E));
+
+ llvm::Any F(B);
+ EXPECT_EQ(7, llvm::any_cast<int>(F));
+ EXPECT_EQ(7, llvm::any_cast<int>(F));
+
+ llvm::Any G(std::move(C));
+ EXPECT_EQ(8, llvm::any_cast<int>(G));
+ EXPECT_EQ(8, llvm::any_cast<int>(G));
+
+ A = F;
+ EXPECT_EQ(7, llvm::any_cast<int>(A));
+ EXPECT_EQ(7, llvm::any_cast<int>(A));
+
+ E = std::move(G);
+ EXPECT_EQ(8, llvm::any_cast<int>(E));
+ EXPECT_EQ(8, llvm::any_cast<int>(E));
+
+ // Make sure we can any_cast from an rvalue and that it's properly destroyed
+ // in the process.
+ EXPECT_EQ(8, llvm::any_cast<int>(std::move(E)));
+ EXPECT_TRUE(E.hasValue());
+
+ // Make sure moving from pointers gives back pointers, and that we can modify
+ // the underlying value through those pointers.
+ EXPECT_EQ(7, *llvm::any_cast<int>(&A));
+ int *N = llvm::any_cast<int>(&A);
+ *N = 42;
+ EXPECT_EQ(42, llvm::any_cast<int>(A));
+
+ // Make sure that we can any_cast to a reference and this is considered a good
+ // cast, resulting in an lvalue which can be modified.
+ llvm::any_cast<int &>(A) = 43;
+ EXPECT_EQ(43, llvm::any_cast<int>(A));
+}
+
+TEST(AnyTest, CopiesAndMoves) {
+ struct TestType {
+ TestType() = default;
+ TestType(const TestType &Other)
+ : Copies(Other.Copies + 1), Moves(Other.Moves) {}
+ TestType(TestType &&Other) : Copies(Other.Copies), Moves(Other.Moves + 1) {}
+ int Copies = 0;
+ int Moves = 0;
+ };
+
+ // One move to get TestType into the Any, and one move on the cast.
+ TestType T1 = llvm::any_cast<TestType>(Any{TestType()});
+ EXPECT_EQ(0, T1.Copies);
+ EXPECT_EQ(2, T1.Moves);
+
+ // One move to get TestType into the Any, and one copy on the cast.
+ Any A{TestType()};
+ TestType T2 = llvm::any_cast<TestType>(A);
+ EXPECT_EQ(1, T2.Copies);
+ EXPECT_EQ(1, T2.Moves);
+
+ // One move to get TestType into the Any, and one move on the cast.
+ TestType T3 = llvm::any_cast<TestType>(std::move(A));
+ EXPECT_EQ(0, T3.Copies);
+ EXPECT_EQ(2, T3.Moves);
+}
+
+TEST(AnyTest, BadAnyCast) {
+ llvm::Any A;
+ llvm::Any B{7};
+ llvm::Any C{"hello"};
+ llvm::Any D{'x'};
+
+#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
+ EXPECT_DEATH(llvm::any_cast<int>(A), "");
+
+ EXPECT_DEATH(llvm::any_cast<float>(B), "");
+ EXPECT_DEATH(llvm::any_cast<int *>(B), "");
+
+ EXPECT_DEATH(llvm::any_cast<std::string>(C), "");
+
+ EXPECT_DEATH(llvm::any_cast<unsigned char>(D), "");
+#endif
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/ArrayRefTest.cpp b/src/llvm-project/llvm/unittests/ADT/ArrayRefTest.cpp
new file mode 100644
index 0000000..e01d212
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/ArrayRefTest.cpp
@@ -0,0 +1,252 @@
+//===- llvm/unittest/ADT/ArrayRefTest.cpp - ArrayRef unit tests -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <limits>
+#include <vector>
+using namespace llvm;
+
+// Check that the ArrayRef-of-pointer converting constructor only allows adding
+// cv qualifiers (not removing them, or otherwise changing the type)
+static_assert(
+ std::is_convertible<ArrayRef<int *>, ArrayRef<const int *>>::value,
+ "Adding const");
+static_assert(
+ std::is_convertible<ArrayRef<int *>, ArrayRef<volatile int *>>::value,
+ "Adding volatile");
+static_assert(!std::is_convertible<ArrayRef<int *>, ArrayRef<float *>>::value,
+ "Changing pointer of one type to a pointer of another");
+static_assert(
+ !std::is_convertible<ArrayRef<const int *>, ArrayRef<int *>>::value,
+ "Removing const");
+static_assert(
+ !std::is_convertible<ArrayRef<volatile int *>, ArrayRef<int *>>::value,
+ "Removing volatile");
+
+// Check that we can't accidentally assign a temporary location to an ArrayRef.
+// (Unfortunately we can't make use of the same thing with constructors.)
+//
+// Disable this check under MSVC; even MSVC 2015 isn't inconsistent between
+// std::is_assignable and actually writing such an assignment.
+#if !defined(_MSC_VER)
+static_assert(
+ !std::is_assignable<ArrayRef<int *>&, int *>::value,
+ "Assigning from single prvalue element");
+static_assert(
+ !std::is_assignable<ArrayRef<int *>&, int * &&>::value,
+ "Assigning from single xvalue element");
+static_assert(
+ std::is_assignable<ArrayRef<int *>&, int * &>::value,
+ "Assigning from single lvalue element");
+static_assert(
+ !std::is_assignable<ArrayRef<int *>&, std::initializer_list<int *>>::value,
+ "Assigning from an initializer list");
+#endif
+
+namespace {
+
+TEST(ArrayRefTest, AllocatorCopy) {
+ BumpPtrAllocator Alloc;
+ static const uint16_t Words1[] = { 1, 4, 200, 37 };
+ ArrayRef<uint16_t> Array1 = makeArrayRef(Words1, 4);
+ static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 };
+ ArrayRef<uint16_t> Array2 = makeArrayRef(Words2, 5);
+ ArrayRef<uint16_t> Array1c = Array1.copy(Alloc);
+ ArrayRef<uint16_t> Array2c = Array2.copy(Alloc);
+ EXPECT_TRUE(Array1.equals(Array1c));
+ EXPECT_NE(Array1.data(), Array1c.data());
+ EXPECT_TRUE(Array2.equals(Array2c));
+ EXPECT_NE(Array2.data(), Array2c.data());
+
+ // Check that copy can cope with uninitialized memory.
+ struct NonAssignable {
+ const char *Ptr;
+
+ NonAssignable(const char *Ptr) : Ptr(Ptr) {}
+ NonAssignable(const NonAssignable &RHS) = default;
+ void operator=(const NonAssignable &RHS) { assert(RHS.Ptr != nullptr); }
+ bool operator==(const NonAssignable &RHS) const { return Ptr == RHS.Ptr; }
+ } Array3Src[] = {"hello", "world"};
+ ArrayRef<NonAssignable> Array3Copy = makeArrayRef(Array3Src).copy(Alloc);
+ EXPECT_EQ(makeArrayRef(Array3Src), Array3Copy);
+ EXPECT_NE(makeArrayRef(Array3Src).data(), Array3Copy.data());
+}
+
+TEST(ArrayRefTest, SizeTSizedOperations) {
+ ArrayRef<char> AR(nullptr, std::numeric_limits<ptrdiff_t>::max());
+
+ // Check that drop_back accepts size_t-sized numbers.
+ EXPECT_EQ(1U, AR.drop_back(AR.size() - 1).size());
+
+ // Check that drop_front accepts size_t-sized numbers.
+ EXPECT_EQ(1U, AR.drop_front(AR.size() - 1).size());
+
+ // Check that slice accepts size_t-sized numbers.
+ EXPECT_EQ(1U, AR.slice(AR.size() - 1).size());
+ EXPECT_EQ(AR.size() - 1, AR.slice(1, AR.size() - 1).size());
+}
+
+TEST(ArrayRefTest, DropBack) {
+ static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> AR2(TheNumbers, AR1.size() - 1);
+ EXPECT_TRUE(AR1.drop_back().equals(AR2));
+}
+
+TEST(ArrayRefTest, DropFront) {
+ static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> AR2(&TheNumbers[2], AR1.size() - 2);
+ EXPECT_TRUE(AR1.drop_front(2).equals(AR2));
+}
+
+TEST(ArrayRefTest, DropWhile) {
+ static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> Expected = AR1.drop_front(3);
+ EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 == 1; }));
+
+ EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; }));
+ EXPECT_EQ(ArrayRef<int>(),
+ AR1.drop_while([](const int &N) { return N > 0; }));
+}
+
+TEST(ArrayRefTest, DropUntil) {
+ static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> Expected = AR1.drop_front(3);
+ EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 == 0; }));
+
+ EXPECT_EQ(ArrayRef<int>(),
+ AR1.drop_until([](const int &N) { return N < 0; }));
+ EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; }));
+}
+
+TEST(ArrayRefTest, TakeBack) {
+ static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> AR2(AR1.end() - 1, 1);
+ EXPECT_TRUE(AR1.take_back().equals(AR2));
+}
+
+TEST(ArrayRefTest, TakeFront) {
+ static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> AR2(AR1.data(), 2);
+ EXPECT_TRUE(AR1.take_front(2).equals(AR2));
+}
+
+TEST(ArrayRefTest, TakeWhile) {
+ static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> Expected = AR1.take_front(3);
+ EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 == 1; }));
+
+ EXPECT_EQ(ArrayRef<int>(),
+ AR1.take_while([](const int &N) { return N < 0; }));
+ EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; }));
+}
+
+TEST(ArrayRefTest, TakeUntil) {
+ static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};
+ ArrayRef<int> AR1(TheNumbers);
+ ArrayRef<int> Expected = AR1.take_front(3);
+ EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 == 0; }));
+
+ EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; }));
+ EXPECT_EQ(ArrayRef<int>(),
+ AR1.take_until([](const int &N) { return N > 0; }));
+}
+
+TEST(ArrayRefTest, Equals) {
+ static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+ ArrayRef<int> AR1(A1);
+ EXPECT_TRUE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8}));
+ EXPECT_FALSE(AR1.equals({8, 1, 2, 4, 5, 6, 6, 7}));
+ EXPECT_FALSE(AR1.equals({2, 4, 5, 6, 6, 7, 8, 1}));
+ EXPECT_FALSE(AR1.equals({0, 1, 2, 4, 5, 6, 6, 7}));
+ EXPECT_FALSE(AR1.equals({1, 2, 42, 4, 5, 6, 7, 8}));
+ EXPECT_FALSE(AR1.equals({42, 2, 3, 4, 5, 6, 7, 8}));
+ EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 42}));
+ EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7}));
+ EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8, 9}));
+
+ ArrayRef<int> AR1a = AR1.drop_back();
+ EXPECT_TRUE(AR1a.equals({1, 2, 3, 4, 5, 6, 7}));
+ EXPECT_FALSE(AR1a.equals({1, 2, 3, 4, 5, 6, 7, 8}));
+
+ ArrayRef<int> AR1b = AR1a.slice(2, 4);
+ EXPECT_TRUE(AR1b.equals({3, 4, 5, 6}));
+ EXPECT_FALSE(AR1b.equals({2, 3, 4, 5, 6}));
+ EXPECT_FALSE(AR1b.equals({3, 4, 5, 6, 7}));
+}
+
+TEST(ArrayRefTest, EmptyEquals) {
+ EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>());
+}
+
+TEST(ArrayRefTest, ConstConvert) {
+ int buf[4];
+ for (int i = 0; i < 4; ++i)
+ buf[i] = i;
+
+ static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]};
+ ArrayRef<const int *> a((ArrayRef<int *>(A)));
+ a = ArrayRef<int *>(A);
+}
+
+static std::vector<int> ReturnTest12() { return {1, 2}; }
+static void ArgTest12(ArrayRef<int> A) {
+ EXPECT_EQ(2U, A.size());
+ EXPECT_EQ(1, A[0]);
+ EXPECT_EQ(2, A[1]);
+}
+
+TEST(ArrayRefTest, InitializerList) {
+ std::initializer_list<int> init_list = { 0, 1, 2, 3, 4 };
+ ArrayRef<int> A = init_list;
+ for (int i = 0; i < 5; ++i)
+ EXPECT_EQ(i, A[i]);
+
+ std::vector<int> B = ReturnTest12();
+ A = B;
+ EXPECT_EQ(1, A[0]);
+ EXPECT_EQ(2, A[1]);
+
+ ArgTest12({1, 2});
+}
+
+TEST(ArrayRefTest, EmptyInitializerList) {
+ ArrayRef<int> A = {};
+ EXPECT_TRUE(A.empty());
+
+ A = {};
+ EXPECT_TRUE(A.empty());
+}
+
+// Test that makeArrayRef works on ArrayRef (no-op)
+TEST(ArrayRefTest, makeArrayRef) {
+ static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ // No copy expected for non-const ArrayRef (true no-op)
+ ArrayRef<int> AR1(A1);
+ ArrayRef<int> &AR1Ref = makeArrayRef(AR1);
+ EXPECT_EQ(&AR1, &AR1Ref);
+
+ // A copy is expected for non-const ArrayRef (thin copy)
+ const ArrayRef<int> AR2(A1);
+ const ArrayRef<int> &AR2Ref = makeArrayRef(AR2);
+ EXPECT_NE(&AR2Ref, &AR2);
+ EXPECT_TRUE(AR2.equals(AR2Ref));
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/BitVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/BitVectorTest.cpp
new file mode 100644
index 0000000..84290b3
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/BitVectorTest.cpp
@@ -0,0 +1,1125 @@
+//===- llvm/unittest/ADT/BitVectorTest.cpp - BitVector tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Some of these tests fail on PowerPC for unknown reasons.
+#ifndef __ppc__
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SmallBitVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture
+template <typename T>
+class BitVectorTest : public ::testing::Test { };
+
+// Test both BitVector and SmallBitVector with the same suite of tests.
+typedef ::testing::Types<BitVector, SmallBitVector> BitVectorTestTypes;
+TYPED_TEST_CASE(BitVectorTest, BitVectorTestTypes);
+
+TYPED_TEST(BitVectorTest, TrivialOperation) {
+ TypeParam Vec;
+ EXPECT_EQ(0U, Vec.count());
+ EXPECT_EQ(0U, Vec.size());
+ EXPECT_FALSE(Vec.any());
+ EXPECT_TRUE(Vec.all());
+ EXPECT_TRUE(Vec.none());
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.resize(5, true);
+ EXPECT_EQ(5U, Vec.count());
+ EXPECT_EQ(5U, Vec.size());
+ EXPECT_TRUE(Vec.any());
+ EXPECT_TRUE(Vec.all());
+ EXPECT_FALSE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ Vec.resize(11);
+ EXPECT_EQ(5U, Vec.count());
+ EXPECT_EQ(11U, Vec.size());
+ EXPECT_TRUE(Vec.any());
+ EXPECT_FALSE(Vec.all());
+ EXPECT_FALSE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ TypeParam Inv = Vec;
+ Inv.flip();
+ EXPECT_EQ(6U, Inv.count());
+ EXPECT_EQ(11U, Inv.size());
+ EXPECT_TRUE(Inv.any());
+ EXPECT_FALSE(Inv.all());
+ EXPECT_FALSE(Inv.none());
+ EXPECT_FALSE(Inv.empty());
+
+ EXPECT_FALSE(Inv == Vec);
+ EXPECT_TRUE(Inv != Vec);
+ Vec.flip();
+ EXPECT_TRUE(Inv == Vec);
+ EXPECT_FALSE(Inv != Vec);
+
+ // Add some "interesting" data to Vec.
+ Vec.resize(23, true);
+ Vec.resize(25, false);
+ Vec.resize(26, true);
+ Vec.resize(29, false);
+ Vec.resize(33, true);
+ Vec.resize(57, false);
+ unsigned Count = 0;
+ for (unsigned i = Vec.find_first(); i != -1u; i = Vec.find_next(i)) {
+ ++Count;
+ EXPECT_TRUE(Vec[i]);
+ EXPECT_TRUE(Vec.test(i));
+ }
+ EXPECT_EQ(Count, Vec.count());
+ EXPECT_EQ(Count, 23u);
+ EXPECT_FALSE(Vec[0]);
+ EXPECT_TRUE(Vec[32]);
+ EXPECT_FALSE(Vec[56]);
+ Vec.resize(61, false);
+
+ TypeParam Copy = Vec;
+ TypeParam Alt(3, false);
+ Alt.resize(6, true);
+ std::swap(Alt, Vec);
+ EXPECT_TRUE(Copy == Alt);
+ EXPECT_TRUE(Vec.size() == 6);
+ EXPECT_TRUE(Vec.count() == 3);
+ EXPECT_TRUE(Vec.find_first() == 3);
+ std::swap(Copy, Vec);
+
+ // Add some more "interesting" data.
+ Vec.resize(68, true);
+ Vec.resize(78, false);
+ Vec.resize(89, true);
+ Vec.resize(90, false);
+ Vec.resize(91, true);
+ Vec.resize(130, false);
+ Count = 0;
+ for (unsigned i = Vec.find_first(); i != -1u; i = Vec.find_next(i)) {
+ ++Count;
+ EXPECT_TRUE(Vec[i]);
+ EXPECT_TRUE(Vec.test(i));
+ }
+ EXPECT_EQ(Count, Vec.count());
+ EXPECT_EQ(Count, 42u);
+ EXPECT_FALSE(Vec[0]);
+ EXPECT_TRUE(Vec[32]);
+ EXPECT_FALSE(Vec[60]);
+ EXPECT_FALSE(Vec[129]);
+
+ Vec.flip(60);
+ EXPECT_TRUE(Vec[60]);
+ EXPECT_EQ(Count + 1, Vec.count());
+ Vec.flip(60);
+ EXPECT_FALSE(Vec[60]);
+ EXPECT_EQ(Count, Vec.count());
+
+ Vec.reset(32);
+ EXPECT_FALSE(Vec[32]);
+ EXPECT_EQ(Count - 1, Vec.count());
+ Vec.set(32);
+ EXPECT_TRUE(Vec[32]);
+ EXPECT_EQ(Count, Vec.count());
+
+ Vec.flip();
+ EXPECT_EQ(Vec.size() - Count, Vec.count());
+
+ Vec.reset();
+ EXPECT_EQ(0U, Vec.count());
+ EXPECT_EQ(130U, Vec.size());
+ EXPECT_FALSE(Vec.any());
+ EXPECT_FALSE(Vec.all());
+ EXPECT_TRUE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ Vec.flip();
+ EXPECT_EQ(130U, Vec.count());
+ EXPECT_EQ(130U, Vec.size());
+ EXPECT_TRUE(Vec.any());
+ EXPECT_TRUE(Vec.all());
+ EXPECT_FALSE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ Vec.resize(64);
+ EXPECT_EQ(64U, Vec.count());
+ EXPECT_EQ(64U, Vec.size());
+ EXPECT_TRUE(Vec.any());
+ EXPECT_TRUE(Vec.all());
+ EXPECT_FALSE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ Vec.flip();
+ EXPECT_EQ(0U, Vec.count());
+ EXPECT_EQ(64U, Vec.size());
+ EXPECT_FALSE(Vec.any());
+ EXPECT_FALSE(Vec.all());
+ EXPECT_TRUE(Vec.none());
+ EXPECT_FALSE(Vec.empty());
+
+ Inv = TypeParam().flip();
+ EXPECT_EQ(0U, Inv.count());
+ EXPECT_EQ(0U, Inv.size());
+ EXPECT_FALSE(Inv.any());
+ EXPECT_TRUE(Inv.all());
+ EXPECT_TRUE(Inv.none());
+ EXPECT_TRUE(Inv.empty());
+
+ Vec.clear();
+ EXPECT_EQ(0U, Vec.count());
+ EXPECT_EQ(0U, Vec.size());
+ EXPECT_FALSE(Vec.any());
+ EXPECT_TRUE(Vec.all());
+ EXPECT_TRUE(Vec.none());
+ EXPECT_TRUE(Vec.empty());
+}
+
+TYPED_TEST(BitVectorTest, SimpleFindOpsMultiWord) {
+ TypeParam A;
+
+ // Test finding next set and unset bits in a BitVector with multiple words
+ A.resize(100);
+ A.set(12);
+ A.set(13);
+ A.set(75);
+
+ EXPECT_EQ(75, A.find_last());
+ EXPECT_EQ(12, A.find_first());
+ EXPECT_EQ(13, A.find_next(12));
+ EXPECT_EQ(75, A.find_next(13));
+ EXPECT_EQ(-1, A.find_next(75));
+
+ EXPECT_EQ(-1, A.find_prev(12));
+ EXPECT_EQ(12, A.find_prev(13));
+ EXPECT_EQ(13, A.find_prev(75));
+ EXPECT_EQ(75, A.find_prev(90));
+
+ EXPECT_EQ(0, A.find_first_unset());
+ EXPECT_EQ(99, A.find_last_unset());
+ EXPECT_EQ(14, A.find_next_unset(11));
+ EXPECT_EQ(14, A.find_next_unset(12));
+ EXPECT_EQ(14, A.find_next_unset(13));
+ EXPECT_EQ(16, A.find_next_unset(15));
+ EXPECT_EQ(76, A.find_next_unset(74));
+ EXPECT_EQ(76, A.find_next_unset(75));
+ EXPECT_EQ(-1, A.find_next_unset(99));
+
+ A.set(0, 100);
+ EXPECT_EQ(100U, A.count());
+ EXPECT_EQ(0, A.find_first());
+ EXPECT_EQ(-1, A.find_first_unset());
+ EXPECT_EQ(-1, A.find_last_unset());
+ EXPECT_EQ(99, A.find_last());
+ EXPECT_EQ(99, A.find_next(98));
+
+ A.reset(0, 100);
+ EXPECT_EQ(0U, A.count());
+ EXPECT_EQ(-1, A.find_first());
+ EXPECT_EQ(-1, A.find_last());
+ EXPECT_EQ(0, A.find_first_unset());
+ EXPECT_EQ(99, A.find_last_unset());
+ EXPECT_EQ(99, A.find_next_unset(98));
+}
+
+// Check if a SmallBitVector is in small mode. This check is used in tests
+// that run for both SmallBitVector and BitVector. This check doesn't apply
+// to BitVector so we provide an overload that returns true to get the tests
+// to compile.
+static bool SmallBitVectorIsSmallMode(const SmallBitVector &bv) {
+ return bv.isSmall();
+}
+static bool SmallBitVectorIsSmallMode(const BitVector &) { return true; }
+
+// These tests are intended to exercise the single-word case of BitVector
+// and the small-mode case of SmallBitVector.
+TYPED_TEST(BitVectorTest, SimpleFindOpsSingleWord) {
+ // Test finding in an empty BitVector.
+ TypeParam A;
+ ASSERT_TRUE(SmallBitVectorIsSmallMode(A));
+ EXPECT_EQ(-1, A.find_first());
+ EXPECT_EQ(-1, A.find_last());
+ EXPECT_EQ(-1, A.find_first_unset());
+ EXPECT_EQ(-1, A.find_last_unset());
+
+ A.resize(20);
+ A.set(3);
+ A.set(4);
+ A.set(16);
+ ASSERT_TRUE(SmallBitVectorIsSmallMode(A));
+ EXPECT_EQ(16, A.find_last());
+ EXPECT_EQ(3, A.find_first());
+ EXPECT_EQ(3, A.find_next(1));
+ EXPECT_EQ(4, A.find_next(3));
+ EXPECT_EQ(16, A.find_next(4));
+ EXPECT_EQ(-1, A.find_next(16));
+
+ EXPECT_EQ(-1, A.find_prev(3));
+ EXPECT_EQ(3, A.find_prev(4));
+ EXPECT_EQ(4, A.find_prev(16));
+ EXPECT_EQ(16, A.find_prev(18));
+
+ EXPECT_EQ(0, A.find_first_unset());
+ EXPECT_EQ(19, A.find_last_unset());
+ EXPECT_EQ(5, A.find_next_unset(3));
+ EXPECT_EQ(5, A.find_next_unset(4));
+ EXPECT_EQ(13, A.find_next_unset(12));
+ EXPECT_EQ(17, A.find_next_unset(15));
+}
+
+TEST(BitVectorTest, FindInRangeMultiWord) {
+ BitVector Vec;
+
+ Vec.resize(200);
+ Vec.set(3, 7);
+ Vec.set(24, 35);
+ Vec.set(50, 70);
+ Vec.set(150);
+ Vec.set(152);
+ Vec.set(154);
+
+ // find first
+ EXPECT_EQ(-1, Vec.find_first_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_first_in(7, 24));
+
+ EXPECT_EQ(3, Vec.find_first_in(0, 10));
+ EXPECT_EQ(4, Vec.find_first_in(4, 10));
+ EXPECT_EQ(150, Vec.find_first_in(100, 200));
+ EXPECT_EQ(152, Vec.find_first_in(151, 200));
+ EXPECT_EQ(154, Vec.find_first_in(153, 200));
+
+ EXPECT_EQ(-1, Vec.find_first_in(155, 200));
+ Vec.set(199);
+ EXPECT_EQ(199, Vec.find_first_in(199, 200));
+ Vec.reset(199);
+
+ // find last
+ EXPECT_EQ(-1, Vec.find_last_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_last_in(7, 24));
+
+ EXPECT_EQ(6, Vec.find_last_in(0, 10));
+ EXPECT_EQ(5, Vec.find_last_in(0, 6));
+ EXPECT_EQ(154, Vec.find_last_in(100, 155));
+ EXPECT_EQ(152, Vec.find_last_in(100, 154));
+ EXPECT_EQ(150, Vec.find_last_in(100, 152));
+ EXPECT_EQ(-1, Vec.find_last_in(100, 150));
+ Vec.set(199);
+ EXPECT_EQ(199, Vec.find_last_in(199, 200));
+ Vec.reset(199);
+
+ // find first unset
+ EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(24, 35));
+
+ EXPECT_EQ(0, Vec.find_first_unset_in(0, 10));
+ EXPECT_EQ(1, Vec.find_first_unset_in(1, 10));
+ EXPECT_EQ(7, Vec.find_first_unset_in(5, 25));
+ EXPECT_EQ(151, Vec.find_first_unset_in(150, 200));
+ EXPECT_EQ(151, Vec.find_first_unset_in(151, 200));
+ EXPECT_EQ(153, Vec.find_first_unset_in(152, 200));
+ EXPECT_EQ(153, Vec.find_first_unset_in(153, 200));
+ EXPECT_EQ(155, Vec.find_first_unset_in(154, 200));
+ EXPECT_EQ(155, Vec.find_first_unset_in(155, 200));
+ EXPECT_EQ(199, Vec.find_first_unset_in(199, 200));
+
+ // find last unset
+ EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(24, 35));
+
+ EXPECT_EQ(9, Vec.find_last_unset_in(0, 10));
+ EXPECT_EQ(8, Vec.find_last_unset_in(0, 9));
+ EXPECT_EQ(2, Vec.find_last_unset_in(0, 7));
+ EXPECT_EQ(149, Vec.find_last_unset_in(100, 151));
+ EXPECT_EQ(151, Vec.find_last_unset_in(100, 152));
+ EXPECT_EQ(151, Vec.find_last_unset_in(100, 153));
+ EXPECT_EQ(153, Vec.find_last_unset_in(100, 154));
+ EXPECT_EQ(153, Vec.find_last_unset_in(100, 155));
+ EXPECT_EQ(155, Vec.find_last_unset_in(100, 156));
+ EXPECT_EQ(199, Vec.find_last_unset_in(199, 200));
+}
+
+TEST(BitVectorTest, FindInRangeSingleWord) {
+ // When the bit vector contains only a single word, this is slightly different
+ // than when the bit vector contains multiple words, because masks are applied
+ // to the front and back of the same word. So make sure this works.
+ BitVector Vec;
+
+ Vec.resize(25);
+ Vec.set(2, 4);
+ Vec.set(6, 9);
+ Vec.set(12, 15);
+ Vec.set(19);
+ Vec.set(21);
+ Vec.set(23);
+
+ // find first
+ EXPECT_EQ(-1, Vec.find_first_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_first_in(9, 12));
+
+ EXPECT_EQ(2, Vec.find_first_in(0, 10));
+ EXPECT_EQ(6, Vec.find_first_in(4, 10));
+ EXPECT_EQ(19, Vec.find_first_in(18, 25));
+ EXPECT_EQ(21, Vec.find_first_in(20, 25));
+ EXPECT_EQ(23, Vec.find_first_in(22, 25));
+ EXPECT_EQ(-1, Vec.find_first_in(24, 25));
+
+ // find last
+ EXPECT_EQ(-1, Vec.find_last_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_in(24, 24));
+ EXPECT_EQ(-1, Vec.find_last_in(9, 12));
+
+ EXPECT_EQ(8, Vec.find_last_in(0, 10));
+ EXPECT_EQ(3, Vec.find_last_in(0, 6));
+ EXPECT_EQ(23, Vec.find_last_in(18, 25));
+ EXPECT_EQ(21, Vec.find_last_in(18, 23));
+ EXPECT_EQ(19, Vec.find_last_in(18, 21));
+ EXPECT_EQ(-1, Vec.find_last_in(18, 19));
+
+ // find first unset
+ EXPECT_EQ(-1, Vec.find_first_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_first_unset_in(6, 9));
+
+ EXPECT_EQ(0, Vec.find_first_unset_in(0, 6));
+ EXPECT_EQ(1, Vec.find_first_unset_in(1, 6));
+ EXPECT_EQ(9, Vec.find_first_unset_in(7, 13));
+ EXPECT_EQ(18, Vec.find_first_unset_in(18, 25));
+ EXPECT_EQ(20, Vec.find_first_unset_in(19, 25));
+ EXPECT_EQ(20, Vec.find_first_unset_in(20, 25));
+ EXPECT_EQ(22, Vec.find_first_unset_in(21, 25));
+ EXPECT_EQ(22, Vec.find_first_unset_in(22, 25));
+ EXPECT_EQ(24, Vec.find_first_unset_in(23, 25));
+ EXPECT_EQ(24, Vec.find_first_unset_in(24, 25));
+
+ // find last unset
+ EXPECT_EQ(-1, Vec.find_last_unset_in(0, 0));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(23, 23));
+ EXPECT_EQ(-1, Vec.find_last_unset_in(6, 9));
+
+ EXPECT_EQ(5, Vec.find_last_unset_in(0, 6));
+ EXPECT_EQ(4, Vec.find_last_unset_in(0, 5));
+ EXPECT_EQ(1, Vec.find_last_unset_in(0, 4));
+ EXPECT_EQ(11, Vec.find_last_unset_in(7, 13));
+ EXPECT_EQ(24, Vec.find_last_unset_in(18, 25));
+ EXPECT_EQ(22, Vec.find_last_unset_in(18, 24));
+ EXPECT_EQ(22, Vec.find_last_unset_in(18, 23));
+ EXPECT_EQ(20, Vec.find_last_unset_in(18, 22));
+ EXPECT_EQ(20, Vec.find_last_unset_in(18, 21));
+ EXPECT_EQ(18, Vec.find_last_unset_in(18, 20));
+ EXPECT_EQ(18, Vec.find_last_unset_in(18, 19));
+}
+
+TYPED_TEST(BitVectorTest, CompoundAssignment) {
+ TypeParam A;
+ A.resize(10);
+ A.set(4);
+ A.set(7);
+
+ TypeParam B;
+ B.resize(50);
+ B.set(5);
+ B.set(18);
+
+ A |= B;
+ EXPECT_TRUE(A.test(4));
+ EXPECT_TRUE(A.test(5));
+ EXPECT_TRUE(A.test(7));
+ EXPECT_TRUE(A.test(18));
+ EXPECT_EQ(4U, A.count());
+ EXPECT_EQ(50U, A.size());
+
+ B.resize(10);
+ B.set();
+ B.reset(2);
+ B.reset(7);
+ A &= B;
+ EXPECT_FALSE(A.test(2));
+ EXPECT_FALSE(A.test(7));
+ EXPECT_TRUE(A.test(4));
+ EXPECT_TRUE(A.test(5));
+ EXPECT_EQ(2U, A.count());
+ EXPECT_EQ(50U, A.size());
+
+ B.resize(100);
+ B.set();
+
+ A ^= B;
+ EXPECT_TRUE(A.test(2));
+ EXPECT_TRUE(A.test(7));
+ EXPECT_EQ(98U, A.count());
+ EXPECT_EQ(100U, A.size());
+}
+
+// Test SmallBitVector operations with mixed big/small representations
+TYPED_TEST(BitVectorTest, MixedBigSmall) {
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Small &= Big;
+ EXPECT_TRUE(Small.test(0));
+ EXPECT_EQ(1u, Small.count());
+ // FIXME BitVector and SmallBitVector behave differently here.
+ // SmallBitVector resizes the LHS to max(LHS.size(), RHS.size())
+ // but BitVector does not.
+ // EXPECT_EQ(20u, Small.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Big &= Small;
+ EXPECT_TRUE(Big.test(0));
+ EXPECT_EQ(1u, Big.count());
+ // FIXME BitVector and SmallBitVector behave differently here.
+ // SmallBitVector resizes the LHS to max(LHS.size(), RHS.size())
+ // but BitVector does not.
+ // EXPECT_EQ(20u, Big.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Small |= Big;
+ EXPECT_TRUE(Small.test(0));
+ EXPECT_TRUE(Small.test(1));
+ EXPECT_TRUE(Small.test(2));
+ EXPECT_TRUE(Small.test(16));
+ EXPECT_EQ(4u, Small.count());
+ EXPECT_EQ(20u, Small.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Big |= Small;
+ EXPECT_TRUE(Big.test(0));
+ EXPECT_TRUE(Big.test(1));
+ EXPECT_TRUE(Big.test(2));
+ EXPECT_TRUE(Big.test(16));
+ EXPECT_EQ(4u, Big.count());
+ EXPECT_EQ(20u, Big.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Small ^= Big;
+ EXPECT_TRUE(Small.test(1));
+ EXPECT_TRUE(Small.test(2));
+ EXPECT_TRUE(Small.test(16));
+ EXPECT_EQ(3u, Small.count());
+ EXPECT_EQ(20u, Small.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Big ^= Small;
+ EXPECT_TRUE(Big.test(1));
+ EXPECT_TRUE(Big.test(2));
+ EXPECT_TRUE(Big.test(16));
+ EXPECT_EQ(3u, Big.count());
+ EXPECT_EQ(20u, Big.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Small.reset(Big);
+ EXPECT_TRUE(Small.test(1));
+ EXPECT_EQ(1u, Small.count());
+ EXPECT_EQ(10u, Small.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+ Big.set(2);
+ Big.set(16);
+
+ Big.reset(Small);
+ EXPECT_TRUE(Big.test(2));
+ EXPECT_TRUE(Big.test(16));
+ EXPECT_EQ(2u, Big.count());
+ EXPECT_EQ(20u, Big.size());
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(10);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+
+ EXPECT_FALSE(Big == Small);
+ EXPECT_FALSE(Small == Big);
+ Big.set(1);
+ EXPECT_TRUE(Big == Small);
+ EXPECT_TRUE(Small == Big);
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(20);
+ Small.resize(10);
+
+ Small.set(0);
+ Big.set(1);
+
+ EXPECT_FALSE(Small.anyCommon(Big));
+ EXPECT_FALSE(Big.anyCommon(Small));
+ Big.set(0);
+ EXPECT_TRUE(Small.anyCommon(Big));
+ EXPECT_TRUE(Big.anyCommon(Small));
+ }
+
+ {
+ TypeParam Big;
+ TypeParam Small;
+
+ Big.reserve(100);
+ Big.resize(10);
+ Small.resize(10);
+
+ Small.set(0);
+ Small.set(1);
+ Big.set(0);
+
+ EXPECT_TRUE(Small.test(Big));
+ EXPECT_FALSE(Big.test(Small));
+ Big.set(1);
+ EXPECT_FALSE(Small.test(Big));
+ EXPECT_FALSE(Big.test(Small));
+ }
+}
+
+TYPED_TEST(BitVectorTest, ProxyIndex) {
+ TypeParam Vec(3);
+ EXPECT_TRUE(Vec.none());
+ Vec[0] = Vec[1] = Vec[2] = true;
+ EXPECT_EQ(Vec.size(), Vec.count());
+ Vec[2] = Vec[1] = Vec[0] = false;
+ EXPECT_TRUE(Vec.none());
+}
+
+TYPED_TEST(BitVectorTest, PortableBitMask) {
+ TypeParam A;
+ const uint32_t Mask1[] = { 0x80000000, 6, 5 };
+
+ A.resize(10);
+ A.setBitsInMask(Mask1, 1);
+ EXPECT_EQ(10u, A.size());
+ EXPECT_FALSE(A.test(0));
+
+ A.resize(32);
+ A.setBitsInMask(Mask1, 1);
+ EXPECT_FALSE(A.test(0));
+ EXPECT_TRUE(A.test(31));
+ EXPECT_EQ(1u, A.count());
+
+ A.resize(33);
+ A.setBitsInMask(Mask1, 1);
+ EXPECT_EQ(1u, A.count());
+ A.setBitsInMask(Mask1, 2);
+ EXPECT_EQ(1u, A.count());
+
+ A.resize(34);
+ A.setBitsInMask(Mask1, 2);
+ EXPECT_EQ(2u, A.count());
+
+ A.resize(65);
+ A.setBitsInMask(Mask1, 3);
+ EXPECT_EQ(4u, A.count());
+
+ A.setBitsNotInMask(Mask1, 1);
+ EXPECT_EQ(32u+3u, A.count());
+
+ A.setBitsNotInMask(Mask1, 3);
+ EXPECT_EQ(65u, A.count());
+
+ A.resize(96);
+ EXPECT_EQ(65u, A.count());
+
+ A.clear();
+ A.resize(128);
+ A.setBitsNotInMask(Mask1, 3);
+ EXPECT_EQ(96u-5u, A.count());
+
+ A.clearBitsNotInMask(Mask1, 1);
+ EXPECT_EQ(64-4u, A.count());
+}
+
+TYPED_TEST(BitVectorTest, BinOps) {
+ TypeParam A;
+ TypeParam B;
+
+ A.resize(65);
+ EXPECT_FALSE(A.anyCommon(B));
+ EXPECT_FALSE(B.anyCommon(B));
+
+ B.resize(64);
+ A.set(64);
+ EXPECT_FALSE(A.anyCommon(B));
+ EXPECT_FALSE(B.anyCommon(A));
+
+ B.set(63);
+ EXPECT_FALSE(A.anyCommon(B));
+ EXPECT_FALSE(B.anyCommon(A));
+
+ A.set(63);
+ EXPECT_TRUE(A.anyCommon(B));
+ EXPECT_TRUE(B.anyCommon(A));
+
+ B.resize(70);
+ B.set(64);
+ B.reset(63);
+ A.resize(64);
+ EXPECT_FALSE(A.anyCommon(B));
+ EXPECT_FALSE(B.anyCommon(A));
+}
+
+typedef std::vector<std::pair<int, int>> RangeList;
+
+template <typename VecType>
+static inline VecType createBitVector(uint32_t Size,
+ const RangeList &setRanges) {
+ VecType V;
+ V.resize(Size);
+ for (auto &R : setRanges)
+ V.set(R.first, R.second);
+ return V;
+}
+
+TYPED_TEST(BitVectorTest, ShiftOpsSingleWord) {
+ // Test that shift ops work when the desired shift amount is less
+ // than one word.
+
+ // 1. Case where the number of bits in the BitVector also fit into a single
+ // word.
+ TypeParam A = createBitVector<TypeParam>(12, {{2, 4}, {8, 10}});
+ TypeParam B = A;
+
+ EXPECT_EQ(4U, A.count());
+ EXPECT_TRUE(A.test(2));
+ EXPECT_TRUE(A.test(3));
+ EXPECT_TRUE(A.test(8));
+ EXPECT_TRUE(A.test(9));
+
+ A >>= 1;
+ EXPECT_EQ(createBitVector<TypeParam>(12, {{1, 3}, {7, 9}}), A);
+
+ A <<= 1;
+ EXPECT_EQ(B, A);
+
+ A >>= 10;
+ EXPECT_EQ(createBitVector<TypeParam>(12, {}), A);
+
+ A = B;
+ A <<= 10;
+ EXPECT_EQ(createBitVector<TypeParam>(12, {}), A);
+
+ // 2. Case where the number of bits in the BitVector do not fit into a single
+ // word.
+
+ // 31----------------------------------------------------------------------0
+ // XXXXXXXX XXXXXXXX XXXXXXXX 00000111 | 11111110 00000000 00001111 11111111
+ A = createBitVector<TypeParam>(40, {{0, 12}, {25, 35}});
+ EXPECT_EQ(40U, A.size());
+ EXPECT_EQ(22U, A.count());
+
+ // 2a. Make sure that left shifting some 1 bits out of the vector works.
+ // 31----------------------------------------------------------------------0
+ // Before:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 00000111 | 11111110 00000000 00001111 11111111
+ // After:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 11111100 | 00000000 00011111 11111110 00000000
+ A <<= 9;
+ EXPECT_EQ(createBitVector<TypeParam>(40, {{9, 21}, {34, 40}}), A);
+
+ // 2b. Make sure that keeping the number of one bits unchanged works.
+ // 31----------------------------------------------------------------------0
+ // Before:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 11111100 | 00000000 00011111 11111110 00000000
+ // After:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 00000011 | 11110000 00000000 01111111 11111000
+ A >>= 6;
+ EXPECT_EQ(createBitVector<TypeParam>(40, {{3, 15}, {28, 34}}), A);
+
+ // 2c. Make sure that right shifting some 1 bits out of the vector works.
+ // 31----------------------------------------------------------------------0
+ // Before:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 00000011 | 11110000 00000000 01111111 11111000
+ // After:
+ // XXXXXXXX XXXXXXXX XXXXXXXX 00000000 | 00000000 11111100 00000000 00011111
+ A >>= 10;
+ EXPECT_EQ(createBitVector<TypeParam>(40, {{0, 5}, {18, 24}}), A);
+
+ // 3. Big test.
+ A = createBitVector<TypeParam>(300, {{1, 30}, {60, 95}, {200, 275}});
+ A <<= 29;
+ EXPECT_EQ(createBitVector<TypeParam>(
+ 300, {{1 + 29, 30 + 29}, {60 + 29, 95 + 29}, {200 + 29, 300}}),
+ A);
+}
+
+TYPED_TEST(BitVectorTest, ShiftOpsMultiWord) {
+ // Test that shift ops work when the desired shift amount is greater than or
+ // equal to the size of a single word.
+ auto A = createBitVector<TypeParam>(300, {{1, 30}, {60, 95}, {200, 275}});
+
+ // Make a copy so we can re-use it later.
+ auto B = A;
+
+ // 1. Shift left by an exact multiple of the word size. This should invoke
+ // only a memmove and no per-word bit operations.
+ A <<= 64;
+ auto Expected = createBitVector<TypeParam>(
+ 300, {{1 + 64, 30 + 64}, {60 + 64, 95 + 64}, {200 + 64, 300}});
+ EXPECT_EQ(Expected, A);
+
+ // 2. Shift left by a non multiple of the word size. This should invoke both
+ // a memmove and per-word bit operations.
+ A = B;
+ A <<= 93;
+ EXPECT_EQ(createBitVector<TypeParam>(
+ 300, {{1 + 93, 30 + 93}, {60 + 93, 95 + 93}, {200 + 93, 300}}),
+ A);
+
+ // 1. Shift right by an exact multiple of the word size. This should invoke
+ // only a memmove and no per-word bit operations.
+ A = B;
+ A >>= 64;
+ EXPECT_EQ(
+ createBitVector<TypeParam>(300, {{0, 95 - 64}, {200 - 64, 275 - 64}}), A);
+
+ // 2. Shift left by a non multiple of the word size. This should invoke both
+ // a memmove and per-word bit operations.
+ A = B;
+ A >>= 93;
+ EXPECT_EQ(
+ createBitVector<TypeParam>(300, {{0, 95 - 93}, {200 - 93, 275 - 93}}), A);
+}
+
+TYPED_TEST(BitVectorTest, RangeOps) {
+ TypeParam A;
+ A.resize(256);
+ A.reset();
+ A.set(1, 255);
+
+ EXPECT_FALSE(A.test(0));
+ EXPECT_TRUE( A.test(1));
+ EXPECT_TRUE( A.test(23));
+ EXPECT_TRUE( A.test(254));
+ EXPECT_FALSE(A.test(255));
+
+ TypeParam B;
+ B.resize(256);
+ B.set();
+ B.reset(1, 255);
+
+ EXPECT_TRUE( B.test(0));
+ EXPECT_FALSE(B.test(1));
+ EXPECT_FALSE(B.test(23));
+ EXPECT_FALSE(B.test(254));
+ EXPECT_TRUE( B.test(255));
+
+ TypeParam C;
+ C.resize(3);
+ C.reset();
+ C.set(0, 1);
+
+ EXPECT_TRUE(C.test(0));
+ EXPECT_FALSE( C.test(1));
+ EXPECT_FALSE( C.test(2));
+
+ TypeParam D;
+ D.resize(3);
+ D.set();
+ D.reset(0, 1);
+
+ EXPECT_FALSE(D.test(0));
+ EXPECT_TRUE( D.test(1));
+ EXPECT_TRUE( D.test(2));
+
+ TypeParam E;
+ E.resize(128);
+ E.reset();
+ E.set(1, 33);
+
+ EXPECT_FALSE(E.test(0));
+ EXPECT_TRUE( E.test(1));
+ EXPECT_TRUE( E.test(32));
+ EXPECT_FALSE(E.test(33));
+
+ TypeParam BufferOverrun;
+ unsigned size = sizeof(unsigned long) * 8;
+ BufferOverrun.resize(size);
+ BufferOverrun.reset(0, size);
+ BufferOverrun.set(0, size);
+}
+
+TYPED_TEST(BitVectorTest, CompoundTestReset) {
+ TypeParam A(50, true);
+ TypeParam B(50, false);
+
+ TypeParam C(100, true);
+ TypeParam D(100, false);
+
+ EXPECT_FALSE(A.test(A));
+ EXPECT_TRUE(A.test(B));
+ EXPECT_FALSE(A.test(C));
+ EXPECT_TRUE(A.test(D));
+ EXPECT_FALSE(B.test(A));
+ EXPECT_FALSE(B.test(B));
+ EXPECT_FALSE(B.test(C));
+ EXPECT_FALSE(B.test(D));
+ EXPECT_TRUE(C.test(A));
+ EXPECT_TRUE(C.test(B));
+ EXPECT_FALSE(C.test(C));
+ EXPECT_TRUE(C.test(D));
+
+ A.reset(B);
+ A.reset(D);
+ EXPECT_TRUE(A.all());
+ A.reset(A);
+ EXPECT_TRUE(A.none());
+ A.set();
+ A.reset(C);
+ EXPECT_TRUE(A.none());
+ A.set();
+
+ C.reset(A);
+ EXPECT_EQ(50, C.find_first());
+ C.reset(C);
+ EXPECT_TRUE(C.none());
+}
+
+TYPED_TEST(BitVectorTest, MoveConstructor) {
+ TypeParam A(10, true);
+ TypeParam B(std::move(A));
+ // Check that the move ctor leaves the moved-from object in a valid state.
+ // The following line used to crash.
+ A = B;
+
+ TypeParam C(10, true);
+ EXPECT_EQ(C, A);
+ EXPECT_EQ(C, B);
+}
+
+TYPED_TEST(BitVectorTest, MoveAssignment) {
+ TypeParam A(10, true);
+ TypeParam B;
+ B = std::move(A);
+ // Check that move assignment leaves the moved-from object in a valid state.
+ // The following line used to crash.
+ A = B;
+
+ TypeParam C(10, true);
+ EXPECT_EQ(C, A);
+ EXPECT_EQ(C, B);
+}
+
+template<class TypeParam>
+static void testEmpty(const TypeParam &A) {
+ EXPECT_TRUE(A.empty());
+ EXPECT_EQ((size_t)0, A.size());
+ EXPECT_EQ((size_t)0, A.count());
+ EXPECT_FALSE(A.any());
+ EXPECT_TRUE(A.all());
+ EXPECT_TRUE(A.none());
+ EXPECT_EQ(-1, A.find_first());
+ EXPECT_EQ(A, TypeParam());
+}
+
+/// Tests whether BitVector behaves well with Bits==nullptr, Capacity==0
+TYPED_TEST(BitVectorTest, EmptyVector) {
+ TypeParam A;
+ testEmpty(A);
+
+ TypeParam B;
+ B.reset();
+ testEmpty(B);
+
+ TypeParam C;
+ C.clear();
+ testEmpty(C);
+
+ TypeParam D(A);
+ testEmpty(D);
+
+ TypeParam E;
+ E = A;
+ testEmpty(E);
+
+ TypeParam F;
+ E.reset(A);
+ testEmpty(E);
+}
+
+TYPED_TEST(BitVectorTest, Iterators) {
+ TypeParam Filled(10, true);
+ EXPECT_NE(Filled.set_bits_begin(), Filled.set_bits_end());
+ unsigned Counter = 0;
+ for (unsigned Bit : Filled.set_bits())
+ EXPECT_EQ(Bit, Counter++);
+
+ TypeParam Empty;
+ EXPECT_EQ(Empty.set_bits_begin(), Empty.set_bits_end());
+ for (unsigned Bit : Empty.set_bits()) {
+ (void)Bit;
+ EXPECT_TRUE(false);
+ }
+
+ TypeParam ToFill(100, false);
+ ToFill.set(0);
+ EXPECT_NE(ToFill.set_bits_begin(), ToFill.set_bits_end());
+ EXPECT_EQ(++ToFill.set_bits_begin(), ToFill.set_bits_end());
+ EXPECT_EQ(*ToFill.set_bits_begin(), 0U);
+ ToFill.reset(0);
+ EXPECT_EQ(ToFill.set_bits_begin(), ToFill.set_bits_end());
+
+ const unsigned List[] = {1, 10, 25, 99};
+ for (unsigned Num : List)
+ ToFill.set(Num);
+ unsigned i = 0;
+ for (unsigned Bit : ToFill.set_bits())
+ EXPECT_EQ(List[i++], Bit);
+}
+
+TYPED_TEST(BitVectorTest, PushBack) {
+ TypeParam Vec(10, false);
+ EXPECT_EQ(-1, Vec.find_first());
+ EXPECT_EQ(10U, Vec.size());
+ EXPECT_EQ(0U, Vec.count());
+
+ Vec.push_back(true);
+ EXPECT_EQ(10, Vec.find_first());
+ EXPECT_EQ(11U, Vec.size());
+ EXPECT_EQ(1U, Vec.count());
+
+ Vec.push_back(false);
+ EXPECT_EQ(10, Vec.find_first());
+ EXPECT_EQ(12U, Vec.size());
+ EXPECT_EQ(1U, Vec.count());
+
+ Vec.push_back(true);
+ EXPECT_EQ(10, Vec.find_first());
+ EXPECT_EQ(13U, Vec.size());
+ EXPECT_EQ(2U, Vec.count());
+
+ // Add a lot of values to cause reallocation.
+ for (int i = 0; i != 100; ++i) {
+ Vec.push_back(true);
+ Vec.push_back(false);
+ }
+ EXPECT_EQ(10, Vec.find_first());
+ EXPECT_EQ(213U, Vec.size());
+ EXPECT_EQ(102U, Vec.count());
+}
+}
+#endif
diff --git a/src/llvm-project/llvm/unittests/ADT/BitmaskEnumTest.cpp b/src/llvm-project/llvm/unittests/ADT/BitmaskEnumTest.cpp
new file mode 100644
index 0000000..77635c6
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/BitmaskEnumTest.cpp
@@ -0,0 +1,134 @@
+//===- llvm/unittest/ADT/BitmaskEnumTest.cpp - BitmaskEnum unit tests -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/BitmaskEnum.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+enum Flags {
+ F0 = 0,
+ F1 = 1,
+ F2 = 2,
+ F3 = 4,
+ F4 = 8,
+ LLVM_MARK_AS_BITMASK_ENUM(F4)
+};
+
+TEST(BitmaskEnumTest, BitwiseOr) {
+ Flags f = F1 | F2;
+ EXPECT_EQ(3, f);
+
+ f = f | F3;
+ EXPECT_EQ(7, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseOrEquals) {
+ Flags f = F1;
+ f |= F3;
+ EXPECT_EQ(5, f);
+
+ // |= should return a reference to the LHS.
+ f = F2;
+ (f |= F3) = F1;
+ EXPECT_EQ(F1, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseAnd) {
+ Flags f = static_cast<Flags>(3) & F2;
+ EXPECT_EQ(F2, f);
+
+ f = (f | F3) & (F1 | F2 | F3);
+ EXPECT_EQ(6, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseAndEquals) {
+ Flags f = F1 | F2 | F3;
+ f &= F1 | F2;
+ EXPECT_EQ(3, f);
+
+ // &= should return a reference to the LHS.
+ (f &= F1) = F3;
+ EXPECT_EQ(F3, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseXor) {
+ Flags f = (F1 | F2) ^ (F2 | F3);
+ EXPECT_EQ(5, f);
+
+ f = f ^ F1;
+ EXPECT_EQ(4, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseXorEquals) {
+ Flags f = (F1 | F2);
+ f ^= (F2 | F4);
+ EXPECT_EQ(9, f);
+
+ // ^= should return a reference to the LHS.
+ (f ^= F4) = F3;
+ EXPECT_EQ(F3, f);
+}
+
+TEST(BitmaskEnumTest, BitwiseNot) {
+ Flags f = ~F1;
+ EXPECT_EQ(14, f); // Largest value for f is 15.
+ EXPECT_EQ(15, ~F0);
+}
+
+enum class FlagsClass {
+ F0 = 0,
+ F1 = 1,
+ F2 = 2,
+ F3 = 4,
+ LLVM_MARK_AS_BITMASK_ENUM(F3)
+};
+
+TEST(BitmaskEnumTest, ScopedEnum) {
+ FlagsClass f = (FlagsClass::F1 & ~FlagsClass::F0) | FlagsClass::F2;
+ f |= FlagsClass::F3;
+ EXPECT_EQ(7, static_cast<int>(f));
+}
+
+struct Container {
+ enum Flags { F0 = 0, F1 = 1, F2 = 2, F3 = 4, LLVM_MARK_AS_BITMASK_ENUM(F3) };
+
+ static Flags getFlags() {
+ Flags f = F0 | F1;
+ f |= F2;
+ return f;
+ }
+};
+
+TEST(BitmaskEnumTest, EnumInStruct) { EXPECT_EQ(3, Container::getFlags()); }
+
+} // namespace
+
+namespace foo {
+namespace bar {
+namespace {
+enum FlagsInNamespace {
+ F0 = 0,
+ F1 = 1,
+ F2 = 2,
+ F3 = 4,
+ LLVM_MARK_AS_BITMASK_ENUM(F3)
+};
+} // namespace
+} // namespace foo
+} // namespace bar
+
+namespace {
+TEST(BitmaskEnumTest, EnumInNamespace) {
+ foo::bar::FlagsInNamespace f = ~foo::bar::F0 & (foo::bar::F1 | foo::bar::F2);
+ f |= foo::bar::F3;
+ EXPECT_EQ(7, f);
+}
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/BreadthFirstIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/BreadthFirstIteratorTest.cpp
new file mode 100644
index 0000000..42a07bb
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/BreadthFirstIteratorTest.cpp
@@ -0,0 +1,74 @@
+//=== llvm/unittest/ADT/BreadthFirstIteratorTest.cpp - BFS iterator tests -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/BreadthFirstIterator.h"
+#include "TestGraph.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+TEST(BreadthFristIteratorTest, Basic) {
+ typedef bf_iterator<Graph<4>> BFIter;
+
+ Graph<4> G;
+ G.AddEdge(0, 1);
+ G.AddEdge(0, 2);
+ G.AddEdge(1, 3);
+
+ auto It = BFIter::begin(G);
+ auto End = BFIter::end(G);
+ EXPECT_EQ(It.getLevel(), 0U);
+ EXPECT_EQ(*It, G.AccessNode(0));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 1U);
+ EXPECT_EQ(*It, G.AccessNode(1));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 1U);
+ EXPECT_EQ(*It, G.AccessNode(2));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 2U);
+ EXPECT_EQ(*It, G.AccessNode(3));
+ ++It;
+ EXPECT_EQ(It, End);
+}
+
+TEST(BreadthFristIteratorTest, Cycle) {
+ typedef bf_iterator<Graph<4>> BFIter;
+
+ Graph<4> G;
+ G.AddEdge(0, 1);
+ G.AddEdge(1, 0);
+ G.AddEdge(1, 2);
+ G.AddEdge(2, 1);
+ G.AddEdge(2, 1);
+ G.AddEdge(2, 3);
+ G.AddEdge(3, 2);
+ G.AddEdge(3, 1);
+ G.AddEdge(3, 0);
+
+ auto It = BFIter::begin(G);
+ auto End = BFIter::end(G);
+ EXPECT_EQ(It.getLevel(), 0U);
+ EXPECT_EQ(*It, G.AccessNode(0));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 1U);
+ EXPECT_EQ(*It, G.AccessNode(1));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 2U);
+ EXPECT_EQ(*It, G.AccessNode(2));
+ ++It;
+ EXPECT_EQ(It.getLevel(), 3U);
+ EXPECT_EQ(*It, G.AccessNode(3));
+ ++It;
+ EXPECT_EQ(It, End);
+}
+
+} // end namespace llvm
diff --git a/src/llvm-project/llvm/unittests/ADT/BumpPtrListTest.cpp b/src/llvm-project/llvm/unittests/ADT/BumpPtrListTest.cpp
new file mode 100644
index 0000000..be34a71
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/BumpPtrListTest.cpp
@@ -0,0 +1,243 @@
+//===- unittests/ADT/BumpPtrListTest.cpp - BumpPtrList unit tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/AllocatorList.h"
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+struct CountsDestructors {
+ static unsigned NumCalls;
+ ~CountsDestructors() { ++NumCalls; }
+};
+unsigned CountsDestructors::NumCalls = 0;
+
+struct MoveOnly {
+ int V;
+ explicit MoveOnly(int V) : V(V) {}
+ MoveOnly() = delete;
+ MoveOnly(MoveOnly &&X) { V = X.V; }
+ MoveOnly(const MoveOnly &X) = delete;
+ MoveOnly &operator=(MoveOnly &&X) = delete;
+ MoveOnly &operator=(const MoveOnly &X) = delete;
+};
+
+struct EmplaceOnly {
+ int V1, V2;
+ explicit EmplaceOnly(int V1, int V2) : V1(V1), V2(V2) {}
+ EmplaceOnly() = delete;
+ EmplaceOnly(EmplaceOnly &&X) = delete;
+ EmplaceOnly(const EmplaceOnly &X) = delete;
+ EmplaceOnly &operator=(EmplaceOnly &&X) = delete;
+ EmplaceOnly &operator=(const EmplaceOnly &X) = delete;
+};
+
+TEST(BumpPtrListTest, DefaultConstructor) {
+ BumpPtrList<int> L;
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(BumpPtrListTest, pushPopBack) {
+ // Build a list with push_back.
+ BumpPtrList<int> L;
+ int Ns[] = {1, 3, 9, 5, 7};
+ for (const int N : Ns)
+ L.push_back(N);
+
+ // Use iterators to check contents.
+ auto I = L.begin();
+ for (int N : Ns)
+ EXPECT_EQ(N, *I++);
+ EXPECT_EQ(I, L.end());
+
+ // Unbuild the list with pop_back.
+ for (int N : llvm::reverse(Ns)) {
+ EXPECT_EQ(N, L.back());
+ L.pop_back();
+ }
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(BumpPtrListTest, pushPopFront) {
+ // Build a list with push_front.
+ BumpPtrList<int> L;
+ int Ns[] = {1, 3, 9, 5, 7};
+ for (const int N : Ns)
+ L.push_front(N);
+
+ // Use reverse iterators to check contents.
+ auto I = L.rbegin();
+ for (int N : Ns)
+ EXPECT_EQ(N, *I++);
+ EXPECT_EQ(I, L.rend());
+
+ // Unbuild the list with pop_front.
+ for (int N : llvm::reverse(Ns)) {
+ EXPECT_EQ(N, L.front());
+ L.pop_front();
+ }
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(BumpPtrListTest, pushBackMoveOnly) {
+ BumpPtrList<MoveOnly> L;
+ int Ns[] = {1, 3, 9, 5, 7};
+ for (const int N : Ns) {
+ L.push_back(MoveOnly(N));
+ EXPECT_EQ(N, L.back().V);
+ }
+ // Instantiate with MoveOnly.
+ while (!L.empty())
+ L.pop_back();
+}
+
+TEST(BumpPtrListTest, pushFrontMoveOnly) {
+ BumpPtrList<MoveOnly> L;
+ int Ns[] = {1, 3, 9, 5, 7};
+ for (const int N : Ns) {
+ L.push_front(MoveOnly(N));
+ EXPECT_EQ(N, L.front().V);
+ }
+ // Instantiate with MoveOnly.
+ while (!L.empty())
+ L.pop_front();
+}
+
+TEST(BumpPtrListTest, emplaceBack) {
+ BumpPtrList<EmplaceOnly> L;
+ int N1s[] = {1, 3, 9, 5, 7};
+ int N2s[] = {7, 3, 1, 8, 2};
+ for (int I = 0; I != 5; ++I) {
+ L.emplace_back(N1s[I], N2s[I]);
+ EXPECT_EQ(N1s[I], L.back().V1);
+ EXPECT_EQ(N2s[I], L.back().V2);
+ }
+ // Instantiate with EmplaceOnly.
+ while (!L.empty())
+ L.pop_back();
+}
+
+TEST(BumpPtrListTest, emplaceFront) {
+ BumpPtrList<EmplaceOnly> L;
+ int N1s[] = {1, 3, 9, 5, 7};
+ int N2s[] = {7, 3, 1, 8, 2};
+ for (int I = 0; I != 5; ++I) {
+ L.emplace_front(N1s[I], N2s[I]);
+ EXPECT_EQ(N1s[I], L.front().V1);
+ EXPECT_EQ(N2s[I], L.front().V2);
+ }
+ // Instantiate with EmplaceOnly.
+ while (!L.empty())
+ L.pop_front();
+}
+
+TEST(BumpPtrListTest, swap) {
+ // Build two lists with different lifetimes and swap them.
+ int N1s[] = {1, 3, 5, 7, 9};
+ int N2s[] = {2, 4, 6, 8, 10};
+
+ BumpPtrList<int> L1;
+ L1.insert(L1.end(), std::begin(N1s), std::end(N1s));
+ {
+ BumpPtrList<int> L2;
+ L2.insert(L2.end(), std::begin(N2s), std::end(N2s));
+
+ // Swap the lists.
+ L1.swap(L2);
+
+ // Check L2's contents before it goes out of scope.
+ auto I = L2.begin();
+ for (int N : N1s)
+ EXPECT_EQ(N, *I++);
+ EXPECT_EQ(I, L2.end());
+ }
+
+ // Check L1's contents now that L2 is out of scope (with its allocation
+ // blocks).
+ auto I = L1.begin();
+ for (int N : N2s)
+ EXPECT_EQ(N, *I++);
+ EXPECT_EQ(I, L1.end());
+}
+
+TEST(BumpPtrListTest, clear) {
+ CountsDestructors::NumCalls = 0;
+ CountsDestructors N;
+ BumpPtrList<CountsDestructors> L;
+ L.push_back(N);
+ L.push_back(N);
+ L.push_back(N);
+ EXPECT_EQ(3u, L.size());
+ EXPECT_EQ(0u, CountsDestructors::NumCalls);
+ L.pop_back();
+ EXPECT_EQ(1u, CountsDestructors::NumCalls);
+ L.clear();
+ EXPECT_EQ(3u, CountsDestructors::NumCalls);
+}
+
+TEST(BumpPtrListTest, move) {
+ BumpPtrList<int> L1, L2;
+ L1.push_back(1);
+ L2.push_back(2);
+ L1 = std::move(L2);
+ EXPECT_EQ(1u, L1.size());
+ EXPECT_EQ(2, L1.front());
+ EXPECT_EQ(0u, L2.size());
+}
+
+TEST(BumpPtrListTest, moveCallsDestructors) {
+ CountsDestructors::NumCalls = 0;
+ BumpPtrList<CountsDestructors> L1, L2;
+ L1.emplace_back();
+ EXPECT_EQ(0u, CountsDestructors::NumCalls);
+ L1 = std::move(L2);
+ EXPECT_EQ(1u, CountsDestructors::NumCalls);
+}
+
+TEST(BumpPtrListTest, copy) {
+ BumpPtrList<int> L1, L2;
+ L1.push_back(1);
+ L2.push_back(2);
+ L1 = L2;
+ EXPECT_EQ(1u, L1.size());
+ EXPECT_EQ(2, L1.front());
+ EXPECT_EQ(1u, L2.size());
+ EXPECT_EQ(2, L2.front());
+}
+
+TEST(BumpPtrListTest, copyCallsDestructors) {
+ CountsDestructors::NumCalls = 0;
+ BumpPtrList<CountsDestructors> L1, L2;
+ L1.emplace_back();
+ EXPECT_EQ(0u, CountsDestructors::NumCalls);
+ L1 = L2;
+ EXPECT_EQ(1u, CountsDestructors::NumCalls);
+}
+
+TEST(BumpPtrListTest, resetAlloc) {
+ // Resetting an empty list should work.
+ BumpPtrList<int> L;
+
+ // Resetting an empty list that has allocated should also work.
+ L.resetAlloc();
+ L.push_back(5);
+ L.erase(L.begin());
+ L.resetAlloc();
+
+ // Resetting a non-empty list should crash.
+ L.push_back(5);
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
+ EXPECT_DEATH(L.resetAlloc(), "Cannot reset allocator if not empty");
+#endif
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/CMakeLists.txt b/src/llvm-project/llvm/unittests/ADT/CMakeLists.txt
new file mode 100644
index 0000000..098b6b6
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/CMakeLists.txt
@@ -0,0 +1,74 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_llvm_unittest(ADTTests
+ AnyTest.cpp
+ APFloatTest.cpp
+ APIntTest.cpp
+ APSIntTest.cpp
+ ArrayRefTest.cpp
+ BitmaskEnumTest.cpp
+ BitVectorTest.cpp
+ BreadthFirstIteratorTest.cpp
+ BumpPtrListTest.cpp
+ DAGDeltaAlgorithmTest.cpp
+ DeltaAlgorithmTest.cpp
+ DenseMapTest.cpp
+ DenseSetTest.cpp
+ DepthFirstIteratorTest.cpp
+ EquivalenceClassesTest.cpp
+ FoldingSet.cpp
+ FunctionExtrasTest.cpp
+ FunctionRefTest.cpp
+ HashingTest.cpp
+ IListBaseTest.cpp
+ IListIteratorTest.cpp
+ IListNodeBaseTest.cpp
+ IListNodeTest.cpp
+ IListSentinelTest.cpp
+ IListTest.cpp
+ ImmutableListTest.cpp
+ ImmutableMapTest.cpp
+ ImmutableSetTest.cpp
+ IntEqClassesTest.cpp
+ IntervalMapTest.cpp
+ IntrusiveRefCntPtrTest.cpp
+ IteratorTest.cpp
+ MakeUniqueTest.cpp
+ MappedIteratorTest.cpp
+ MapVectorTest.cpp
+ OptionalTest.cpp
+ PackedVectorTest.cpp
+ PointerEmbeddedIntTest.cpp
+ PointerIntPairTest.cpp
+ PointerSumTypeTest.cpp
+ PointerUnionTest.cpp
+ PostOrderIteratorTest.cpp
+ PriorityWorklistTest.cpp
+ RangeAdapterTest.cpp
+ SCCIteratorTest.cpp
+ STLExtrasTest.cpp
+ ScopeExitTest.cpp
+ SequenceTest.cpp
+ SetVectorTest.cpp
+ SimpleIListTest.cpp
+ SmallPtrSetTest.cpp
+ SmallSetTest.cpp
+ SmallStringTest.cpp
+ SmallVectorTest.cpp
+ SparseBitVectorTest.cpp
+ SparseMultiSetTest.cpp
+ SparseSetTest.cpp
+ StatisticTest.cpp
+ StringExtrasTest.cpp
+ StringMapTest.cpp
+ StringRefTest.cpp
+ StringSwitchTest.cpp
+ TinyPtrVectorTest.cpp
+ TripleTest.cpp
+ TwineTest.cpp
+ VariadicFunctionTest.cpp
+ )
+
+add_dependencies(ADTTests intrinsics_gen)
diff --git a/src/llvm-project/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp b/src/llvm-project/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp
new file mode 100644
index 0000000..030fadb
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp
@@ -0,0 +1,105 @@
+//===- llvm/unittest/ADT/DAGDeltaAlgorithmTest.cpp ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DAGDeltaAlgorithm.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <cstdarg>
+using namespace llvm;
+
+namespace {
+
+typedef DAGDeltaAlgorithm::edge_ty edge_ty;
+
+class FixedDAGDeltaAlgorithm : public DAGDeltaAlgorithm {
+ changeset_ty FailingSet;
+ unsigned NumTests;
+
+protected:
+ bool ExecuteOneTest(const changeset_ty &Changes) override {
+ ++NumTests;
+ return std::includes(Changes.begin(), Changes.end(),
+ FailingSet.begin(), FailingSet.end());
+ }
+
+public:
+ FixedDAGDeltaAlgorithm(const changeset_ty &_FailingSet)
+ : FailingSet(_FailingSet),
+ NumTests(0) {}
+
+ unsigned getNumTests() const { return NumTests; }
+};
+
+std::set<unsigned> fixed_set(unsigned N, ...) {
+ std::set<unsigned> S;
+ va_list ap;
+ va_start(ap, N);
+ for (unsigned i = 0; i != N; ++i)
+ S.insert(va_arg(ap, unsigned));
+ va_end(ap);
+ return S;
+}
+
+std::set<unsigned> range(unsigned Start, unsigned End) {
+ std::set<unsigned> S;
+ while (Start != End)
+ S.insert(Start++);
+ return S;
+}
+
+std::set<unsigned> range(unsigned N) {
+ return range(0, N);
+}
+
+TEST(DAGDeltaAlgorithmTest, Basic) {
+ std::vector<edge_ty> Deps;
+
+ // Dependencies:
+ // 1 - 3
+ Deps.clear();
+ Deps.push_back(std::make_pair(3, 1));
+
+ // P = {3,5,7} \in S,
+ // [0, 20),
+ // should minimize to {1,3,5,7} in a reasonable number of tests.
+ FixedDAGDeltaAlgorithm FDA(fixed_set(3, 3, 5, 7));
+ EXPECT_EQ(fixed_set(4, 1, 3, 5, 7), FDA.Run(range(20), Deps));
+ EXPECT_GE(46U, FDA.getNumTests());
+
+ // Dependencies:
+ // 0 - 1
+ // \- 2 - 3
+ // \- 4
+ Deps.clear();
+ Deps.push_back(std::make_pair(1, 0));
+ Deps.push_back(std::make_pair(2, 0));
+ Deps.push_back(std::make_pair(4, 0));
+ Deps.push_back(std::make_pair(3, 2));
+
+ // This is a case where we must hold required changes.
+ //
+ // P = {1,3} \in S,
+ // [0, 5),
+ // should minimize to {0,1,2,3} in a small number of tests.
+ FixedDAGDeltaAlgorithm FDA2(fixed_set(2, 1, 3));
+ EXPECT_EQ(fixed_set(4, 0, 1, 2, 3), FDA2.Run(range(5), Deps));
+ EXPECT_GE(9U, FDA2.getNumTests());
+
+ // This is a case where we should quickly prune part of the tree.
+ //
+ // P = {4} \in S,
+ // [0, 5),
+ // should minimize to {0,4} in a small number of tests.
+ FixedDAGDeltaAlgorithm FDA3(fixed_set(1, 4));
+ EXPECT_EQ(fixed_set(2, 0, 4), FDA3.Run(range(5), Deps));
+ EXPECT_GE(6U, FDA3.getNumTests());
+}
+
+}
+
diff --git a/src/llvm-project/llvm/unittests/ADT/DeltaAlgorithmTest.cpp b/src/llvm-project/llvm/unittests/ADT/DeltaAlgorithmTest.cpp
new file mode 100644
index 0000000..01dc1f3
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/DeltaAlgorithmTest.cpp
@@ -0,0 +1,100 @@
+//===- llvm/unittest/ADT/DeltaAlgorithmTest.cpp ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DeltaAlgorithm.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <cstdarg>
+using namespace llvm;
+
+namespace std {
+
+std::ostream &operator<<(std::ostream &OS,
+ const std::set<unsigned> &S) {
+ OS << "{";
+ for (std::set<unsigned>::const_iterator it = S.begin(),
+ ie = S.end(); it != ie; ++it) {
+ if (it != S.begin())
+ OS << ",";
+ OS << *it;
+ }
+ OS << "}";
+ return OS;
+}
+
+}
+
+namespace {
+
+class FixedDeltaAlgorithm final : public DeltaAlgorithm {
+ changeset_ty FailingSet;
+ unsigned NumTests;
+
+protected:
+ bool ExecuteOneTest(const changeset_ty &Changes) override {
+ ++NumTests;
+ return std::includes(Changes.begin(), Changes.end(),
+ FailingSet.begin(), FailingSet.end());
+ }
+
+public:
+ FixedDeltaAlgorithm(const changeset_ty &_FailingSet)
+ : FailingSet(_FailingSet),
+ NumTests(0) {}
+
+ unsigned getNumTests() const { return NumTests; }
+};
+
+std::set<unsigned> fixed_set(unsigned N, ...) {
+ std::set<unsigned> S;
+ va_list ap;
+ va_start(ap, N);
+ for (unsigned i = 0; i != N; ++i)
+ S.insert(va_arg(ap, unsigned));
+ va_end(ap);
+ return S;
+}
+
+std::set<unsigned> range(unsigned Start, unsigned End) {
+ std::set<unsigned> S;
+ while (Start != End)
+ S.insert(Start++);
+ return S;
+}
+
+std::set<unsigned> range(unsigned N) {
+ return range(0, N);
+}
+
+TEST(DeltaAlgorithmTest, Basic) {
+ // P = {3,5,7} \in S
+ // [0, 20) should minimize to {3,5,7} in a reasonable number of tests.
+ std::set<unsigned> Fails = fixed_set(3, 3, 5, 7);
+ FixedDeltaAlgorithm FDA(Fails);
+ EXPECT_EQ(fixed_set(3, 3, 5, 7), FDA.Run(range(20)));
+ EXPECT_GE(33U, FDA.getNumTests());
+
+ // P = {3,5,7} \in S
+ // [10, 20) should minimize to [10,20)
+ EXPECT_EQ(range(10,20), FDA.Run(range(10,20)));
+
+ // P = [0,4) \in S
+ // [0, 4) should minimize to [0,4) in 11 tests.
+ //
+ // 11 = |{ {},
+ // {0}, {1}, {2}, {3},
+ // {1, 2, 3}, {0, 2, 3}, {0, 1, 3}, {0, 1, 2},
+ // {0, 1}, {2, 3} }|
+ FDA = FixedDeltaAlgorithm(range(10));
+ EXPECT_EQ(range(4), FDA.Run(range(4)));
+ EXPECT_EQ(11U, FDA.getNumTests());
+}
+
+}
+
diff --git a/src/llvm-project/llvm/unittests/ADT/DenseMapTest.cpp b/src/llvm-project/llvm/unittests/ADT/DenseMapTest.cpp
new file mode 100644
index 0000000..ee9c5dd
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/DenseMapTest.cpp
@@ -0,0 +1,617 @@
+//===- llvm/unittest/ADT/DenseMapMap.cpp - DenseMap unit tests --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseMap.h"
+#include "gtest/gtest.h"
+#include <map>
+#include <set>
+
+using namespace llvm;
+
+namespace {
+
+uint32_t getTestKey(int i, uint32_t *) { return i; }
+uint32_t getTestValue(int i, uint32_t *) { return 42 + i; }
+
+uint32_t *getTestKey(int i, uint32_t **) {
+ static uint32_t dummy_arr1[8192];
+ assert(i < 8192 && "Only support 8192 dummy keys.");
+ return &dummy_arr1[i];
+}
+uint32_t *getTestValue(int i, uint32_t **) {
+ static uint32_t dummy_arr1[8192];
+ assert(i < 8192 && "Only support 8192 dummy keys.");
+ return &dummy_arr1[i];
+}
+
+/// A test class that tries to check that construction and destruction
+/// occur correctly.
+class CtorTester {
+ static std::set<CtorTester *> Constructed;
+ int Value;
+
+public:
+ explicit CtorTester(int Value = 0) : Value(Value) {
+ EXPECT_TRUE(Constructed.insert(this).second);
+ }
+ CtorTester(uint32_t Value) : Value(Value) {
+ EXPECT_TRUE(Constructed.insert(this).second);
+ }
+ CtorTester(const CtorTester &Arg) : Value(Arg.Value) {
+ EXPECT_TRUE(Constructed.insert(this).second);
+ }
+ CtorTester &operator=(const CtorTester &) = default;
+ ~CtorTester() {
+ EXPECT_EQ(1u, Constructed.erase(this));
+ }
+ operator uint32_t() const { return Value; }
+
+ int getValue() const { return Value; }
+ bool operator==(const CtorTester &RHS) const { return Value == RHS.Value; }
+};
+
+std::set<CtorTester *> CtorTester::Constructed;
+
+struct CtorTesterMapInfo {
+ static inline CtorTester getEmptyKey() { return CtorTester(-1); }
+ static inline CtorTester getTombstoneKey() { return CtorTester(-2); }
+ static unsigned getHashValue(const CtorTester &Val) {
+ return Val.getValue() * 37u;
+ }
+ static bool isEqual(const CtorTester &LHS, const CtorTester &RHS) {
+ return LHS == RHS;
+ }
+};
+
+CtorTester getTestKey(int i, CtorTester *) { return CtorTester(i); }
+CtorTester getTestValue(int i, CtorTester *) { return CtorTester(42 + i); }
+
+// Test fixture, with helper functions implemented by forwarding to global
+// function overloads selected by component types of the type parameter. This
+// allows all of the map implementations to be tested with shared
+// implementations of helper routines.
+template <typename T>
+class DenseMapTest : public ::testing::Test {
+protected:
+ T Map;
+
+ static typename T::key_type *const dummy_key_ptr;
+ static typename T::mapped_type *const dummy_value_ptr;
+
+ typename T::key_type getKey(int i = 0) {
+ return getTestKey(i, dummy_key_ptr);
+ }
+ typename T::mapped_type getValue(int i = 0) {
+ return getTestValue(i, dummy_value_ptr);
+ }
+};
+
+template <typename T>
+typename T::key_type *const DenseMapTest<T>::dummy_key_ptr = nullptr;
+template <typename T>
+typename T::mapped_type *const DenseMapTest<T>::dummy_value_ptr = nullptr;
+
+// Register these types for testing.
+typedef ::testing::Types<DenseMap<uint32_t, uint32_t>,
+ DenseMap<uint32_t *, uint32_t *>,
+ DenseMap<CtorTester, CtorTester, CtorTesterMapInfo>,
+ SmallDenseMap<uint32_t, uint32_t>,
+ SmallDenseMap<uint32_t *, uint32_t *>,
+ SmallDenseMap<CtorTester, CtorTester, 4,
+ CtorTesterMapInfo>
+ > DenseMapTestTypes;
+TYPED_TEST_CASE(DenseMapTest, DenseMapTestTypes);
+
+// Empty map tests
+TYPED_TEST(DenseMapTest, EmptyIntMapTest) {
+ // Size tests
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+
+ // Iterator tests
+ EXPECT_TRUE(this->Map.begin() == this->Map.end());
+
+ // Lookup tests
+ EXPECT_FALSE(this->Map.count(this->getKey()));
+ EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.end());
+#if !defined(_MSC_VER) || defined(__clang__)
+ EXPECT_EQ(typename TypeParam::mapped_type(),
+ this->Map.lookup(this->getKey()));
+#else
+ // MSVC, at least old versions, cannot parse the typename to disambiguate
+ // TypeParam::mapped_type as a type. However, because MSVC doesn't implement
+ // two-phase name lookup, it also doesn't require the typename. Deal with
+ // this mutual incompatibility through specialized code.
+ EXPECT_EQ(TypeParam::mapped_type(),
+ this->Map.lookup(this->getKey()));
+#endif
+}
+
+// Constant map tests
+TYPED_TEST(DenseMapTest, ConstEmptyMapTest) {
+ const TypeParam &ConstMap = this->Map;
+ EXPECT_EQ(0u, ConstMap.size());
+ EXPECT_TRUE(ConstMap.empty());
+ EXPECT_TRUE(ConstMap.begin() == ConstMap.end());
+}
+
+// A map with a single entry
+TYPED_TEST(DenseMapTest, SingleEntryMapTest) {
+ this->Map[this->getKey()] = this->getValue();
+
+ // Size tests
+ EXPECT_EQ(1u, this->Map.size());
+ EXPECT_FALSE(this->Map.begin() == this->Map.end());
+ EXPECT_FALSE(this->Map.empty());
+
+ // Iterator tests
+ typename TypeParam::iterator it = this->Map.begin();
+ EXPECT_EQ(this->getKey(), it->first);
+ EXPECT_EQ(this->getValue(), it->second);
+ ++it;
+ EXPECT_TRUE(it == this->Map.end());
+
+ // Lookup tests
+ EXPECT_TRUE(this->Map.count(this->getKey()));
+ EXPECT_TRUE(this->Map.find(this->getKey()) == this->Map.begin());
+ EXPECT_EQ(this->getValue(), this->Map.lookup(this->getKey()));
+ EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
+}
+
+// Test clear() method
+TYPED_TEST(DenseMapTest, ClearTest) {
+ this->Map[this->getKey()] = this->getValue();
+ this->Map.clear();
+
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+ EXPECT_TRUE(this->Map.begin() == this->Map.end());
+}
+
+// Test erase(iterator) method
+TYPED_TEST(DenseMapTest, EraseTest) {
+ this->Map[this->getKey()] = this->getValue();
+ this->Map.erase(this->Map.begin());
+
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+ EXPECT_TRUE(this->Map.begin() == this->Map.end());
+}
+
+// Test erase(value) method
+TYPED_TEST(DenseMapTest, EraseTest2) {
+ this->Map[this->getKey()] = this->getValue();
+ this->Map.erase(this->getKey());
+
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+ EXPECT_TRUE(this->Map.begin() == this->Map.end());
+}
+
+// Test insert() method
+TYPED_TEST(DenseMapTest, InsertTest) {
+ this->Map.insert(std::make_pair(this->getKey(), this->getValue()));
+ EXPECT_EQ(1u, this->Map.size());
+ EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
+}
+
+// Test copy constructor method
+TYPED_TEST(DenseMapTest, CopyConstructorTest) {
+ this->Map[this->getKey()] = this->getValue();
+ TypeParam copyMap(this->Map);
+
+ EXPECT_EQ(1u, copyMap.size());
+ EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
+}
+
+// Test copy constructor method where SmallDenseMap isn't small.
+TYPED_TEST(DenseMapTest, CopyConstructorNotSmallTest) {
+ for (int Key = 0; Key < 5; ++Key)
+ this->Map[this->getKey(Key)] = this->getValue(Key);
+ TypeParam copyMap(this->Map);
+
+ EXPECT_EQ(5u, copyMap.size());
+ for (int Key = 0; Key < 5; ++Key)
+ EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
+}
+
+// Test copying from a default-constructed map.
+TYPED_TEST(DenseMapTest, CopyConstructorFromDefaultTest) {
+ TypeParam copyMap(this->Map);
+
+ EXPECT_TRUE(copyMap.empty());
+}
+
+// Test copying from an empty map where SmallDenseMap isn't small.
+TYPED_TEST(DenseMapTest, CopyConstructorFromEmptyTest) {
+ for (int Key = 0; Key < 5; ++Key)
+ this->Map[this->getKey(Key)] = this->getValue(Key);
+ this->Map.clear();
+ TypeParam copyMap(this->Map);
+
+ EXPECT_TRUE(copyMap.empty());
+}
+
+// Test assignment operator method
+TYPED_TEST(DenseMapTest, AssignmentTest) {
+ this->Map[this->getKey()] = this->getValue();
+ TypeParam copyMap = this->Map;
+
+ EXPECT_EQ(1u, copyMap.size());
+ EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
+
+ // test self-assignment.
+ copyMap = static_cast<TypeParam &>(copyMap);
+ EXPECT_EQ(1u, copyMap.size());
+ EXPECT_EQ(this->getValue(), copyMap[this->getKey()]);
+}
+
+TYPED_TEST(DenseMapTest, AssignmentTestNotSmall) {
+ for (int Key = 0; Key < 5; ++Key)
+ this->Map[this->getKey(Key)] = this->getValue(Key);
+ TypeParam copyMap = this->Map;
+
+ EXPECT_EQ(5u, copyMap.size());
+ for (int Key = 0; Key < 5; ++Key)
+ EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
+
+ // test self-assignment.
+ copyMap = static_cast<TypeParam &>(copyMap);
+ EXPECT_EQ(5u, copyMap.size());
+ for (int Key = 0; Key < 5; ++Key)
+ EXPECT_EQ(this->getValue(Key), copyMap[this->getKey(Key)]);
+}
+
+// Test swap method
+TYPED_TEST(DenseMapTest, SwapTest) {
+ this->Map[this->getKey()] = this->getValue();
+ TypeParam otherMap;
+
+ this->Map.swap(otherMap);
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+ EXPECT_EQ(1u, otherMap.size());
+ EXPECT_EQ(this->getValue(), otherMap[this->getKey()]);
+
+ this->Map.swap(otherMap);
+ EXPECT_EQ(0u, otherMap.size());
+ EXPECT_TRUE(otherMap.empty());
+ EXPECT_EQ(1u, this->Map.size());
+ EXPECT_EQ(this->getValue(), this->Map[this->getKey()]);
+
+ // Make this more interesting by inserting 100 numbers into the map.
+ for (int i = 0; i < 100; ++i)
+ this->Map[this->getKey(i)] = this->getValue(i);
+
+ this->Map.swap(otherMap);
+ EXPECT_EQ(0u, this->Map.size());
+ EXPECT_TRUE(this->Map.empty());
+ EXPECT_EQ(100u, otherMap.size());
+ for (int i = 0; i < 100; ++i)
+ EXPECT_EQ(this->getValue(i), otherMap[this->getKey(i)]);
+
+ this->Map.swap(otherMap);
+ EXPECT_EQ(0u, otherMap.size());
+ EXPECT_TRUE(otherMap.empty());
+ EXPECT_EQ(100u, this->Map.size());
+ for (int i = 0; i < 100; ++i)
+ EXPECT_EQ(this->getValue(i), this->Map[this->getKey(i)]);
+}
+
+// A more complex iteration test
+TYPED_TEST(DenseMapTest, IterationTest) {
+ bool visited[100];
+ std::map<typename TypeParam::key_type, unsigned> visitedIndex;
+
+ // Insert 100 numbers into the map
+ for (int i = 0; i < 100; ++i) {
+ visited[i] = false;
+ visitedIndex[this->getKey(i)] = i;
+
+ this->Map[this->getKey(i)] = this->getValue(i);
+ }
+
+ // Iterate over all numbers and mark each one found.
+ for (typename TypeParam::iterator it = this->Map.begin();
+ it != this->Map.end(); ++it)
+ visited[visitedIndex[it->first]] = true;
+
+ // Ensure every number was visited.
+ for (int i = 0; i < 100; ++i)
+ ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
+}
+
+// const_iterator test
+TYPED_TEST(DenseMapTest, ConstIteratorTest) {
+ // Check conversion from iterator to const_iterator.
+ typename TypeParam::iterator it = this->Map.begin();
+ typename TypeParam::const_iterator cit(it);
+ EXPECT_TRUE(it == cit);
+
+ // Check copying of const_iterators.
+ typename TypeParam::const_iterator cit2(cit);
+ EXPECT_TRUE(cit == cit2);
+}
+
+namespace {
+// Simple class that counts how many moves and copy happens when growing a map
+struct CountCopyAndMove {
+ static int Move;
+ static int Copy;
+ CountCopyAndMove() {}
+
+ CountCopyAndMove(const CountCopyAndMove &) { Copy++; }
+ CountCopyAndMove &operator=(const CountCopyAndMove &) {
+ Copy++;
+ return *this;
+ }
+ CountCopyAndMove(CountCopyAndMove &&) { Move++; }
+ CountCopyAndMove &operator=(const CountCopyAndMove &&) {
+ Move++;
+ return *this;
+ }
+};
+int CountCopyAndMove::Copy = 0;
+int CountCopyAndMove::Move = 0;
+
+} // anonymous namespace
+
+// Test initializer list construction.
+TEST(DenseMapCustomTest, InitializerList) {
+ DenseMap<int, int> M({{0, 0}, {0, 1}, {1, 2}});
+ EXPECT_EQ(2u, M.size());
+ EXPECT_EQ(1u, M.count(0));
+ EXPECT_EQ(0, M[0]);
+ EXPECT_EQ(1u, M.count(1));
+ EXPECT_EQ(2, M[1]);
+}
+
+// Test initializer list construction.
+TEST(DenseMapCustomTest, EqualityComparison) {
+ DenseMap<int, int> M1({{0, 0}, {1, 2}});
+ DenseMap<int, int> M2({{0, 0}, {1, 2}});
+ DenseMap<int, int> M3({{0, 0}, {1, 3}});
+
+ EXPECT_EQ(M1, M2);
+ EXPECT_NE(M1, M3);
+}
+
+// Test for the default minimum size of a DenseMap
+TEST(DenseMapCustomTest, DefaultMinReservedSizeTest) {
+ // IF THIS VALUE CHANGE, please update InitialSizeTest, InitFromIterator, and
+ // ReserveTest as well!
+ const int ExpectedInitialBucketCount = 64;
+ // Formula from DenseMap::getMinBucketToReserveForEntries()
+ const int ExpectedMaxInitialEntries = ExpectedInitialBucketCount * 3 / 4 - 1;
+
+ DenseMap<int, CountCopyAndMove> Map;
+ // Will allocate 64 buckets
+ Map.reserve(1);
+ unsigned MemorySize = Map.getMemorySize();
+ CountCopyAndMove::Copy = 0;
+ CountCopyAndMove::Move = 0;
+ for (int i = 0; i < ExpectedMaxInitialEntries; ++i)
+ Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
+ std::forward_as_tuple(i),
+ std::forward_as_tuple()));
+ // Check that we didn't grow
+ EXPECT_EQ(MemorySize, Map.getMemorySize());
+ // Check that move was called the expected number of times
+ EXPECT_EQ(ExpectedMaxInitialEntries, CountCopyAndMove::Move);
+ // Check that no copy occurred
+ EXPECT_EQ(0, CountCopyAndMove::Copy);
+
+ // Adding one extra element should grow the map
+ Map.insert(std::pair<int, CountCopyAndMove>(
+ std::piecewise_construct,
+ std::forward_as_tuple(ExpectedMaxInitialEntries),
+ std::forward_as_tuple()));
+ // Check that we grew
+ EXPECT_NE(MemorySize, Map.getMemorySize());
+ // Check that move was called the expected number of times
+ // This relies on move-construction elision, and cannot be reliably tested.
+ // EXPECT_EQ(ExpectedMaxInitialEntries + 2, CountCopyAndMove::Move);
+ // Check that no copy occurred
+ EXPECT_EQ(0, CountCopyAndMove::Copy);
+}
+
+// Make sure creating the map with an initial size of N actually gives us enough
+// buckets to insert N items without increasing allocation size.
+TEST(DenseMapCustomTest, InitialSizeTest) {
+ // Test a few different sizes, 48 is *not* a random choice: we need a value
+ // that is 2/3 of a power of two to stress the grow() condition, and the power
+ // of two has to be at least 64 because of minimum size allocation in the
+ // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
+ // 64 default init.
+ for (auto Size : {1, 2, 48, 66}) {
+ DenseMap<int, CountCopyAndMove> Map(Size);
+ unsigned MemorySize = Map.getMemorySize();
+ CountCopyAndMove::Copy = 0;
+ CountCopyAndMove::Move = 0;
+ for (int i = 0; i < Size; ++i)
+ Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
+ std::forward_as_tuple(i),
+ std::forward_as_tuple()));
+ // Check that we didn't grow
+ EXPECT_EQ(MemorySize, Map.getMemorySize());
+ // Check that move was called the expected number of times
+ EXPECT_EQ(Size, CountCopyAndMove::Move);
+ // Check that no copy occurred
+ EXPECT_EQ(0, CountCopyAndMove::Copy);
+ }
+}
+
+// Make sure creating the map with a iterator range does not trigger grow()
+TEST(DenseMapCustomTest, InitFromIterator) {
+ std::vector<std::pair<int, CountCopyAndMove>> Values;
+ // The size is a random value greater than 64 (hardcoded DenseMap min init)
+ const int Count = 65;
+ for (int i = 0; i < Count; i++)
+ Values.emplace_back(i, CountCopyAndMove());
+
+ CountCopyAndMove::Move = 0;
+ CountCopyAndMove::Copy = 0;
+ DenseMap<int, CountCopyAndMove> Map(Values.begin(), Values.end());
+ // Check that no move occurred
+ EXPECT_EQ(0, CountCopyAndMove::Move);
+ // Check that copy was called the expected number of times
+ EXPECT_EQ(Count, CountCopyAndMove::Copy);
+}
+
+// Make sure reserve actually gives us enough buckets to insert N items
+// without increasing allocation size.
+TEST(DenseMapCustomTest, ReserveTest) {
+ // Test a few different size, 48 is *not* a random choice: we need a value
+ // that is 2/3 of a power of two to stress the grow() condition, and the power
+ // of two has to be at least 64 because of minimum size allocation in the
+ // DenseMap (see DefaultMinReservedSizeTest). 66 is a value just above the
+ // 64 default init.
+ for (auto Size : {1, 2, 48, 66}) {
+ DenseMap<int, CountCopyAndMove> Map;
+ Map.reserve(Size);
+ unsigned MemorySize = Map.getMemorySize();
+ CountCopyAndMove::Copy = 0;
+ CountCopyAndMove::Move = 0;
+ for (int i = 0; i < Size; ++i)
+ Map.insert(std::pair<int, CountCopyAndMove>(std::piecewise_construct,
+ std::forward_as_tuple(i),
+ std::forward_as_tuple()));
+ // Check that we didn't grow
+ EXPECT_EQ(MemorySize, Map.getMemorySize());
+ // Check that move was called the expected number of times
+ EXPECT_EQ(Size, CountCopyAndMove::Move);
+ // Check that no copy occurred
+ EXPECT_EQ(0, CountCopyAndMove::Copy);
+ }
+}
+
+// Make sure DenseMap works with StringRef keys.
+TEST(DenseMapCustomTest, StringRefTest) {
+ DenseMap<StringRef, int> M;
+
+ M["a"] = 1;
+ M["b"] = 2;
+ M["c"] = 3;
+
+ EXPECT_EQ(3u, M.size());
+ EXPECT_EQ(1, M.lookup("a"));
+ EXPECT_EQ(2, M.lookup("b"));
+ EXPECT_EQ(3, M.lookup("c"));
+
+ EXPECT_EQ(0, M.lookup("q"));
+
+ // Test the empty string, spelled various ways.
+ EXPECT_EQ(0, M.lookup(""));
+ EXPECT_EQ(0, M.lookup(StringRef()));
+ EXPECT_EQ(0, M.lookup(StringRef("a", 0)));
+ M[""] = 42;
+ EXPECT_EQ(42, M.lookup(""));
+ EXPECT_EQ(42, M.lookup(StringRef()));
+ EXPECT_EQ(42, M.lookup(StringRef("a", 0)));
+}
+
+// Key traits that allows lookup with either an unsigned or char* key;
+// In the latter case, "a" == 0, "b" == 1 and so on.
+struct TestDenseMapInfo {
+ static inline unsigned getEmptyKey() { return ~0; }
+ static inline unsigned getTombstoneKey() { return ~0U - 1; }
+ static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+ static unsigned getHashValue(const char* Val) {
+ return (unsigned)(Val[0] - 'a') * 37U;
+ }
+ static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+ return LHS == RHS;
+ }
+ static bool isEqual(const char* LHS, const unsigned& RHS) {
+ return (unsigned)(LHS[0] - 'a') == RHS;
+ }
+};
+
+// find_as() tests
+TEST(DenseMapCustomTest, FindAsTest) {
+ DenseMap<unsigned, unsigned, TestDenseMapInfo> map;
+ map[0] = 1;
+ map[1] = 2;
+ map[2] = 3;
+
+ // Size tests
+ EXPECT_EQ(3u, map.size());
+
+ // Normal lookup tests
+ EXPECT_EQ(1u, map.count(1));
+ EXPECT_EQ(1u, map.find(0)->second);
+ EXPECT_EQ(2u, map.find(1)->second);
+ EXPECT_EQ(3u, map.find(2)->second);
+ EXPECT_TRUE(map.find(3) == map.end());
+
+ // find_as() tests
+ EXPECT_EQ(1u, map.find_as("a")->second);
+ EXPECT_EQ(2u, map.find_as("b")->second);
+ EXPECT_EQ(3u, map.find_as("c")->second);
+ EXPECT_TRUE(map.find_as("d") == map.end());
+}
+
+struct ContiguousDenseMapInfo {
+ static inline unsigned getEmptyKey() { return ~0; }
+ static inline unsigned getTombstoneKey() { return ~0U - 1; }
+ static unsigned getHashValue(const unsigned& Val) { return Val; }
+ static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+ return LHS == RHS;
+ }
+};
+
+// Test that filling a small dense map with exactly the number of elements in
+// the map grows to have enough space for an empty bucket.
+TEST(DenseMapCustomTest, SmallDenseMapGrowTest) {
+ SmallDenseMap<unsigned, unsigned, 32, ContiguousDenseMapInfo> map;
+ // Add some number of elements, then delete a few to leave us some tombstones.
+ // If we just filled the map with 32 elements we'd grow because of not enough
+ // tombstones which masks the issue here.
+ for (unsigned i = 0; i < 20; ++i)
+ map[i] = i + 1;
+ for (unsigned i = 0; i < 10; ++i)
+ map.erase(i);
+ for (unsigned i = 20; i < 32; ++i)
+ map[i] = i + 1;
+
+ // Size tests
+ EXPECT_EQ(22u, map.size());
+
+ // Try to find an element which doesn't exist. There was a bug in
+ // SmallDenseMap which led to a map with num elements == small capacity not
+ // having an empty bucket any more. Finding an element not in the map would
+ // therefore never terminate.
+ EXPECT_TRUE(map.find(32) == map.end());
+}
+
+TEST(DenseMapCustomTest, TryEmplaceTest) {
+ DenseMap<int, std::unique_ptr<int>> Map;
+ std::unique_ptr<int> P(new int(2));
+ auto Try1 = Map.try_emplace(0, new int(1));
+ EXPECT_TRUE(Try1.second);
+ auto Try2 = Map.try_emplace(0, std::move(P));
+ EXPECT_FALSE(Try2.second);
+ EXPECT_EQ(Try1.first, Try2.first);
+ EXPECT_NE(nullptr, P);
+}
+
+TEST(DenseMapCustomTest, ConstTest) {
+ // Test that const pointers work okay for count and find, even when the
+ // underlying map is a non-const pointer.
+ DenseMap<int *, int> Map;
+ int A;
+ int *B = &A;
+ const int *C = &A;
+ Map.insert({B, 0});
+ EXPECT_EQ(Map.count(B), 1u);
+ EXPECT_EQ(Map.count(C), 1u);
+ EXPECT_NE(Map.find(B), Map.end());
+ EXPECT_NE(Map.find(C), Map.end());
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/DenseSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/DenseSetTest.cpp
new file mode 100644
index 0000000..7368e2e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/DenseSetTest.cpp
@@ -0,0 +1,225 @@
+//===- llvm/unittest/ADT/DenseSetTest.cpp - DenseSet unit tests --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseSet.h"
+#include "gtest/gtest.h"
+#include <type_traits>
+
+using namespace llvm;
+
+namespace {
+
+static_assert(std::is_const<std::remove_pointer<
+ DenseSet<int>::const_iterator::pointer>::type>::value,
+ "Iterator pointer type should be const");
+static_assert(std::is_const<std::remove_reference<
+ DenseSet<int>::const_iterator::reference>::type>::value,
+ "Iterator reference type should be const");
+
+// Test hashing with a set of only two entries.
+TEST(DenseSetTest, DoubleEntrySetTest) {
+ llvm::DenseSet<unsigned> set(2);
+ set.insert(0);
+ set.insert(1);
+ // Original failure was an infinite loop in this call:
+ EXPECT_EQ(0u, set.count(2));
+}
+
+struct TestDenseSetInfo {
+ static inline unsigned getEmptyKey() { return ~0; }
+ static inline unsigned getTombstoneKey() { return ~0U - 1; }
+ static unsigned getHashValue(const unsigned& Val) { return Val * 37U; }
+ static unsigned getHashValue(const char* Val) {
+ return (unsigned)(Val[0] - 'a') * 37U;
+ }
+ static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
+ return LHS == RHS;
+ }
+ static bool isEqual(const char* LHS, const unsigned& RHS) {
+ return (unsigned)(LHS[0] - 'a') == RHS;
+ }
+};
+
+// Test fixture
+template <typename T> class DenseSetTest : public testing::Test {
+protected:
+ T Set = GetTestSet();
+
+private:
+ static T GetTestSet() {
+ typename std::remove_const<T>::type Set;
+ Set.insert(0);
+ Set.insert(1);
+ Set.insert(2);
+ return Set;
+ }
+};
+
+// Register these types for testing.
+typedef ::testing::Types<DenseSet<unsigned, TestDenseSetInfo>,
+ const DenseSet<unsigned, TestDenseSetInfo>,
+ SmallDenseSet<unsigned, 1, TestDenseSetInfo>,
+ SmallDenseSet<unsigned, 4, TestDenseSetInfo>,
+ const SmallDenseSet<unsigned, 4, TestDenseSetInfo>,
+ SmallDenseSet<unsigned, 64, TestDenseSetInfo>>
+ DenseSetTestTypes;
+TYPED_TEST_CASE(DenseSetTest, DenseSetTestTypes);
+
+TYPED_TEST(DenseSetTest, InitializerList) {
+ TypeParam set({1, 2, 1, 4});
+ EXPECT_EQ(3u, set.size());
+ EXPECT_EQ(1u, set.count(1));
+ EXPECT_EQ(1u, set.count(2));
+ EXPECT_EQ(1u, set.count(4));
+ EXPECT_EQ(0u, set.count(3));
+}
+
+TYPED_TEST(DenseSetTest, InitializerListWithNonPowerOfTwoLength) {
+ TypeParam set({1, 2, 3});
+ EXPECT_EQ(3u, set.size());
+ EXPECT_EQ(1u, set.count(1));
+ EXPECT_EQ(1u, set.count(2));
+ EXPECT_EQ(1u, set.count(3));
+}
+
+TYPED_TEST(DenseSetTest, ConstIteratorComparison) {
+ TypeParam set({1});
+ const TypeParam &cset = set;
+ EXPECT_EQ(set.begin(), cset.begin());
+ EXPECT_EQ(set.end(), cset.end());
+ EXPECT_NE(set.end(), cset.begin());
+ EXPECT_NE(set.begin(), cset.end());
+}
+
+TYPED_TEST(DenseSetTest, DefaultConstruction) {
+ typename TypeParam::iterator I, J;
+ typename TypeParam::const_iterator CI, CJ;
+ EXPECT_EQ(I, J);
+ EXPECT_EQ(CI, CJ);
+}
+
+TYPED_TEST(DenseSetTest, EmptyInitializerList) {
+ TypeParam set({});
+ EXPECT_EQ(0u, set.size());
+ EXPECT_EQ(0u, set.count(0));
+}
+
+TYPED_TEST(DenseSetTest, FindAsTest) {
+ auto &set = this->Set;
+ // Size tests
+ EXPECT_EQ(3u, set.size());
+
+ // Normal lookup tests
+ EXPECT_EQ(1u, set.count(1));
+ EXPECT_EQ(0u, *set.find(0));
+ EXPECT_EQ(1u, *set.find(1));
+ EXPECT_EQ(2u, *set.find(2));
+ EXPECT_TRUE(set.find(3) == set.end());
+
+ // find_as() tests
+ EXPECT_EQ(0u, *set.find_as("a"));
+ EXPECT_EQ(1u, *set.find_as("b"));
+ EXPECT_EQ(2u, *set.find_as("c"));
+ EXPECT_TRUE(set.find_as("d") == set.end());
+}
+
+TYPED_TEST(DenseSetTest, EqualityComparisonTest) {
+ TypeParam set1({1, 2, 3, 4});
+ TypeParam set2({4, 3, 2, 1});
+ TypeParam set3({2, 3, 4, 5});
+
+ EXPECT_EQ(set1, set2);
+ EXPECT_NE(set1, set3);
+}
+
+// Simple class that counts how many moves and copy happens when growing a map
+struct CountCopyAndMove {
+ static int Move;
+ static int Copy;
+ int Value;
+ CountCopyAndMove(int Value) : Value(Value) {}
+
+ CountCopyAndMove(const CountCopyAndMove &RHS) {
+ Value = RHS.Value;
+ Copy++;
+ }
+ CountCopyAndMove &operator=(const CountCopyAndMove &RHS) {
+ Value = RHS.Value;
+ Copy++;
+ return *this;
+ }
+ CountCopyAndMove(CountCopyAndMove &&RHS) {
+ Value = RHS.Value;
+ Move++;
+ }
+ CountCopyAndMove &operator=(const CountCopyAndMove &&RHS) {
+ Value = RHS.Value;
+ Move++;
+ return *this;
+ }
+};
+int CountCopyAndMove::Copy = 0;
+int CountCopyAndMove::Move = 0;
+} // anonymous namespace
+
+namespace llvm {
+// Specialization required to insert a CountCopyAndMove into a DenseSet.
+template <> struct DenseMapInfo<CountCopyAndMove> {
+ static inline CountCopyAndMove getEmptyKey() { return CountCopyAndMove(-1); };
+ static inline CountCopyAndMove getTombstoneKey() {
+ return CountCopyAndMove(-2);
+ };
+ static unsigned getHashValue(const CountCopyAndMove &Val) {
+ return Val.Value;
+ }
+ static bool isEqual(const CountCopyAndMove &LHS,
+ const CountCopyAndMove &RHS) {
+ return LHS.Value == RHS.Value;
+ }
+};
+}
+
+namespace {
+// Make sure reserve actually gives us enough buckets to insert N items
+// without increasing allocation size.
+TEST(DenseSetCustomTest, ReserveTest) {
+ // Test a few different size, 48 is *not* a random choice: we need a value
+ // that is 2/3 of a power of two to stress the grow() condition, and the power
+ // of two has to be at least 64 because of minimum size allocation in the
+ // DenseMa. 66 is a value just above the 64 default init.
+ for (auto Size : {1, 2, 48, 66}) {
+ DenseSet<CountCopyAndMove> Set;
+ Set.reserve(Size);
+ unsigned MemorySize = Set.getMemorySize();
+ CountCopyAndMove::Copy = 0;
+ CountCopyAndMove::Move = 0;
+ for (int i = 0; i < Size; ++i)
+ Set.insert(CountCopyAndMove(i));
+ // Check that we didn't grow
+ EXPECT_EQ(MemorySize, Set.getMemorySize());
+ // Check that move was called the expected number of times
+ EXPECT_EQ(Size, CountCopyAndMove::Move);
+ // Check that no copy occurred
+ EXPECT_EQ(0, CountCopyAndMove::Copy);
+ }
+}
+TEST(DenseSetCustomTest, ConstTest) {
+ // Test that const pointers work okay for count and find, even when the
+ // underlying map is a non-const pointer.
+ DenseSet<int *> Map;
+ int A;
+ int *B = &A;
+ const int *C = &A;
+ Map.insert(B);
+ EXPECT_EQ(Map.count(B), 1u);
+ EXPECT_EQ(Map.count(C), 1u);
+ EXPECT_NE(Map.find(B), Map.end());
+ EXPECT_NE(Map.find(C), Map.end());
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/DepthFirstIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/DepthFirstIteratorTest.cpp
new file mode 100644
index 0000000..4169cd4
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/DepthFirstIteratorTest.cpp
@@ -0,0 +1,54 @@
+//=== llvm/unittest/ADT/DepthFirstIteratorTest.cpp - DFS iterator tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DepthFirstIterator.h"
+#include "TestGraph.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+template <typename T> struct CountedSet {
+ typedef typename SmallPtrSet<T, 4>::iterator iterator;
+
+ SmallPtrSet<T, 4> S;
+ int InsertVisited = 0;
+
+ std::pair<iterator, bool> insert(const T &Item) {
+ InsertVisited++;
+ return S.insert(Item);
+ }
+
+ size_t count(const T &Item) const { return S.count(Item); }
+
+ void completed(T) { }
+};
+
+template <typename T> class df_iterator_storage<CountedSet<T>, true> {
+public:
+ df_iterator_storage(CountedSet<T> &VSet) : Visited(VSet) {}
+
+ CountedSet<T> &Visited;
+};
+
+TEST(DepthFirstIteratorTest, ActuallyUpdateIterator) {
+ typedef CountedSet<Graph<3>::NodeType *> StorageT;
+ typedef df_iterator<Graph<3>, StorageT, true> DFIter;
+
+ Graph<3> G;
+ G.AddEdge(0, 1);
+ G.AddEdge(0, 2);
+ StorageT S;
+ for (auto N : make_range(DFIter::begin(G, S), DFIter::end(G, S)))
+ (void)N;
+
+ EXPECT_EQ(3, S.InsertVisited);
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/EquivalenceClassesTest.cpp b/src/llvm-project/llvm/unittests/ADT/EquivalenceClassesTest.cpp
new file mode 100644
index 0000000..57d588a
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/EquivalenceClassesTest.cpp
@@ -0,0 +1,85 @@
+//=== llvm/unittest/ADT/EquivalenceClassesTest.cpp - the structure tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/EquivalenceClasses.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+
+TEST(EquivalenceClassesTest, NoMerges) {
+ EquivalenceClasses<int> EqClasses;
+ // Until we merged any sets, check that every element is only equivalent to
+ // itself.
+ for (int i = 0; i < 3; i++)
+ for (int j = 0; j < 3; j++)
+ if (i == j)
+ EXPECT_TRUE(EqClasses.isEquivalent(i, j));
+ else
+ EXPECT_FALSE(EqClasses.isEquivalent(i, j));
+}
+
+TEST(EquivalenceClassesTest, SimpleMerge1) {
+ EquivalenceClasses<int> EqClasses;
+ // Check that once we merge (A, B), (B, C), (C, D), then all elements belong
+ // to one set.
+ EqClasses.unionSets(0, 1);
+ EqClasses.unionSets(1, 2);
+ EqClasses.unionSets(2, 3);
+ for (int i = 0; i < 4; ++i)
+ for (int j = 0; j < 4; ++j)
+ EXPECT_TRUE(EqClasses.isEquivalent(i, j));
+}
+
+TEST(EquivalenceClassesTest, SimpleMerge2) {
+ EquivalenceClasses<int> EqClasses;
+ // Check that once we merge (A, B), (C, D), (A, C), then all elements belong
+ // to one set.
+ EqClasses.unionSets(0, 1);
+ EqClasses.unionSets(2, 3);
+ EqClasses.unionSets(0, 2);
+ for (int i = 0; i < 4; ++i)
+ for (int j = 0; j < 4; ++j)
+ EXPECT_TRUE(EqClasses.isEquivalent(i, j));
+}
+
+TEST(EquivalenceClassesTest, TwoSets) {
+ EquivalenceClasses<int> EqClasses;
+ // Form sets of odd and even numbers, check that we split them into these
+ // two sets correcrly.
+ for (int i = 0; i < 30; i += 2)
+ EqClasses.unionSets(0, i);
+ for (int i = 1; i < 30; i += 2)
+ EqClasses.unionSets(1, i);
+
+ for (int i = 0; i < 30; i++)
+ for (int j = 0; j < 30; j++)
+ if (i % 2 == j % 2)
+ EXPECT_TRUE(EqClasses.isEquivalent(i, j));
+ else
+ EXPECT_FALSE(EqClasses.isEquivalent(i, j));
+}
+
+TEST(EquivalenceClassesTest, MultipleSets) {
+ EquivalenceClasses<int> EqClasses;
+ // Split numbers from [0, 100) into sets so that values in the same set have
+ // equal remainders (mod 17).
+ for (int i = 0; i < 100; i++)
+ EqClasses.unionSets(i % 17, i);
+
+ for (int i = 0; i < 100; i++)
+ for (int j = 0; j < 100; j++)
+ if (i % 17 == j % 17)
+ EXPECT_TRUE(EqClasses.isEquivalent(i, j));
+ else
+ EXPECT_FALSE(EqClasses.isEquivalent(i, j));
+}
+
+} // llvm
diff --git a/src/llvm-project/llvm/unittests/ADT/FoldingSet.cpp b/src/llvm-project/llvm/unittests/ADT/FoldingSet.cpp
new file mode 100644
index 0000000..f5b1b71
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/FoldingSet.cpp
@@ -0,0 +1,193 @@
+//===- llvm/unittest/ADT/FoldingSetTest.cpp -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// FoldingSet unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FoldingSet.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+// Unaligned string test.
+TEST(FoldingSetTest, UnalignedStringTest) {
+ SCOPED_TRACE("UnalignedStringTest");
+
+ FoldingSetNodeID a, b;
+ // An aligned string.
+ std::string str1= "a test string";
+ a.AddString(str1);
+
+ // An unaligned string.
+ std::string str2 = ">" + str1;
+ b.AddString(str2.c_str() + 1);
+
+ EXPECT_EQ(a.ComputeHash(), b.ComputeHash());
+}
+
+TEST(FoldingSetTest, LongLongComparison) {
+ struct LongLongContainer : FoldingSetNode {
+ unsigned long long A, B;
+ LongLongContainer(unsigned long long A, unsigned long long B)
+ : A(A), B(B) {}
+ void Profile(FoldingSetNodeID &ID) const {
+ ID.AddInteger(A);
+ ID.AddInteger(B);
+ }
+ };
+
+ LongLongContainer C1((1ULL << 32) + 1, 1ULL);
+ LongLongContainer C2(1ULL, (1ULL << 32) + 1);
+
+ FoldingSet<LongLongContainer> Set;
+
+ EXPECT_EQ(&C1, Set.GetOrInsertNode(&C1));
+ EXPECT_EQ(&C2, Set.GetOrInsertNode(&C2));
+ EXPECT_EQ(2U, Set.size());
+}
+
+struct TrivialPair : public FoldingSetNode {
+ unsigned Key = 0;
+ unsigned Value = 0;
+ TrivialPair(unsigned K, unsigned V) : FoldingSetNode(), Key(K), Value(V) {}
+
+ void Profile(FoldingSetNodeID &ID) const {
+ ID.AddInteger(Key);
+ ID.AddInteger(Value);
+ }
+};
+
+TEST(FoldingSetTest, IDComparison) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T);
+
+ void *InsertPos = nullptr;
+ FoldingSetNodeID ID;
+ T.Profile(ID);
+ TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
+ EXPECT_EQ(&T, N);
+ EXPECT_EQ(nullptr, InsertPos);
+}
+
+TEST(FoldingSetTest, MissedIDComparison) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair S(100, 42);
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T);
+
+ void *InsertPos = nullptr;
+ FoldingSetNodeID ID;
+ S.Profile(ID);
+ TrivialPair *N = Trivial.FindNodeOrInsertPos(ID, InsertPos);
+ EXPECT_EQ(nullptr, N);
+ EXPECT_NE(nullptr, InsertPos);
+}
+
+TEST(FoldingSetTest, RemoveNodeThatIsPresent) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T);
+ EXPECT_EQ(Trivial.size(), 1U);
+
+ bool WasThere = Trivial.RemoveNode(&T);
+ EXPECT_TRUE(WasThere);
+ EXPECT_EQ(0U, Trivial.size());
+}
+
+TEST(FoldingSetTest, RemoveNodeThatIsAbsent) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair T(99, 42);
+ bool WasThere = Trivial.RemoveNode(&T);
+ EXPECT_FALSE(WasThere);
+ EXPECT_EQ(0U, Trivial.size());
+}
+
+TEST(FoldingSetTest, GetOrInsertInserting) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair T(99, 42);
+ TrivialPair *N = Trivial.GetOrInsertNode(&T);
+ EXPECT_EQ(&T, N);
+}
+
+TEST(FoldingSetTest, GetOrInsertGetting) {
+ FoldingSet<TrivialPair> Trivial;
+
+ TrivialPair T(99, 42);
+ TrivialPair T2(99, 42);
+ Trivial.InsertNode(&T);
+ TrivialPair *N = Trivial.GetOrInsertNode(&T2);
+ EXPECT_EQ(&T, N);
+}
+
+TEST(FoldingSetTest, InsertAtPos) {
+ FoldingSet<TrivialPair> Trivial;
+
+ void *InsertPos = nullptr;
+ TrivialPair Finder(99, 42);
+ FoldingSetNodeID ID;
+ Finder.Profile(ID);
+ Trivial.FindNodeOrInsertPos(ID, InsertPos);
+
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T, InsertPos);
+ EXPECT_EQ(1U, Trivial.size());
+}
+
+TEST(FoldingSetTest, EmptyIsTrue) {
+ FoldingSet<TrivialPair> Trivial;
+ EXPECT_TRUE(Trivial.empty());
+}
+
+TEST(FoldingSetTest, EmptyIsFalse) {
+ FoldingSet<TrivialPair> Trivial;
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T);
+ EXPECT_FALSE(Trivial.empty());
+}
+
+TEST(FoldingSetTest, ClearOnEmpty) {
+ FoldingSet<TrivialPair> Trivial;
+ Trivial.clear();
+ EXPECT_TRUE(Trivial.empty());
+}
+
+TEST(FoldingSetTest, ClearOnNonEmpty) {
+ FoldingSet<TrivialPair> Trivial;
+ TrivialPair T(99, 42);
+ Trivial.InsertNode(&T);
+ Trivial.clear();
+ EXPECT_TRUE(Trivial.empty());
+}
+
+TEST(FoldingSetTest, CapacityLargerThanReserve) {
+ FoldingSet<TrivialPair> Trivial;
+ auto OldCapacity = Trivial.capacity();
+ Trivial.reserve(OldCapacity + 1);
+ EXPECT_GE(Trivial.capacity(), OldCapacity + 1);
+}
+
+TEST(FoldingSetTest, SmallReserveChangesNothing) {
+ FoldingSet<TrivialPair> Trivial;
+ auto OldCapacity = Trivial.capacity();
+ Trivial.reserve(OldCapacity - 1);
+ EXPECT_EQ(Trivial.capacity(), OldCapacity);
+}
+
+}
+
diff --git a/src/llvm-project/llvm/unittests/ADT/FunctionExtrasTest.cpp b/src/llvm-project/llvm/unittests/ADT/FunctionExtrasTest.cpp
new file mode 100644
index 0000000..d85962e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/FunctionExtrasTest.cpp
@@ -0,0 +1,228 @@
+//===- FunctionExtrasTest.cpp - Unit tests for function type erasure ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "gtest/gtest.h"
+
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+TEST(UniqueFunctionTest, Basic) {
+ unique_function<int(int, int)> Sum = [](int A, int B) { return A + B; };
+ EXPECT_EQ(Sum(1, 2), 3);
+
+ unique_function<int(int, int)> Sum2 = std::move(Sum);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ unique_function<int(int, int)> Sum3 = [](int A, int B) { return A + B; };
+ Sum2 = std::move(Sum3);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ Sum2 = unique_function<int(int, int)>([](int A, int B) { return A + B; });
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ // Explicit self-move test.
+ *&Sum2 = std::move(Sum2);
+ EXPECT_EQ(Sum2(1, 2), 3);
+
+ Sum2 = unique_function<int(int, int)>();
+ EXPECT_FALSE(Sum2);
+
+ // Make sure we can forward through l-value reference parameters.
+ unique_function<void(int &)> Inc = [](int &X) { ++X; };
+ int X = 42;
+ Inc(X);
+ EXPECT_EQ(X, 43);
+
+ // Make sure we can forward through r-value reference parameters with
+ // move-only types.
+ unique_function<int(std::unique_ptr<int> &&)> ReadAndDeallocByRef =
+ [](std::unique_ptr<int> &&Ptr) {
+ int V = *Ptr;
+ Ptr.reset();
+ return V;
+ };
+ std::unique_ptr<int> Ptr{new int(13)};
+ EXPECT_EQ(ReadAndDeallocByRef(std::move(Ptr)), 13);
+ EXPECT_FALSE((bool)Ptr);
+
+ // Make sure we can pass a move-only temporary as opposed to a local variable.
+ EXPECT_EQ(ReadAndDeallocByRef(std::unique_ptr<int>(new int(42))), 42);
+
+ // Make sure we can pass a move-only type by-value.
+ unique_function<int(std::unique_ptr<int>)> ReadAndDeallocByVal =
+ [](std::unique_ptr<int> Ptr) {
+ int V = *Ptr;
+ Ptr.reset();
+ return V;
+ };
+ Ptr.reset(new int(13));
+ EXPECT_EQ(ReadAndDeallocByVal(std::move(Ptr)), 13);
+ EXPECT_FALSE((bool)Ptr);
+
+ EXPECT_EQ(ReadAndDeallocByVal(std::unique_ptr<int>(new int(42))), 42);
+}
+
+TEST(UniqueFunctionTest, Captures) {
+ long A = 1, B = 2, C = 3, D = 4, E = 5;
+
+ unique_function<long()> Tmp;
+
+ unique_function<long()> C1 = [A]() { return A; };
+ EXPECT_EQ(C1(), 1);
+ Tmp = std::move(C1);
+ EXPECT_EQ(Tmp(), 1);
+
+ unique_function<long()> C2 = [A, B]() { return A + B; };
+ EXPECT_EQ(C2(), 3);
+ Tmp = std::move(C2);
+ EXPECT_EQ(Tmp(), 3);
+
+ unique_function<long()> C3 = [A, B, C]() { return A + B + C; };
+ EXPECT_EQ(C3(), 6);
+ Tmp = std::move(C3);
+ EXPECT_EQ(Tmp(), 6);
+
+ unique_function<long()> C4 = [A, B, C, D]() { return A + B + C + D; };
+ EXPECT_EQ(C4(), 10);
+ Tmp = std::move(C4);
+ EXPECT_EQ(Tmp(), 10);
+
+ unique_function<long()> C5 = [A, B, C, D, E]() { return A + B + C + D + E; };
+ EXPECT_EQ(C5(), 15);
+ Tmp = std::move(C5);
+ EXPECT_EQ(Tmp(), 15);
+}
+
+TEST(UniqueFunctionTest, MoveOnly) {
+ struct SmallCallable {
+ std::unique_ptr<int> A{new int(1)};
+
+ int operator()(int B) { return *A + B; }
+ };
+ unique_function<int(int)> Small = SmallCallable();
+ EXPECT_EQ(Small(2), 3);
+ unique_function<int(int)> Small2 = std::move(Small);
+ EXPECT_EQ(Small2(2), 3);
+
+ struct LargeCallable {
+ std::unique_ptr<int> A{new int(1)};
+ std::unique_ptr<int> B{new int(2)};
+ std::unique_ptr<int> C{new int(3)};
+ std::unique_ptr<int> D{new int(4)};
+ std::unique_ptr<int> E{new int(5)};
+
+ int operator()() { return *A + *B + *C + *D + *E; }
+ };
+ unique_function<int()> Large = LargeCallable();
+ EXPECT_EQ(Large(), 15);
+ unique_function<int()> Large2 = std::move(Large);
+ EXPECT_EQ(Large2(), 15);
+}
+
+TEST(UniqueFunctionTest, CountForwardingCopies) {
+ struct CopyCounter {
+ int &CopyCount;
+
+ CopyCounter(int &CopyCount) : CopyCount(CopyCount) {}
+ CopyCounter(const CopyCounter &Arg) : CopyCount(Arg.CopyCount) {
+ ++CopyCount;
+ }
+ };
+
+ unique_function<void(CopyCounter)> ByValF = [](CopyCounter) {};
+ int CopyCount = 0;
+ ByValF(CopyCounter(CopyCount));
+ EXPECT_EQ(1, CopyCount);
+
+ CopyCount = 0;
+ {
+ CopyCounter Counter{CopyCount};
+ ByValF(Counter);
+ }
+ EXPECT_EQ(2, CopyCount);
+
+ // Check that we don't generate a copy at all when we can bind a reference all
+ // the way down, even if that reference could *in theory* allow copies.
+ unique_function<void(const CopyCounter &)> ByRefF = [](const CopyCounter &) {
+ };
+ CopyCount = 0;
+ ByRefF(CopyCounter(CopyCount));
+ EXPECT_EQ(0, CopyCount);
+
+ CopyCount = 0;
+ {
+ CopyCounter Counter{CopyCount};
+ ByRefF(Counter);
+ }
+ EXPECT_EQ(0, CopyCount);
+
+ // If we use a reference, we can make a stronger guarantee that *no* copy
+ // occurs.
+ struct Uncopyable {
+ Uncopyable() = default;
+ Uncopyable(const Uncopyable &) = delete;
+ };
+ unique_function<void(const Uncopyable &)> UncopyableF =
+ [](const Uncopyable &) {};
+ UncopyableF(Uncopyable());
+ Uncopyable X;
+ UncopyableF(X);
+}
+
+TEST(UniqueFunctionTest, CountForwardingMoves) {
+ struct MoveCounter {
+ int &MoveCount;
+
+ MoveCounter(int &MoveCount) : MoveCount(MoveCount) {}
+ MoveCounter(MoveCounter &&Arg) : MoveCount(Arg.MoveCount) { ++MoveCount; }
+ };
+
+ unique_function<void(MoveCounter)> ByValF = [](MoveCounter) {};
+ int MoveCount = 0;
+ ByValF(MoveCounter(MoveCount));
+ EXPECT_EQ(1, MoveCount);
+
+ MoveCount = 0;
+ {
+ MoveCounter Counter{MoveCount};
+ ByValF(std::move(Counter));
+ }
+ EXPECT_EQ(2, MoveCount);
+
+ // Check that when we use an r-value reference we get no spurious copies.
+ unique_function<void(MoveCounter &&)> ByRefF = [](MoveCounter &&) {};
+ MoveCount = 0;
+ ByRefF(MoveCounter(MoveCount));
+ EXPECT_EQ(0, MoveCount);
+
+ MoveCount = 0;
+ {
+ MoveCounter Counter{MoveCount};
+ ByRefF(std::move(Counter));
+ }
+ EXPECT_EQ(0, MoveCount);
+
+ // If we use an r-value reference we can in fact make a stronger guarantee
+ // with an unmovable type.
+ struct Unmovable {
+ Unmovable() = default;
+ Unmovable(Unmovable &&) = delete;
+ };
+ unique_function<void(const Unmovable &)> UnmovableF = [](const Unmovable &) {
+ };
+ UnmovableF(Unmovable());
+ Unmovable X;
+ UnmovableF(X);
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/FunctionRefTest.cpp b/src/llvm-project/llvm/unittests/ADT/FunctionRefTest.cpp
new file mode 100644
index 0000000..b7ef7d7
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/FunctionRefTest.cpp
@@ -0,0 +1,42 @@
+//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique unit tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// Ensure that there is a default constructor and we can test for a null
+// function_ref.
+TEST(FunctionRefTest, Null) {
+ function_ref<int()> F;
+ EXPECT_FALSE(F);
+
+ auto L = [] { return 1; };
+ F = L;
+ EXPECT_TRUE(F);
+
+ F = {};
+ EXPECT_FALSE(F);
+}
+
+// Ensure that copies of a function_ref copy the underlying state rather than
+// causing one function_ref to chain to the next.
+TEST(FunctionRefTest, Copy) {
+ auto A = [] { return 1; };
+ auto B = [] { return 2; };
+ function_ref<int()> X = A;
+ function_ref<int()> Y = X;
+ X = B;
+ EXPECT_EQ(1, Y());
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/HashingTest.cpp b/src/llvm-project/llvm/unittests/ADT/HashingTest.cpp
new file mode 100644
index 0000000..d96dd7e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/HashingTest.cpp
@@ -0,0 +1,395 @@
+//===- llvm/unittest/ADT/HashingTest.cpp ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Hashing.h unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+#include <deque>
+#include <list>
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+// Helper for test code to print hash codes.
+void PrintTo(const hash_code &code, std::ostream *os) {
+ *os << static_cast<size_t>(code);
+}
+
+// Fake an object that is recognized as hashable data to test super large
+// objects.
+struct LargeTestInteger { uint64_t arr[8]; };
+
+struct NonPOD {
+ uint64_t x, y;
+ NonPOD(uint64_t x, uint64_t y) : x(x), y(y) {}
+ friend hash_code hash_value(const NonPOD &obj) {
+ return hash_combine(obj.x, obj.y);
+ }
+};
+
+namespace hashing {
+namespace detail {
+template <> struct is_hashable_data<LargeTestInteger> : std::true_type {};
+} // namespace detail
+} // namespace hashing
+
+} // namespace llvm
+
+using namespace llvm;
+
+namespace {
+
+enum TestEnumeration {
+ TE_Foo = 42,
+ TE_Bar = 43
+};
+
+TEST(HashingTest, HashValueBasicTest) {
+ int x = 42, y = 43, c = 'x';
+ void *p = nullptr;
+ uint64_t i = 71;
+ const unsigned ci = 71;
+ volatile int vi = 71;
+ const volatile int cvi = 71;
+ uintptr_t addr = reinterpret_cast<uintptr_t>(&y);
+ EXPECT_EQ(hash_value(42), hash_value(x));
+ EXPECT_EQ(hash_value(42), hash_value(TE_Foo));
+ EXPECT_NE(hash_value(42), hash_value(y));
+ EXPECT_NE(hash_value(42), hash_value(TE_Bar));
+ EXPECT_NE(hash_value(42), hash_value(p));
+ EXPECT_EQ(hash_value(71), hash_value(i));
+ EXPECT_EQ(hash_value(71), hash_value(ci));
+ EXPECT_EQ(hash_value(71), hash_value(vi));
+ EXPECT_EQ(hash_value(71), hash_value(cvi));
+ EXPECT_EQ(hash_value(c), hash_value('x'));
+ EXPECT_EQ(hash_value('4'), hash_value('0' + 4));
+ EXPECT_EQ(hash_value(addr), hash_value(&y));
+}
+
+TEST(HashingTest, HashValueStdPair) {
+ EXPECT_EQ(hash_combine(42, 43), hash_value(std::make_pair(42, 43)));
+ EXPECT_NE(hash_combine(43, 42), hash_value(std::make_pair(42, 43)));
+ EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43ull)));
+ EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42, 43ull)));
+ EXPECT_NE(hash_combine(42, 43), hash_value(std::make_pair(42ull, 43)));
+
+ // Note that pairs are implicitly flattened to a direct sequence of data and
+ // hashed efficiently as a consequence.
+ EXPECT_EQ(hash_combine(42, 43, 44),
+ hash_value(std::make_pair(42, std::make_pair(43, 44))));
+ EXPECT_EQ(hash_value(std::make_pair(42, std::make_pair(43, 44))),
+ hash_value(std::make_pair(std::make_pair(42, 43), 44)));
+
+ // Ensure that pairs which have padding bytes *inside* them don't get treated
+ // this way.
+ EXPECT_EQ(hash_combine('0', hash_combine(1ull, '2')),
+ hash_value(std::make_pair('0', std::make_pair(1ull, '2'))));
+
+ // Ensure that non-POD pairs don't explode the traits used.
+ NonPOD obj1(1, 2), obj2(3, 4), obj3(5, 6);
+ EXPECT_EQ(hash_combine(obj1, hash_combine(obj2, obj3)),
+ hash_value(std::make_pair(obj1, std::make_pair(obj2, obj3))));
+}
+
+TEST(HashingTest, HashValueStdString) {
+ std::string s = "Hello World!";
+ EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size()), hash_value(s));
+ EXPECT_EQ(hash_combine_range(s.c_str(), s.c_str() + s.size() - 1),
+ hash_value(s.substr(0, s.size() - 1)));
+ EXPECT_EQ(hash_combine_range(s.c_str() + 1, s.c_str() + s.size() - 1),
+ hash_value(s.substr(1, s.size() - 2)));
+
+ std::wstring ws = L"Hello Wide World!";
+ EXPECT_EQ(hash_combine_range(ws.c_str(), ws.c_str() + ws.size()),
+ hash_value(ws));
+ EXPECT_EQ(hash_combine_range(ws.c_str(), ws.c_str() + ws.size() - 1),
+ hash_value(ws.substr(0, ws.size() - 1)));
+ EXPECT_EQ(hash_combine_range(ws.c_str() + 1, ws.c_str() + ws.size() - 1),
+ hash_value(ws.substr(1, ws.size() - 2)));
+}
+
+template <typename T, size_t N> T *begin(T (&arr)[N]) { return arr; }
+template <typename T, size_t N> T *end(T (&arr)[N]) { return arr + N; }
+
+// Provide a dummy, hashable type designed for easy verification: its hash is
+// the same as its value.
+struct HashableDummy { size_t value; };
+hash_code hash_value(HashableDummy dummy) { return dummy.value; }
+
+TEST(HashingTest, HashCombineRangeBasicTest) {
+ // Leave this uninitialized in the hope that valgrind will catch bad reads.
+ int dummy;
+ hash_code dummy_hash = hash_combine_range(&dummy, &dummy);
+ EXPECT_NE(hash_code(0), dummy_hash);
+
+ const int arr1[] = { 1, 2, 3 };
+ hash_code arr1_hash = hash_combine_range(begin(arr1), end(arr1));
+ EXPECT_NE(dummy_hash, arr1_hash);
+ EXPECT_EQ(arr1_hash, hash_combine_range(begin(arr1), end(arr1)));
+
+ const std::vector<int> vec(begin(arr1), end(arr1));
+ EXPECT_EQ(arr1_hash, hash_combine_range(vec.begin(), vec.end()));
+
+ const std::list<int> list(begin(arr1), end(arr1));
+ EXPECT_EQ(arr1_hash, hash_combine_range(list.begin(), list.end()));
+
+ const std::deque<int> deque(begin(arr1), end(arr1));
+ EXPECT_EQ(arr1_hash, hash_combine_range(deque.begin(), deque.end()));
+
+ const int arr2[] = { 3, 2, 1 };
+ hash_code arr2_hash = hash_combine_range(begin(arr2), end(arr2));
+ EXPECT_NE(dummy_hash, arr2_hash);
+ EXPECT_NE(arr1_hash, arr2_hash);
+
+ const int arr3[] = { 1, 1, 2, 3 };
+ hash_code arr3_hash = hash_combine_range(begin(arr3), end(arr3));
+ EXPECT_NE(dummy_hash, arr3_hash);
+ EXPECT_NE(arr1_hash, arr3_hash);
+
+ const int arr4[] = { 1, 2, 3, 3 };
+ hash_code arr4_hash = hash_combine_range(begin(arr4), end(arr4));
+ EXPECT_NE(dummy_hash, arr4_hash);
+ EXPECT_NE(arr1_hash, arr4_hash);
+
+ const size_t arr5[] = { 1, 2, 3 };
+ const HashableDummy d_arr5[] = { {1}, {2}, {3} };
+ hash_code arr5_hash = hash_combine_range(begin(arr5), end(arr5));
+ hash_code d_arr5_hash = hash_combine_range(begin(d_arr5), end(d_arr5));
+ EXPECT_EQ(arr5_hash, d_arr5_hash);
+}
+
+TEST(HashingTest, HashCombineRangeLengthDiff) {
+ // Test that as only the length varies, we compute different hash codes for
+ // sequences.
+ std::map<size_t, size_t> code_to_size;
+ std::vector<char> all_one_c(256, '\xff');
+ for (unsigned Idx = 1, Size = all_one_c.size(); Idx < Size; ++Idx) {
+ hash_code code = hash_combine_range(&all_one_c[0], &all_one_c[0] + Idx);
+ std::map<size_t, size_t>::iterator
+ I = code_to_size.insert(std::make_pair(code, Idx)).first;
+ EXPECT_EQ(Idx, I->second);
+ }
+ code_to_size.clear();
+ std::vector<char> all_zero_c(256, '\0');
+ for (unsigned Idx = 1, Size = all_zero_c.size(); Idx < Size; ++Idx) {
+ hash_code code = hash_combine_range(&all_zero_c[0], &all_zero_c[0] + Idx);
+ std::map<size_t, size_t>::iterator
+ I = code_to_size.insert(std::make_pair(code, Idx)).first;
+ EXPECT_EQ(Idx, I->second);
+ }
+ code_to_size.clear();
+ std::vector<unsigned> all_one_int(512, -1);
+ for (unsigned Idx = 1, Size = all_one_int.size(); Idx < Size; ++Idx) {
+ hash_code code = hash_combine_range(&all_one_int[0], &all_one_int[0] + Idx);
+ std::map<size_t, size_t>::iterator
+ I = code_to_size.insert(std::make_pair(code, Idx)).first;
+ EXPECT_EQ(Idx, I->second);
+ }
+ code_to_size.clear();
+ std::vector<unsigned> all_zero_int(512, 0);
+ for (unsigned Idx = 1, Size = all_zero_int.size(); Idx < Size; ++Idx) {
+ hash_code code = hash_combine_range(&all_zero_int[0], &all_zero_int[0] + Idx);
+ std::map<size_t, size_t>::iterator
+ I = code_to_size.insert(std::make_pair(code, Idx)).first;
+ EXPECT_EQ(Idx, I->second);
+ }
+}
+
+TEST(HashingTest, HashCombineRangeGoldenTest) {
+ struct { const char *s; uint64_t hash; } golden_data[] = {
+#if SIZE_MAX == UINT64_MAX || SIZE_MAX == UINT32_MAX
+ { "a", 0xaeb6f9d5517c61f8ULL },
+ { "ab", 0x7ab1edb96be496b4ULL },
+ { "abc", 0xe38e60bf19c71a3fULL },
+ { "abcde", 0xd24461a66de97f6eULL },
+ { "abcdefgh", 0x4ef872ec411dec9dULL },
+ { "abcdefghijklm", 0xe8a865539f4eadfeULL },
+ { "abcdefghijklmnopqrstu", 0x261cdf85faaf4e79ULL },
+ { "abcdefghijklmnopqrstuvwxyzabcdef", 0x43ba70e4198e3b2aULL },
+ { "abcdefghijklmnopqrstuvwxyzabcdef"
+ "abcdefghijklmnopqrstuvwxyzghijkl"
+ "abcdefghijklmnopqrstuvwxyzmnopqr"
+ "abcdefghijklmnopqrstuvwxyzstuvwx"
+ "abcdefghijklmnopqrstuvwxyzyzabcd", 0xdcd57fb2afdf72beULL },
+ { "a", 0xaeb6f9d5517c61f8ULL },
+ { "aa", 0xf2b3b69a9736a1ebULL },
+ { "aaa", 0xf752eb6f07b1cafeULL },
+ { "aaaaa", 0x812bd21e1236954cULL },
+ { "aaaaaaaa", 0xff07a2cff08ac587ULL },
+ { "aaaaaaaaaaaaa", 0x84ac949d54d704ecULL },
+ { "aaaaaaaaaaaaaaaaaaaaa", 0xcb2c8fb6be8f5648ULL },
+ { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xcc40ab7f164091b6ULL },
+ { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0xc58e174c1e78ffe9ULL },
+ { "z", 0x1ba160d7e8f8785cULL },
+ { "zz", 0x2c5c03172f1285d7ULL },
+ { "zzz", 0x9d2c4f4b507a2ac3ULL },
+ { "zzzzz", 0x0f03b9031735693aULL },
+ { "zzzzzzzz", 0xe674147c8582c08eULL },
+ { "zzzzzzzzzzzzz", 0x3162d9fa6938db83ULL },
+ { "zzzzzzzzzzzzzzzzzzzzz", 0x37b9a549e013620cULL },
+ { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x8921470aff885016ULL },
+ { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0xf60fdcd9beb08441ULL },
+ { "a", 0xaeb6f9d5517c61f8ULL },
+ { "ab", 0x7ab1edb96be496b4ULL },
+ { "aba", 0x3edb049950884d0aULL },
+ { "ababa", 0x8f2de9e73a97714bULL },
+ { "abababab", 0xee14a29ddf0ce54cULL },
+ { "ababababababa", 0x38b3ddaada2d52b4ULL },
+ { "ababababababababababa", 0xd3665364219f2b85ULL },
+ { "abababababababababababababababab", 0xa75cd6afbf1bc972ULL },
+ { "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab", 0x840192d129f7a22bULL }
+#else
+#error This test only supports 64-bit and 32-bit systems.
+#endif
+ };
+ for (unsigned i = 0; i < sizeof(golden_data)/sizeof(*golden_data); ++i) {
+ StringRef str = golden_data[i].s;
+ hash_code hash = hash_combine_range(str.begin(), str.end());
+#if 0 // Enable this to generate paste-able text for the above structure.
+ std::string member_str = "\"" + str.str() + "\",";
+ fprintf(stderr, " { %-35s 0x%016llxULL },\n",
+ member_str.c_str(), static_cast<uint64_t>(hash));
+#endif
+ EXPECT_EQ(static_cast<size_t>(golden_data[i].hash),
+ static_cast<size_t>(hash));
+ }
+}
+
+TEST(HashingTest, HashCombineBasicTest) {
+ // Hashing a sequence of homogenous types matches range hashing.
+ const int i1 = 42, i2 = 43, i3 = 123, i4 = 999, i5 = 0, i6 = 79;
+ const int arr1[] = { i1, i2, i3, i4, i5, i6 };
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 1), hash_combine(i1));
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 2), hash_combine(i1, i2));
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 3), hash_combine(i1, i2, i3));
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 4), hash_combine(i1, i2, i3, i4));
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 5),
+ hash_combine(i1, i2, i3, i4, i5));
+ EXPECT_EQ(hash_combine_range(arr1, arr1 + 6),
+ hash_combine(i1, i2, i3, i4, i5, i6));
+
+ // Hashing a sequence of heterogeneous types which *happen* to all produce the
+ // same data for hashing produces the same as a range-based hash of the
+ // fundamental values.
+ const size_t s1 = 1024, s2 = 8888, s3 = 9000000;
+ const HashableDummy d1 = { 1024 }, d2 = { 8888 }, d3 = { 9000000 };
+ const size_t arr2[] = { s1, s2, s3 };
+ EXPECT_EQ(hash_combine_range(begin(arr2), end(arr2)),
+ hash_combine(s1, s2, s3));
+ EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, s2, d3));
+ EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(s1, d2, s3));
+ EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, s2, s3));
+ EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, s3));
+ EXPECT_EQ(hash_combine(s1, s2, s3), hash_combine(d1, d2, d3));
+
+ // Permuting values causes hashes to change.
+ EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i1, i2));
+ EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i1, i2, i1));
+ EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i1, i1));
+ EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i1));
+ EXPECT_NE(hash_combine(i1, i1, i1), hash_combine(i2, i2, i2));
+ EXPECT_NE(hash_combine(i2, i1, i1), hash_combine(i1, i1, i2));
+ EXPECT_NE(hash_combine(i1, i1, i2), hash_combine(i1, i2, i1));
+ EXPECT_NE(hash_combine(i1, i2, i1), hash_combine(i2, i1, i1));
+
+ // Changing type w/o changing value causes hashes to change.
+ EXPECT_NE(hash_combine(i1, i2, i3), hash_combine((char)i1, i2, i3));
+ EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, (char)i2, i3));
+ EXPECT_NE(hash_combine(i1, i2, i3), hash_combine(i1, i2, (char)i3));
+
+ // This is array of uint64, but it should have the exact same byte pattern as
+ // an array of LargeTestIntegers.
+ const uint64_t bigarr[] = {
+ 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
+ 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
+ 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
+ 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
+ 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
+ 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
+ 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
+ 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
+ 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
+ };
+ // Hash a preposterously large integer, both aligned with the buffer and
+ // misaligned.
+ const LargeTestInteger li = { {
+ 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL,
+ 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL, 0xafafafafededededULL,
+ 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL
+ } };
+ // Rotate the storage from 'li'.
+ const LargeTestInteger l2 = { {
+ 0xacacacacbcbcbcbcULL, 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL,
+ 0xfefefefededededeULL, 0xafafafafededededULL, 0xffffeeeeddddccccULL,
+ 0xaaaacbcbffffababULL, 0xaaaaaaaaababababULL
+ } };
+ const LargeTestInteger l3 = { {
+ 0xccddeeffeeddccbbULL, 0xdeadbeafdeadbeefULL, 0xfefefefededededeULL,
+ 0xafafafafededededULL, 0xffffeeeeddddccccULL, 0xaaaacbcbffffababULL,
+ 0xaaaaaaaaababababULL, 0xacacacacbcbcbcbcULL
+ } };
+ EXPECT_EQ(hash_combine_range(begin(bigarr), end(bigarr)),
+ hash_combine(li, li, li));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 9),
+ hash_combine(bigarr[0], l2));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 10),
+ hash_combine(bigarr[0], bigarr[1], l3));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 17),
+ hash_combine(li, bigarr[0], l2));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
+ hash_combine(li, bigarr[0], bigarr[1], l3));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 18),
+ hash_combine(bigarr[0], l2, bigarr[9], l3));
+ EXPECT_EQ(hash_combine_range(bigarr, bigarr + 20),
+ hash_combine(bigarr[0], l2, bigarr[9], l3, bigarr[18], bigarr[19]));
+}
+
+TEST(HashingTest, HashCombineArgs18) {
+ // This tests that we can pass in up to 18 args.
+#define CHECK_SAME(...) \
+ EXPECT_EQ(hash_combine(__VA_ARGS__), hash_combine(__VA_ARGS__))
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8, 9);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7, 8);
+ CHECK_SAME(1, 2, 3, 4, 5, 6, 7);
+ CHECK_SAME(1, 2, 3, 4, 5, 6);
+ CHECK_SAME(1, 2, 3, 4, 5);
+ CHECK_SAME(1, 2, 3, 4);
+ CHECK_SAME(1, 2, 3);
+ CHECK_SAME(1, 2);
+ CHECK_SAME(1);
+#undef CHECK_SAME
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/IListBaseTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListBaseTest.cpp
new file mode 100644
index 0000000..3b8ede8
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListBaseTest.cpp
@@ -0,0 +1,166 @@
+//===- unittests/ADT/IListBaseTest.cpp - ilist_base unit tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist_base.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture.
+template <typename T> class IListBaseTest : public ::testing::Test {};
+
+// Test variants with the same test.
+typedef ::testing::Types<ilist_base<false>, ilist_base<true>>
+ IListBaseTestTypes;
+TYPED_TEST_CASE(IListBaseTest, IListBaseTestTypes);
+
+TYPED_TEST(IListBaseTest, insertBeforeImpl) {
+ typedef TypeParam list_base_type;
+ typedef typename list_base_type::node_base_type node_base_type;
+
+ node_base_type S, A, B;
+
+ // [S] <-> [S]
+ S.setPrev(&S);
+ S.setNext(&S);
+
+ // [S] <-> A <-> [S]
+ list_base_type::insertBeforeImpl(S, A);
+ EXPECT_EQ(&A, S.getPrev());
+ EXPECT_EQ(&S, A.getPrev());
+ EXPECT_EQ(&A, S.getNext());
+ EXPECT_EQ(&S, A.getNext());
+
+ // [S] <-> A <-> B <-> [S]
+ list_base_type::insertBeforeImpl(S, B);
+ EXPECT_EQ(&B, S.getPrev());
+ EXPECT_EQ(&A, B.getPrev());
+ EXPECT_EQ(&S, A.getPrev());
+ EXPECT_EQ(&A, S.getNext());
+ EXPECT_EQ(&B, A.getNext());
+ EXPECT_EQ(&S, B.getNext());
+}
+
+TYPED_TEST(IListBaseTest, removeImpl) {
+ typedef TypeParam list_base_type;
+ typedef typename list_base_type::node_base_type node_base_type;
+
+ node_base_type S, A, B;
+
+ // [S] <-> A <-> B <-> [S]
+ S.setPrev(&S);
+ S.setNext(&S);
+ list_base_type::insertBeforeImpl(S, A);
+ list_base_type::insertBeforeImpl(S, B);
+
+ // [S] <-> B <-> [S]
+ list_base_type::removeImpl(A);
+ EXPECT_EQ(&B, S.getPrev());
+ EXPECT_EQ(&S, B.getPrev());
+ EXPECT_EQ(&B, S.getNext());
+ EXPECT_EQ(&S, B.getNext());
+ EXPECT_EQ(nullptr, A.getPrev());
+ EXPECT_EQ(nullptr, A.getNext());
+
+ // [S] <-> [S]
+ list_base_type::removeImpl(B);
+ EXPECT_EQ(&S, S.getPrev());
+ EXPECT_EQ(&S, S.getNext());
+ EXPECT_EQ(nullptr, B.getPrev());
+ EXPECT_EQ(nullptr, B.getNext());
+}
+
+TYPED_TEST(IListBaseTest, removeRangeImpl) {
+ typedef TypeParam list_base_type;
+ typedef typename list_base_type::node_base_type node_base_type;
+
+ node_base_type S, A, B, C, D;
+
+ // [S] <-> A <-> B <-> C <-> D <-> [S]
+ S.setPrev(&S);
+ S.setNext(&S);
+ list_base_type::insertBeforeImpl(S, A);
+ list_base_type::insertBeforeImpl(S, B);
+ list_base_type::insertBeforeImpl(S, C);
+ list_base_type::insertBeforeImpl(S, D);
+
+ // [S] <-> A <-> D <-> [S]
+ list_base_type::removeRangeImpl(B, D);
+ EXPECT_EQ(&D, S.getPrev());
+ EXPECT_EQ(&A, D.getPrev());
+ EXPECT_EQ(&S, A.getPrev());
+ EXPECT_EQ(&A, S.getNext());
+ EXPECT_EQ(&D, A.getNext());
+ EXPECT_EQ(&S, D.getNext());
+ EXPECT_EQ(nullptr, B.getPrev());
+ EXPECT_EQ(nullptr, C.getNext());
+}
+
+TYPED_TEST(IListBaseTest, removeRangeImplAllButSentinel) {
+ typedef TypeParam list_base_type;
+ typedef typename list_base_type::node_base_type node_base_type;
+
+ node_base_type S, A, B;
+
+ // [S] <-> A <-> B <-> [S]
+ S.setPrev(&S);
+ S.setNext(&S);
+ list_base_type::insertBeforeImpl(S, A);
+ list_base_type::insertBeforeImpl(S, B);
+
+ // [S] <-> [S]
+ list_base_type::removeRangeImpl(A, S);
+ EXPECT_EQ(&S, S.getPrev());
+ EXPECT_EQ(&S, S.getNext());
+ EXPECT_EQ(nullptr, A.getPrev());
+ EXPECT_EQ(nullptr, B.getNext());
+}
+
+TYPED_TEST(IListBaseTest, transferBeforeImpl) {
+ typedef TypeParam list_base_type;
+ typedef typename list_base_type::node_base_type node_base_type;
+
+ node_base_type S1, S2, A, B, C, D, E;
+
+ // [S1] <-> A <-> B <-> C <-> [S1]
+ S1.setPrev(&S1);
+ S1.setNext(&S1);
+ list_base_type::insertBeforeImpl(S1, A);
+ list_base_type::insertBeforeImpl(S1, B);
+ list_base_type::insertBeforeImpl(S1, C);
+
+ // [S2] <-> D <-> E <-> [S2]
+ S2.setPrev(&S2);
+ S2.setNext(&S2);
+ list_base_type::insertBeforeImpl(S2, D);
+ list_base_type::insertBeforeImpl(S2, E);
+
+ // [S1] <-> C <-> [S1]
+ list_base_type::transferBeforeImpl(D, A, C);
+ EXPECT_EQ(&C, S1.getPrev());
+ EXPECT_EQ(&S1, C.getPrev());
+ EXPECT_EQ(&C, S1.getNext());
+ EXPECT_EQ(&S1, C.getNext());
+
+ // [S2] <-> A <-> B <-> D <-> E <-> [S2]
+ EXPECT_EQ(&E, S2.getPrev());
+ EXPECT_EQ(&D, E.getPrev());
+ EXPECT_EQ(&B, D.getPrev());
+ EXPECT_EQ(&A, B.getPrev());
+ EXPECT_EQ(&S2, A.getPrev());
+ EXPECT_EQ(&A, S2.getNext());
+ EXPECT_EQ(&B, A.getNext());
+ EXPECT_EQ(&D, B.getNext());
+ EXPECT_EQ(&E, D.getNext());
+ EXPECT_EQ(&S2, E.getNext());
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IListIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListIteratorTest.cpp
new file mode 100644
index 0000000..8b2aa62
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListIteratorTest.cpp
@@ -0,0 +1,174 @@
+//===- unittests/ADT/IListIteratorTest.cpp - ilist_iterator unit tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/simple_ilist.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+struct Node : ilist_node<Node> {};
+
+TEST(IListIteratorTest, DefaultConstructor) {
+ simple_ilist<Node>::iterator I;
+ simple_ilist<Node>::reverse_iterator RI;
+ simple_ilist<Node>::const_iterator CI;
+ simple_ilist<Node>::const_reverse_iterator CRI;
+ EXPECT_EQ(nullptr, I.getNodePtr());
+ EXPECT_EQ(nullptr, CI.getNodePtr());
+ EXPECT_EQ(nullptr, RI.getNodePtr());
+ EXPECT_EQ(nullptr, CRI.getNodePtr());
+ EXPECT_EQ(I, I);
+ EXPECT_EQ(I, CI);
+ EXPECT_EQ(CI, I);
+ EXPECT_EQ(CI, CI);
+ EXPECT_EQ(RI, RI);
+ EXPECT_EQ(RI, CRI);
+ EXPECT_EQ(CRI, RI);
+ EXPECT_EQ(CRI, CRI);
+ EXPECT_EQ(I, RI.getReverse());
+ EXPECT_EQ(RI, I.getReverse());
+}
+
+TEST(IListIteratorTest, Empty) {
+ simple_ilist<Node> L;
+
+ // Check iterators of L.
+ EXPECT_EQ(L.begin(), L.end());
+ EXPECT_EQ(L.rbegin(), L.rend());
+
+ // Reverse of end should be rend (since the sentinel sits on both sides).
+ EXPECT_EQ(L.end(), L.rend().getReverse());
+ EXPECT_EQ(L.rend(), L.end().getReverse());
+
+ // Iterators shouldn't match default constructors.
+ simple_ilist<Node>::iterator I;
+ simple_ilist<Node>::reverse_iterator RI;
+ EXPECT_NE(I, L.begin());
+ EXPECT_NE(I, L.end());
+ EXPECT_NE(RI, L.rbegin());
+ EXPECT_NE(RI, L.rend());
+}
+
+TEST(IListIteratorTest, OneNodeList) {
+ simple_ilist<Node> L;
+ Node A;
+ L.insert(L.end(), A);
+
+ // Check address of reference.
+ EXPECT_EQ(&A, &*L.begin());
+ EXPECT_EQ(&A, &*L.rbegin());
+
+ // Check that the handle matches.
+ EXPECT_EQ(L.rbegin().getNodePtr(), L.begin().getNodePtr());
+
+ // Check iteration.
+ EXPECT_EQ(L.end(), ++L.begin());
+ EXPECT_EQ(L.begin(), --L.end());
+ EXPECT_EQ(L.rend(), ++L.rbegin());
+ EXPECT_EQ(L.rbegin(), --L.rend());
+
+ // Check conversions.
+ EXPECT_EQ(L.rbegin(), L.begin().getReverse());
+ EXPECT_EQ(L.begin(), L.rbegin().getReverse());
+}
+
+TEST(IListIteratorTest, TwoNodeList) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.insert(L.end(), A);
+ L.insert(L.end(), B);
+
+ // Check order.
+ EXPECT_EQ(&A, &*L.begin());
+ EXPECT_EQ(&B, &*++L.begin());
+ EXPECT_EQ(L.end(), ++++L.begin());
+ EXPECT_EQ(&B, &*L.rbegin());
+ EXPECT_EQ(&A, &*++L.rbegin());
+ EXPECT_EQ(L.rend(), ++++L.rbegin());
+
+ // Check conversions.
+ EXPECT_EQ(++L.rbegin(), L.begin().getReverse());
+ EXPECT_EQ(L.rbegin(), (++L.begin()).getReverse());
+ EXPECT_EQ(++L.begin(), L.rbegin().getReverse());
+ EXPECT_EQ(L.begin(), (++L.rbegin()).getReverse());
+}
+
+TEST(IListIteratorTest, CheckEraseForward) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.insert(L.end(), A);
+ L.insert(L.end(), B);
+
+ // Erase nodes.
+ auto I = L.begin();
+ EXPECT_EQ(&A, &*I);
+ L.remove(*I++);
+ EXPECT_EQ(&B, &*I);
+ L.remove(*I++);
+ EXPECT_EQ(L.end(), I);
+}
+
+TEST(IListIteratorTest, CheckEraseReverse) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.insert(L.end(), A);
+ L.insert(L.end(), B);
+
+ // Erase nodes.
+ auto RI = L.rbegin();
+ EXPECT_EQ(&B, &*RI);
+ L.remove(*RI++);
+ EXPECT_EQ(&A, &*RI);
+ L.remove(*RI++);
+ EXPECT_EQ(L.rend(), RI);
+}
+
+TEST(IListIteratorTest, ReverseConstructor) {
+ simple_ilist<Node> L;
+ const simple_ilist<Node> &CL = L;
+ Node A, B;
+ L.insert(L.end(), A);
+ L.insert(L.end(), B);
+
+ // Save typing.
+ typedef simple_ilist<Node>::iterator iterator;
+ typedef simple_ilist<Node>::reverse_iterator reverse_iterator;
+ typedef simple_ilist<Node>::const_iterator const_iterator;
+ typedef simple_ilist<Node>::const_reverse_iterator const_reverse_iterator;
+
+ // Check conversion values.
+ EXPECT_EQ(L.begin(), iterator(L.rend()));
+ EXPECT_EQ(++L.begin(), iterator(++L.rbegin()));
+ EXPECT_EQ(L.end(), iterator(L.rbegin()));
+ EXPECT_EQ(L.rbegin(), reverse_iterator(L.end()));
+ EXPECT_EQ(++L.rbegin(), reverse_iterator(++L.begin()));
+ EXPECT_EQ(L.rend(), reverse_iterator(L.begin()));
+
+ // Check const iterator constructors.
+ EXPECT_EQ(CL.begin(), const_iterator(L.rend()));
+ EXPECT_EQ(CL.begin(), const_iterator(CL.rend()));
+ EXPECT_EQ(CL.rbegin(), const_reverse_iterator(L.end()));
+ EXPECT_EQ(CL.rbegin(), const_reverse_iterator(CL.end()));
+
+ // Confirm lack of implicit conversions.
+ static_assert(!std::is_convertible<iterator, reverse_iterator>::value,
+ "unexpected implicit conversion");
+ static_assert(!std::is_convertible<reverse_iterator, iterator>::value,
+ "unexpected implicit conversion");
+ static_assert(
+ !std::is_convertible<const_iterator, const_reverse_iterator>::value,
+ "unexpected implicit conversion");
+ static_assert(
+ !std::is_convertible<const_reverse_iterator, const_iterator>::value,
+ "unexpected implicit conversion");
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IListNodeBaseTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListNodeBaseTest.cpp
new file mode 100644
index 0000000..8819ab1
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListNodeBaseTest.cpp
@@ -0,0 +1,100 @@
+//===- unittests/ADT/IListNodeBaseTest.cpp - ilist_node_base unit tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist_node_base.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+typedef ilist_node_base<false> RawNode;
+typedef ilist_node_base<true> TrackingNode;
+
+TEST(IListNodeBaseTest, DefaultConstructor) {
+ RawNode A;
+ EXPECT_EQ(nullptr, A.getPrev());
+ EXPECT_EQ(nullptr, A.getNext());
+ EXPECT_FALSE(A.isKnownSentinel());
+
+ TrackingNode TA;
+ EXPECT_EQ(nullptr, TA.getPrev());
+ EXPECT_EQ(nullptr, TA.getNext());
+ EXPECT_FALSE(TA.isKnownSentinel());
+ EXPECT_FALSE(TA.isSentinel());
+}
+
+TEST(IListNodeBaseTest, setPrevAndNext) {
+ RawNode A, B, C;
+ A.setPrev(&B);
+ EXPECT_EQ(&B, A.getPrev());
+ EXPECT_EQ(nullptr, A.getNext());
+ EXPECT_EQ(nullptr, B.getPrev());
+ EXPECT_EQ(nullptr, B.getNext());
+ EXPECT_EQ(nullptr, C.getPrev());
+ EXPECT_EQ(nullptr, C.getNext());
+
+ A.setNext(&C);
+ EXPECT_EQ(&B, A.getPrev());
+ EXPECT_EQ(&C, A.getNext());
+ EXPECT_EQ(nullptr, B.getPrev());
+ EXPECT_EQ(nullptr, B.getNext());
+ EXPECT_EQ(nullptr, C.getPrev());
+ EXPECT_EQ(nullptr, C.getNext());
+
+ TrackingNode TA, TB, TC;
+ TA.setPrev(&TB);
+ EXPECT_EQ(&TB, TA.getPrev());
+ EXPECT_EQ(nullptr, TA.getNext());
+ EXPECT_EQ(nullptr, TB.getPrev());
+ EXPECT_EQ(nullptr, TB.getNext());
+ EXPECT_EQ(nullptr, TC.getPrev());
+ EXPECT_EQ(nullptr, TC.getNext());
+
+ TA.setNext(&TC);
+ EXPECT_EQ(&TB, TA.getPrev());
+ EXPECT_EQ(&TC, TA.getNext());
+ EXPECT_EQ(nullptr, TB.getPrev());
+ EXPECT_EQ(nullptr, TB.getNext());
+ EXPECT_EQ(nullptr, TC.getPrev());
+ EXPECT_EQ(nullptr, TC.getNext());
+}
+
+TEST(IListNodeBaseTest, isKnownSentinel) {
+ // Without sentinel tracking.
+ RawNode A, B;
+ EXPECT_FALSE(A.isKnownSentinel());
+ A.setPrev(&B);
+ A.setNext(&B);
+ EXPECT_EQ(&B, A.getPrev());
+ EXPECT_EQ(&B, A.getNext());
+ EXPECT_FALSE(A.isKnownSentinel());
+ A.initializeSentinel();
+ EXPECT_FALSE(A.isKnownSentinel());
+ EXPECT_EQ(&B, A.getPrev());
+ EXPECT_EQ(&B, A.getNext());
+
+ // With sentinel tracking.
+ TrackingNode TA, TB;
+ EXPECT_FALSE(TA.isKnownSentinel());
+ EXPECT_FALSE(TA.isSentinel());
+ TA.setPrev(&TB);
+ TA.setNext(&TB);
+ EXPECT_EQ(&TB, TA.getPrev());
+ EXPECT_EQ(&TB, TA.getNext());
+ EXPECT_FALSE(TA.isKnownSentinel());
+ EXPECT_FALSE(TA.isSentinel());
+ TA.initializeSentinel();
+ EXPECT_TRUE(TA.isKnownSentinel());
+ EXPECT_TRUE(TA.isSentinel());
+ EXPECT_EQ(&TB, TA.getPrev());
+ EXPECT_EQ(&TB, TA.getNext());
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IListNodeTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListNodeTest.cpp
new file mode 100644
index 0000000..51bebc2
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListNodeTest.cpp
@@ -0,0 +1,70 @@
+//===- unittests/ADT/IListNodeTest.cpp - ilist_node unit tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist_node.h"
+#include "gtest/gtest.h"
+#include <type_traits>
+
+using namespace llvm;
+using namespace llvm::ilist_detail;
+
+namespace {
+
+struct Node;
+
+struct TagA {};
+struct TagB {};
+
+TEST(IListNodeTest, Options) {
+ static_assert(
+ std::is_same<compute_node_options<Node>::type,
+ compute_node_options<Node, ilist_tag<void>>::type>::value,
+ "default tag is void");
+ static_assert(
+ !std::is_same<compute_node_options<Node, ilist_tag<TagA>>::type,
+ compute_node_options<Node, ilist_tag<void>>::type>::value,
+ "default tag is void, different from TagA");
+ static_assert(
+ !std::is_same<compute_node_options<Node, ilist_tag<TagA>>::type,
+ compute_node_options<Node, ilist_tag<TagB>>::type>::value,
+ "TagA is not TagB");
+ static_assert(
+ std::is_same<
+ compute_node_options<Node, ilist_sentinel_tracking<false>>::type,
+ compute_node_options<Node, ilist_sentinel_tracking<false>,
+ ilist_tag<void>>::type>::value,
+ "default tag is void, even with sentinel tracking off");
+ static_assert(
+ std::is_same<
+ compute_node_options<Node, ilist_sentinel_tracking<false>>::type,
+ compute_node_options<Node, ilist_tag<void>,
+ ilist_sentinel_tracking<false>>::type>::value,
+ "order shouldn't matter");
+ static_assert(
+ std::is_same<
+ compute_node_options<Node, ilist_sentinel_tracking<true>>::type,
+ compute_node_options<Node, ilist_sentinel_tracking<true>,
+ ilist_tag<void>>::type>::value,
+ "default tag is void, even with sentinel tracking on");
+ static_assert(
+ std::is_same<
+ compute_node_options<Node, ilist_sentinel_tracking<true>>::type,
+ compute_node_options<Node, ilist_tag<void>,
+ ilist_sentinel_tracking<true>>::type>::value,
+ "order shouldn't matter");
+ static_assert(
+ std::is_same<
+ compute_node_options<Node, ilist_sentinel_tracking<true>,
+ ilist_tag<TagA>>::type,
+ compute_node_options<Node, ilist_tag<TagA>,
+ ilist_sentinel_tracking<true>>::type>::value,
+ "order shouldn't matter with real tags");
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IListSentinelTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListSentinelTest.cpp
new file mode 100644
index 0000000..bd60c90
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListSentinelTest.cpp
@@ -0,0 +1,63 @@
+//===- unittests/ADT/IListSentinelTest.cpp - ilist_sentinel unit tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist_node.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <class T, class... Options> struct PickSentinel {
+ typedef ilist_sentinel<
+ typename ilist_detail::compute_node_options<T, Options...>::type>
+ type;
+};
+
+class Node : public ilist_node<Node> {};
+class TrackingNode : public ilist_node<Node, ilist_sentinel_tracking<true>> {};
+typedef PickSentinel<Node>::type Sentinel;
+typedef PickSentinel<Node, ilist_sentinel_tracking<true>>::type
+ TrackingSentinel;
+typedef PickSentinel<Node, ilist_sentinel_tracking<false>>::type
+ NoTrackingSentinel;
+
+struct LocalAccess : ilist_detail::NodeAccess {
+ using NodeAccess::getPrev;
+ using NodeAccess::getNext;
+};
+
+TEST(IListSentinelTest, DefaultConstructor) {
+ Sentinel S;
+ EXPECT_EQ(&S, LocalAccess::getPrev(S));
+ EXPECT_EQ(&S, LocalAccess::getNext(S));
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+ EXPECT_TRUE(S.isKnownSentinel());
+#else
+ EXPECT_FALSE(S.isKnownSentinel());
+#endif
+
+ TrackingSentinel TS;
+ NoTrackingSentinel NTS;
+ EXPECT_TRUE(TS.isSentinel());
+ EXPECT_TRUE(TS.isKnownSentinel());
+ EXPECT_FALSE(NTS.isKnownSentinel());
+}
+
+TEST(IListSentinelTest, NormalNodeIsNotKnownSentinel) {
+ Node N;
+ EXPECT_EQ(nullptr, LocalAccess::getPrev(N));
+ EXPECT_EQ(nullptr, LocalAccess::getNext(N));
+ EXPECT_FALSE(N.isKnownSentinel());
+
+ TrackingNode TN;
+ EXPECT_FALSE(TN.isSentinel());
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IListTest.cpp b/src/llvm-project/llvm/unittests/ADT/IListTest.cpp
new file mode 100644
index 0000000..0dee4c1
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IListTest.cpp
@@ -0,0 +1,276 @@
+//===- unittests/ADT/IListTest.cpp - ilist unit tests ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ilist_node.h"
+#include "gtest/gtest.h"
+#include <ostream>
+
+using namespace llvm;
+
+namespace {
+
+struct Node : ilist_node<Node> {
+ int Value;
+
+ Node() {}
+ Node(int Value) : Value(Value) {}
+ Node(const Node&) = default;
+ ~Node() { Value = -1; }
+};
+
+TEST(IListTest, Basic) {
+ ilist<Node> List;
+ List.push_back(new Node(1));
+ EXPECT_EQ(1, List.back().Value);
+ EXPECT_EQ(nullptr, List.getPrevNode(List.back()));
+ EXPECT_EQ(nullptr, List.getNextNode(List.back()));
+
+ List.push_back(new Node(2));
+ EXPECT_EQ(2, List.back().Value);
+ EXPECT_EQ(2, List.getNextNode(List.front())->Value);
+ EXPECT_EQ(1, List.getPrevNode(List.back())->Value);
+
+ const ilist<Node> &ConstList = List;
+ EXPECT_EQ(2, ConstList.back().Value);
+ EXPECT_EQ(2, ConstList.getNextNode(ConstList.front())->Value);
+ EXPECT_EQ(1, ConstList.getPrevNode(ConstList.back())->Value);
+}
+
+TEST(IListTest, cloneFrom) {
+ Node L1Nodes[] = {Node(0), Node(1)};
+ Node L2Nodes[] = {Node(0), Node(1)};
+ ilist<Node> L1, L2, L3;
+
+ // Build L1 from L1Nodes.
+ L1.push_back(&L1Nodes[0]);
+ L1.push_back(&L1Nodes[1]);
+
+ // Build L2 from L2Nodes, based on L1 nodes.
+ L2.cloneFrom(L1, [&](const Node &N) { return &L2Nodes[N.Value]; });
+
+ // Add a node to L3 to be deleted, and then rebuild L3 by copying L1.
+ L3.push_back(new Node(7));
+ L3.cloneFrom(L1, [](const Node &N) { return new Node(N); });
+
+ EXPECT_EQ(2u, L1.size());
+ EXPECT_EQ(&L1Nodes[0], &L1.front());
+ EXPECT_EQ(&L1Nodes[1], &L1.back());
+ EXPECT_EQ(2u, L2.size());
+ EXPECT_EQ(&L2Nodes[0], &L2.front());
+ EXPECT_EQ(&L2Nodes[1], &L2.back());
+ EXPECT_EQ(2u, L3.size());
+ EXPECT_EQ(0, L3.front().Value);
+ EXPECT_EQ(1, L3.back().Value);
+
+ // Don't free nodes on the stack.
+ L1.clearAndLeakNodesUnsafely();
+ L2.clearAndLeakNodesUnsafely();
+}
+
+TEST(IListTest, SpliceOne) {
+ ilist<Node> List;
+ List.push_back(new Node(1));
+
+ // The single-element splice operation supports noops.
+ List.splice(List.begin(), List, List.begin());
+ EXPECT_EQ(1u, List.size());
+ EXPECT_EQ(1, List.front().Value);
+ EXPECT_TRUE(std::next(List.begin()) == List.end());
+
+ // Altenative noop. Move the first element behind itself.
+ List.push_back(new Node(2));
+ List.push_back(new Node(3));
+ List.splice(std::next(List.begin()), List, List.begin());
+ EXPECT_EQ(3u, List.size());
+ EXPECT_EQ(1, List.front().Value);
+ EXPECT_EQ(2, std::next(List.begin())->Value);
+ EXPECT_EQ(3, List.back().Value);
+}
+
+TEST(IListTest, SpliceSwap) {
+ ilist<Node> L;
+ Node N0(0);
+ Node N1(1);
+ L.insert(L.end(), &N0);
+ L.insert(L.end(), &N1);
+ EXPECT_EQ(0, L.front().Value);
+ EXPECT_EQ(1, L.back().Value);
+
+ L.splice(L.begin(), L, ++L.begin());
+ EXPECT_EQ(1, L.front().Value);
+ EXPECT_EQ(0, L.back().Value);
+
+ L.clearAndLeakNodesUnsafely();
+}
+
+TEST(IListTest, SpliceSwapOtherWay) {
+ ilist<Node> L;
+ Node N0(0);
+ Node N1(1);
+ L.insert(L.end(), &N0);
+ L.insert(L.end(), &N1);
+ EXPECT_EQ(0, L.front().Value);
+ EXPECT_EQ(1, L.back().Value);
+
+ L.splice(L.end(), L, L.begin());
+ EXPECT_EQ(1, L.front().Value);
+ EXPECT_EQ(0, L.back().Value);
+
+ L.clearAndLeakNodesUnsafely();
+}
+
+TEST(IListTest, UnsafeClear) {
+ ilist<Node> List;
+
+ // Before even allocating a sentinel.
+ List.clearAndLeakNodesUnsafely();
+ EXPECT_EQ(0u, List.size());
+
+ // Empty list with sentinel.
+ ilist<Node>::iterator E = List.end();
+ List.clearAndLeakNodesUnsafely();
+ EXPECT_EQ(0u, List.size());
+ // The sentinel shouldn't change.
+ EXPECT_TRUE(E == List.end());
+
+ // List with contents.
+ List.push_back(new Node(1));
+ ASSERT_EQ(1u, List.size());
+ Node *N = &*List.begin();
+ EXPECT_EQ(1, N->Value);
+ List.clearAndLeakNodesUnsafely();
+ EXPECT_EQ(0u, List.size());
+ ASSERT_EQ(1, N->Value);
+ delete N;
+
+ // List is still functional.
+ List.push_back(new Node(5));
+ List.push_back(new Node(6));
+ ASSERT_EQ(2u, List.size());
+ EXPECT_EQ(5, List.front().Value);
+ EXPECT_EQ(6, List.back().Value);
+}
+
+struct Empty {};
+TEST(IListTest, HasObsoleteCustomizationTrait) {
+ // Negative test for HasObsoleteCustomization.
+ static_assert(!ilist_detail::HasObsoleteCustomization<Empty, Node>::value,
+ "Empty has no customizations");
+}
+
+struct GetNext {
+ Node *getNext(Node *);
+};
+TEST(IListTest, HasGetNextTrait) {
+ static_assert(ilist_detail::HasGetNext<GetNext, Node>::value,
+ "GetNext has a getNext(Node*)");
+ static_assert(ilist_detail::HasObsoleteCustomization<GetNext, Node>::value,
+ "Empty should be obsolete because of getNext()");
+
+ // Negative test for HasGetNext.
+ static_assert(!ilist_detail::HasGetNext<Empty, Node>::value,
+ "Empty does not have a getNext(Node*)");
+}
+
+struct CreateSentinel {
+ Node *createSentinel();
+};
+TEST(IListTest, HasCreateSentinelTrait) {
+ static_assert(ilist_detail::HasCreateSentinel<CreateSentinel>::value,
+ "CreateSentinel has a getNext(Node*)");
+ static_assert(
+ ilist_detail::HasObsoleteCustomization<CreateSentinel, Node>::value,
+ "Empty should be obsolete because of createSentinel()");
+
+ // Negative test for HasCreateSentinel.
+ static_assert(!ilist_detail::HasCreateSentinel<Empty>::value,
+ "Empty does not have a createSentinel()");
+}
+
+struct NodeWithCallback : ilist_node<NodeWithCallback> {
+ int Value = 0;
+ bool IsInList = false;
+ bool WasTransferred = false;
+
+ NodeWithCallback() = default;
+ NodeWithCallback(int Value) : Value(Value) {}
+ NodeWithCallback(const NodeWithCallback &) = delete;
+};
+
+} // end namespace
+
+namespace llvm {
+template <> struct ilist_callback_traits<NodeWithCallback> {
+ void addNodeToList(NodeWithCallback *N) { N->IsInList = true; }
+ void removeNodeFromList(NodeWithCallback *N) { N->IsInList = false; }
+ template <class Iterator>
+ void transferNodesFromList(ilist_callback_traits &Other, Iterator First,
+ Iterator Last) {
+ for (; First != Last; ++First) {
+ First->WasTransferred = true;
+ Other.removeNodeFromList(&*First);
+ addNodeToList(&*First);
+ }
+ }
+};
+} // end namespace llvm
+
+namespace {
+
+TEST(IListTest, addNodeToList) {
+ ilist<NodeWithCallback> L1, L2;
+ NodeWithCallback N(7);
+ ASSERT_FALSE(N.IsInList);
+ ASSERT_FALSE(N.WasTransferred);
+
+ L1.insert(L1.begin(), &N);
+ ASSERT_EQ(1u, L1.size());
+ ASSERT_EQ(&N, &L1.front());
+ ASSERT_TRUE(N.IsInList);
+ ASSERT_FALSE(N.WasTransferred);
+
+ L2.splice(L2.end(), L1);
+ ASSERT_EQ(&N, &L2.front());
+ ASSERT_TRUE(N.IsInList);
+ ASSERT_TRUE(N.WasTransferred);
+
+ L1.remove(&N);
+ ASSERT_EQ(0u, L1.size());
+ ASSERT_FALSE(N.IsInList);
+ ASSERT_TRUE(N.WasTransferred);
+}
+
+struct PrivateNode : private ilist_node<PrivateNode> {
+ friend struct llvm::ilist_detail::NodeAccess;
+
+ int Value = 0;
+
+ PrivateNode() = default;
+ PrivateNode(int Value) : Value(Value) {}
+ PrivateNode(const PrivateNode &) = delete;
+};
+
+TEST(IListTest, privateNode) {
+ // Instantiate various APIs to be sure they're callable when ilist_node is
+ // inherited privately.
+ ilist<PrivateNode> L;
+ PrivateNode N(7);
+ L.insert(L.begin(), &N);
+ ++L.begin();
+ (void)*L.begin();
+ (void)(L.begin() == L.end());
+
+ ilist<PrivateNode> L2;
+ L2.splice(L2.end(), L);
+ L2.remove(&N);
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/ImmutableListTest.cpp b/src/llvm-project/llvm/unittests/ADT/ImmutableListTest.cpp
new file mode 100644
index 0000000..280cb2e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/ImmutableListTest.cpp
@@ -0,0 +1,271 @@
+//===--------- ImmutableListTest.cpp - ImmutableList unit tests --*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. Lee LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ImmutableList.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <typename Fundamental> struct Wrapper : llvm::FoldingSetNode {
+ Fundamental F;
+
+ Wrapper(Fundamental F) : F(F) {}
+
+ operator Fundamental() const { return F; }
+
+ void Profile(FoldingSetNodeID &ID) const { ID.AddInteger(F); }
+};
+
+class ImmutableListTest : public testing::Test {};
+
+void concat(const ImmutableList<Wrapper<char>> &L, char *Buffer) {
+ int Index = 0;
+ for (ImmutableList<Wrapper<char>>::iterator It = L.begin(), End = L.end();
+ It != End; ++It) {
+ Buffer[Index++] = *It;
+ }
+ Buffer[Index] = '\0';
+}
+
+TEST_F(ImmutableListTest, EmptyIntListTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+
+ EXPECT_TRUE(f.getEmptyList() == f.getEmptyList());
+ EXPECT_TRUE(f.getEmptyList().isEqual(f.getEmptyList()));
+ EXPECT_TRUE(f.getEmptyList().isEmpty());
+
+ ImmutableList<Wrapper<int>> L = f.getEmptyList();
+ EXPECT_EQ(nullptr, L.getTail().getInternalPointer());
+ EXPECT_TRUE(L.getTail().isEmpty());
+ EXPECT_TRUE(L.begin() == L.end());
+}
+
+TEST_F(ImmutableListTest, OneElemIntListTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+ ImmutableList<Wrapper<int>> L = f.getEmptyList();
+
+ ImmutableList<Wrapper<int>> L2 = f.add(3, L);
+ EXPECT_TRUE(L.isEmpty());
+ EXPECT_FALSE(L2.isEmpty());
+ EXPECT_TRUE(L2.getTail().isEmpty());
+
+ EXPECT_FALSE(L == L2);
+ EXPECT_TRUE(L == L2.getTail());
+ EXPECT_FALSE(L.isEqual(L2));
+ EXPECT_TRUE(L.isEqual(L2.getTail()));
+ EXPECT_FALSE(L2.begin() == L2.end());
+ EXPECT_TRUE(L2.begin() != L2.end());
+
+ EXPECT_FALSE(L.contains(3));
+ EXPECT_EQ(3, L2.getHead());
+ EXPECT_TRUE(L2.contains(3));
+
+ ImmutableList<Wrapper<int>> L3 = f.add(2, L);
+ EXPECT_TRUE(L.isEmpty());
+ EXPECT_FALSE(L3.isEmpty());
+ EXPECT_FALSE(L == L3);
+ EXPECT_FALSE(L.contains(2));
+ EXPECT_TRUE(L3.contains(2));
+ EXPECT_EQ(2, L3.getHead());
+
+ EXPECT_FALSE(L2 == L3);
+ EXPECT_FALSE(L2.contains(2));
+}
+
+// We'll store references to objects of this type.
+struct Unmodifiable {
+ Unmodifiable() = default;
+
+ // We'll delete all of these special member functions to make sure no copy or
+ // move happens during insertation.
+ Unmodifiable(const Unmodifiable &) = delete;
+ Unmodifiable(const Unmodifiable &&) = delete;
+ Unmodifiable &operator=(const Unmodifiable &) = delete;
+ Unmodifiable &operator=(const Unmodifiable &&) = delete;
+
+ void doNothing() const {}
+
+ void Profile(FoldingSetNodeID &ID) const { ID.AddPointer(this); }
+};
+
+// Mostly just a check whether ImmutableList::iterator can be instantiated
+// with a reference type as a template argument.
+TEST_F(ImmutableListTest, ReferenceStoringTest) {
+ ImmutableList<const Unmodifiable &>::Factory f;
+
+ Unmodifiable N;
+ ImmutableList<const Unmodifiable &> L = f.create(N);
+ for (ImmutableList<const Unmodifiable &>::iterator It = L.begin(),
+ E = L.end();
+ It != E; ++It) {
+ It->doNothing();
+ }
+}
+
+TEST_F(ImmutableListTest, CreatingIntListTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+
+ ImmutableList<Wrapper<int>> L = f.getEmptyList();
+ ImmutableList<Wrapper<int>> L2 = f.create(3);
+
+ EXPECT_FALSE(L2.isEmpty());
+ EXPECT_TRUE(L2.getTail().isEmpty());
+ EXPECT_EQ(3, L2.getHead());
+ EXPECT_TRUE(L.isEqual(L2.getTail()));
+ EXPECT_TRUE(L2.getTail().isEqual(L));
+}
+
+TEST_F(ImmutableListTest, MultiElemIntListTest) {
+ ImmutableList<Wrapper<int>>::Factory f;
+
+ ImmutableList<Wrapper<int>> L = f.getEmptyList();
+ ImmutableList<Wrapper<int>> L2 = f.add(5, f.add(4, f.add(3, L)));
+ ImmutableList<Wrapper<int>> L3 = f.add(43, f.add(20, f.add(9, L2)));
+ ImmutableList<Wrapper<int>> L4 = f.add(9, L2);
+ ImmutableList<Wrapper<int>> L5 = f.add(9, L2);
+
+ EXPECT_TRUE(L.isEmpty());
+ EXPECT_FALSE(L2.isEmpty());
+ EXPECT_FALSE(L3.isEmpty());
+ EXPECT_FALSE(L4.isEmpty());
+
+ EXPECT_FALSE(L.contains(3));
+ EXPECT_FALSE(L.contains(9));
+
+ EXPECT_TRUE(L2.contains(3));
+ EXPECT_TRUE(L2.contains(4));
+ EXPECT_TRUE(L2.contains(5));
+ EXPECT_FALSE(L2.contains(9));
+ EXPECT_FALSE(L2.contains(0));
+
+ EXPECT_EQ(5, L2.getHead());
+ EXPECT_EQ(4, L2.getTail().getHead());
+ EXPECT_EQ(3, L2.getTail().getTail().getHead());
+
+ EXPECT_TRUE(L3.contains(43));
+ EXPECT_TRUE(L3.contains(20));
+ EXPECT_TRUE(L3.contains(9));
+ EXPECT_TRUE(L3.contains(3));
+ EXPECT_TRUE(L3.contains(4));
+ EXPECT_TRUE(L3.contains(5));
+ EXPECT_FALSE(L3.contains(0));
+
+ EXPECT_EQ(43, L3.getHead());
+ EXPECT_EQ(20, L3.getTail().getHead());
+ EXPECT_EQ(9, L3.getTail().getTail().getHead());
+
+ EXPECT_TRUE(L3.getTail().getTail().getTail() == L2);
+ EXPECT_TRUE(L2 == L3.getTail().getTail().getTail());
+ EXPECT_TRUE(L3.getTail().getTail().getTail().isEqual(L2));
+ EXPECT_TRUE(L2.isEqual(L3.getTail().getTail().getTail()));
+
+ EXPECT_TRUE(L4.contains(9));
+ EXPECT_TRUE(L4.contains(3));
+ EXPECT_TRUE(L4.contains(4));
+ EXPECT_TRUE(L4.contains(5));
+ EXPECT_FALSE(L4.contains(20));
+ EXPECT_FALSE(L4.contains(43));
+ EXPECT_TRUE(L4.isEqual(L4));
+ EXPECT_TRUE(L4.isEqual(L5));
+
+ EXPECT_TRUE(L5.isEqual(L4));
+ EXPECT_TRUE(L5.isEqual(L5));
+}
+
+template <typename Fundamental>
+struct ExplicitCtorWrapper : public Wrapper<Fundamental> {
+ explicit ExplicitCtorWrapper(Fundamental F) : Wrapper<Fundamental>(F) {}
+ ExplicitCtorWrapper(const ExplicitCtorWrapper &) = delete;
+ ExplicitCtorWrapper(ExplicitCtorWrapper &&) = default;
+ ExplicitCtorWrapper &operator=(const ExplicitCtorWrapper &) = delete;
+ ExplicitCtorWrapper &operator=(ExplicitCtorWrapper &&) = default;
+};
+
+TEST_F(ImmutableListTest, EmplaceIntListTest) {
+ ImmutableList<ExplicitCtorWrapper<int>>::Factory f;
+
+ ImmutableList<ExplicitCtorWrapper<int>> L = f.getEmptyList();
+ ImmutableList<ExplicitCtorWrapper<int>> L2 = f.emplace(L, 3);
+
+ ImmutableList<ExplicitCtorWrapper<int>> L3 =
+ f.add(ExplicitCtorWrapper<int>(2), L2);
+
+ ImmutableList<ExplicitCtorWrapper<int>> L4 =
+ f.emplace(L3, ExplicitCtorWrapper<int>(1));
+
+ ImmutableList<ExplicitCtorWrapper<int>> L5 =
+ f.add(ExplicitCtorWrapper<int>(1), L3);
+
+ EXPECT_FALSE(L2.isEmpty());
+ EXPECT_TRUE(L2.getTail().isEmpty());
+ EXPECT_EQ(3, L2.getHead());
+ EXPECT_TRUE(L.isEqual(L2.getTail()));
+ EXPECT_TRUE(L2.getTail().isEqual(L));
+
+ EXPECT_FALSE(L3.isEmpty());
+ EXPECT_FALSE(L2 == L3);
+ EXPECT_EQ(2, L3.getHead());
+ EXPECT_TRUE(L2 == L3.getTail());
+
+ EXPECT_FALSE(L4.isEmpty());
+ EXPECT_EQ(1, L4.getHead());
+ EXPECT_TRUE(L3 == L4.getTail());
+
+ EXPECT_TRUE(L4 == L5);
+ EXPECT_TRUE(L3 == L5.getTail());
+}
+
+TEST_F(ImmutableListTest, CharListOrderingTest) {
+ ImmutableList<Wrapper<char>>::Factory f;
+ ImmutableList<Wrapper<char>> L = f.getEmptyList();
+
+ ImmutableList<Wrapper<char>> L2 = f.add('i', f.add('e', f.add('a', L)));
+ ImmutableList<Wrapper<char>> L3 = f.add('u', f.add('o', L2));
+
+ char Buffer[10];
+ concat(L3, Buffer);
+
+ ASSERT_STREQ("uoiea", Buffer);
+}
+
+TEST_F(ImmutableListTest, LongListOrderingTest) {
+ ImmutableList<Wrapper<long>>::Factory f;
+ ImmutableList<Wrapper<long>> L = f.getEmptyList();
+
+ ImmutableList<Wrapper<long>> L2 = f.add(3, f.add(4, f.add(5, L)));
+ ImmutableList<Wrapper<long>> L3 = f.add(0, f.add(1, f.add(2, L2)));
+
+ int i = 0;
+ for (ImmutableList<Wrapper<long>>::iterator I = L.begin(), E = L.end();
+ I != E; ++I) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(0, i);
+
+ i = 3;
+ for (ImmutableList<Wrapper<long>>::iterator I = L2.begin(), E = L2.end();
+ I != E; ++I) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(6, i);
+
+ i = 0;
+ for (ImmutableList<Wrapper<long>>::iterator I = L3.begin(), E = L3.end();
+ I != E; ++I) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(6, i);
+}
+
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/ImmutableMapTest.cpp b/src/llvm-project/llvm/unittests/ADT/ImmutableMapTest.cpp
new file mode 100644
index 0000000..23ca168
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/ImmutableMapTest.cpp
@@ -0,0 +1,50 @@
+//===----------- ImmutableMapTest.cpp - ImmutableMap unit tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ImmutableMap.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(ImmutableMapTest, EmptyIntMapTest) {
+ ImmutableMap<int, int>::Factory f;
+
+ EXPECT_TRUE(f.getEmptyMap() == f.getEmptyMap());
+ EXPECT_FALSE(f.getEmptyMap() != f.getEmptyMap());
+ EXPECT_TRUE(f.getEmptyMap().isEmpty());
+
+ ImmutableMap<int, int> S = f.getEmptyMap();
+ EXPECT_EQ(0u, S.getHeight());
+ EXPECT_TRUE(S.begin() == S.end());
+ EXPECT_FALSE(S.begin() != S.end());
+}
+
+TEST(ImmutableMapTest, MultiElemIntMapTest) {
+ ImmutableMap<int, int>::Factory f;
+ ImmutableMap<int, int> S = f.getEmptyMap();
+
+ ImmutableMap<int, int> S2 = f.add(f.add(f.add(S, 3, 10), 4, 11), 5, 12);
+
+ EXPECT_TRUE(S.isEmpty());
+ EXPECT_FALSE(S2.isEmpty());
+
+ EXPECT_EQ(nullptr, S.lookup(3));
+ EXPECT_EQ(nullptr, S.lookup(9));
+
+ EXPECT_EQ(10, *S2.lookup(3));
+ EXPECT_EQ(11, *S2.lookup(4));
+ EXPECT_EQ(12, *S2.lookup(5));
+
+ EXPECT_EQ(5, S2.getMaxElement()->first);
+ EXPECT_EQ(3U, S2.getHeight());
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/ImmutableSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/ImmutableSetTest.cpp
new file mode 100644
index 0000000..35ac2c1
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/ImmutableSetTest.cpp
@@ -0,0 +1,204 @@
+//===----------- ImmutableSetTest.cpp - ImmutableSet unit tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ImmutableSet.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+class ImmutableSetTest : public testing::Test {
+protected:
+ // for callback tests
+ static char buffer[10];
+
+ struct MyIter {
+ int counter;
+ char *ptr;
+
+ MyIter() : counter(0), ptr(buffer) {
+ for (unsigned i=0; i<sizeof(buffer);++i) buffer[i]='\0';
+ }
+ void operator()(char c) {
+ *ptr++ = c;
+ ++counter;
+ }
+ };
+};
+char ImmutableSetTest::buffer[10];
+
+
+TEST_F(ImmutableSetTest, EmptyIntSetTest) {
+ ImmutableSet<int>::Factory f;
+
+ EXPECT_TRUE(f.getEmptySet() == f.getEmptySet());
+ EXPECT_FALSE(f.getEmptySet() != f.getEmptySet());
+ EXPECT_TRUE(f.getEmptySet().isEmpty());
+
+ ImmutableSet<int> S = f.getEmptySet();
+ EXPECT_EQ(0u, S.getHeight());
+ EXPECT_TRUE(S.begin() == S.end());
+ EXPECT_FALSE(S.begin() != S.end());
+}
+
+
+TEST_F(ImmutableSetTest, OneElemIntSetTest) {
+ ImmutableSet<int>::Factory f;
+ ImmutableSet<int> S = f.getEmptySet();
+
+ ImmutableSet<int> S2 = f.add(S, 3);
+ EXPECT_TRUE(S.isEmpty());
+ EXPECT_FALSE(S2.isEmpty());
+ EXPECT_FALSE(S == S2);
+ EXPECT_TRUE(S != S2);
+ EXPECT_FALSE(S.contains(3));
+ EXPECT_TRUE(S2.contains(3));
+ EXPECT_FALSE(S2.begin() == S2.end());
+ EXPECT_TRUE(S2.begin() != S2.end());
+
+ ImmutableSet<int> S3 = f.add(S, 2);
+ EXPECT_TRUE(S.isEmpty());
+ EXPECT_FALSE(S3.isEmpty());
+ EXPECT_FALSE(S == S3);
+ EXPECT_TRUE(S != S3);
+ EXPECT_FALSE(S.contains(2));
+ EXPECT_TRUE(S3.contains(2));
+
+ EXPECT_FALSE(S2 == S3);
+ EXPECT_TRUE(S2 != S3);
+ EXPECT_FALSE(S2.contains(2));
+ EXPECT_FALSE(S3.contains(3));
+}
+
+TEST_F(ImmutableSetTest, MultiElemIntSetTest) {
+ ImmutableSet<int>::Factory f;
+ ImmutableSet<int> S = f.getEmptySet();
+
+ ImmutableSet<int> S2 = f.add(f.add(f.add(S, 3), 4), 5);
+ ImmutableSet<int> S3 = f.add(f.add(f.add(S2, 9), 20), 43);
+ ImmutableSet<int> S4 = f.add(S2, 9);
+
+ EXPECT_TRUE(S.isEmpty());
+ EXPECT_FALSE(S2.isEmpty());
+ EXPECT_FALSE(S3.isEmpty());
+ EXPECT_FALSE(S4.isEmpty());
+
+ EXPECT_FALSE(S.contains(3));
+ EXPECT_FALSE(S.contains(9));
+
+ EXPECT_TRUE(S2.contains(3));
+ EXPECT_TRUE(S2.contains(4));
+ EXPECT_TRUE(S2.contains(5));
+ EXPECT_FALSE(S2.contains(9));
+ EXPECT_FALSE(S2.contains(0));
+
+ EXPECT_TRUE(S3.contains(43));
+ EXPECT_TRUE(S3.contains(20));
+ EXPECT_TRUE(S3.contains(9));
+ EXPECT_TRUE(S3.contains(3));
+ EXPECT_TRUE(S3.contains(4));
+ EXPECT_TRUE(S3.contains(5));
+ EXPECT_FALSE(S3.contains(0));
+
+ EXPECT_TRUE(S4.contains(9));
+ EXPECT_TRUE(S4.contains(3));
+ EXPECT_TRUE(S4.contains(4));
+ EXPECT_TRUE(S4.contains(5));
+ EXPECT_FALSE(S4.contains(20));
+ EXPECT_FALSE(S4.contains(43));
+}
+
+TEST_F(ImmutableSetTest, RemoveIntSetTest) {
+ ImmutableSet<int>::Factory f;
+ ImmutableSet<int> S = f.getEmptySet();
+
+ ImmutableSet<int> S2 = f.add(f.add(S, 4), 5);
+ ImmutableSet<int> S3 = f.add(S2, 3);
+ ImmutableSet<int> S4 = f.remove(S3, 3);
+
+ EXPECT_TRUE(S3.contains(3));
+ EXPECT_FALSE(S2.contains(3));
+ EXPECT_FALSE(S4.contains(3));
+
+ EXPECT_TRUE(S2 == S4);
+ EXPECT_TRUE(S3 != S2);
+ EXPECT_TRUE(S3 != S4);
+
+ EXPECT_TRUE(S3.contains(4));
+ EXPECT_TRUE(S3.contains(5));
+
+ EXPECT_TRUE(S4.contains(4));
+ EXPECT_TRUE(S4.contains(5));
+}
+
+TEST_F(ImmutableSetTest, CallbackCharSetTest) {
+ ImmutableSet<char>::Factory f;
+ ImmutableSet<char> S = f.getEmptySet();
+
+ ImmutableSet<char> S2 = f.add(f.add(f.add(S, 'a'), 'e'), 'i');
+ ImmutableSet<char> S3 = f.add(f.add(S2, 'o'), 'u');
+
+ S3.foreach<MyIter>();
+
+ ASSERT_STREQ("aeiou", buffer);
+}
+
+TEST_F(ImmutableSetTest, Callback2CharSetTest) {
+ ImmutableSet<char>::Factory f;
+ ImmutableSet<char> S = f.getEmptySet();
+
+ ImmutableSet<char> S2 = f.add(f.add(f.add(S, 'b'), 'c'), 'd');
+ ImmutableSet<char> S3 = f.add(f.add(f.add(S2, 'f'), 'g'), 'h');
+
+ MyIter obj;
+ S3.foreach<MyIter>(obj);
+ ASSERT_STREQ("bcdfgh", buffer);
+ ASSERT_EQ(6, obj.counter);
+
+ MyIter obj2;
+ S2.foreach<MyIter>(obj2);
+ ASSERT_STREQ("bcd", buffer);
+ ASSERT_EQ(3, obj2.counter);
+
+ MyIter obj3;
+ S.foreach<MyIter>(obj);
+ ASSERT_STREQ("", buffer);
+ ASSERT_EQ(0, obj3.counter);
+}
+
+TEST_F(ImmutableSetTest, IterLongSetTest) {
+ ImmutableSet<long>::Factory f;
+ ImmutableSet<long> S = f.getEmptySet();
+
+ ImmutableSet<long> S2 = f.add(f.add(f.add(S, 0), 1), 2);
+ ImmutableSet<long> S3 = f.add(f.add(f.add(S2, 3), 4), 5);
+
+ int i = 0;
+ for (ImmutableSet<long>::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(0, i);
+
+ i = 0;
+ for (ImmutableSet<long>::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(3, i);
+
+ i = 0;
+ for (ImmutableSet<long>::iterator I = S3.begin(), E = S3.end(); I != E; I++) {
+ ASSERT_EQ(i, *I);
+ i++;
+ }
+ ASSERT_EQ(6, i);
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/IntEqClassesTest.cpp b/src/llvm-project/llvm/unittests/ADT/IntEqClassesTest.cpp
new file mode 100644
index 0000000..fc908c1
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IntEqClassesTest.cpp
@@ -0,0 +1,107 @@
+//===---- ADT/IntEqClassesTest.cpp - IntEqClasses unit tests ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/IntEqClasses.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(IntEqClasses, Simple) {
+ IntEqClasses ec(10);
+
+ ec.join(0, 1);
+ ec.join(3, 2);
+ ec.join(4, 5);
+ ec.join(7, 6);
+
+ EXPECT_EQ(0u, ec.findLeader(0));
+ EXPECT_EQ(0u, ec.findLeader(1));
+ EXPECT_EQ(2u, ec.findLeader(2));
+ EXPECT_EQ(2u, ec.findLeader(3));
+ EXPECT_EQ(4u, ec.findLeader(4));
+ EXPECT_EQ(4u, ec.findLeader(5));
+ EXPECT_EQ(6u, ec.findLeader(6));
+ EXPECT_EQ(6u, ec.findLeader(7));
+ EXPECT_EQ(8u, ec.findLeader(8));
+ EXPECT_EQ(9u, ec.findLeader(9));
+
+ // join two non-leaders.
+ ec.join(1, 3);
+
+ EXPECT_EQ(0u, ec.findLeader(0));
+ EXPECT_EQ(0u, ec.findLeader(1));
+ EXPECT_EQ(0u, ec.findLeader(2));
+ EXPECT_EQ(0u, ec.findLeader(3));
+ EXPECT_EQ(4u, ec.findLeader(4));
+ EXPECT_EQ(4u, ec.findLeader(5));
+ EXPECT_EQ(6u, ec.findLeader(6));
+ EXPECT_EQ(6u, ec.findLeader(7));
+ EXPECT_EQ(8u, ec.findLeader(8));
+ EXPECT_EQ(9u, ec.findLeader(9));
+
+ // join two leaders.
+ ec.join(4, 8);
+
+ EXPECT_EQ(0u, ec.findLeader(0));
+ EXPECT_EQ(0u, ec.findLeader(1));
+ EXPECT_EQ(0u, ec.findLeader(2));
+ EXPECT_EQ(0u, ec.findLeader(3));
+ EXPECT_EQ(4u, ec.findLeader(4));
+ EXPECT_EQ(4u, ec.findLeader(5));
+ EXPECT_EQ(6u, ec.findLeader(6));
+ EXPECT_EQ(6u, ec.findLeader(7));
+ EXPECT_EQ(4u, ec.findLeader(8));
+ EXPECT_EQ(9u, ec.findLeader(9));
+
+ // join mixed.
+ ec.join(9, 1);
+
+ EXPECT_EQ(0u, ec.findLeader(0));
+ EXPECT_EQ(0u, ec.findLeader(1));
+ EXPECT_EQ(0u, ec.findLeader(2));
+ EXPECT_EQ(0u, ec.findLeader(3));
+ EXPECT_EQ(4u, ec.findLeader(4));
+ EXPECT_EQ(4u, ec.findLeader(5));
+ EXPECT_EQ(6u, ec.findLeader(6));
+ EXPECT_EQ(6u, ec.findLeader(7));
+ EXPECT_EQ(4u, ec.findLeader(8));
+ EXPECT_EQ(0u, ec.findLeader(9));
+
+ // compressed map.
+ ec.compress();
+ EXPECT_EQ(3u, ec.getNumClasses());
+
+ EXPECT_EQ(0u, ec[0]);
+ EXPECT_EQ(0u, ec[1]);
+ EXPECT_EQ(0u, ec[2]);
+ EXPECT_EQ(0u, ec[3]);
+ EXPECT_EQ(1u, ec[4]);
+ EXPECT_EQ(1u, ec[5]);
+ EXPECT_EQ(2u, ec[6]);
+ EXPECT_EQ(2u, ec[7]);
+ EXPECT_EQ(1u, ec[8]);
+ EXPECT_EQ(0u, ec[9]);
+
+ // uncompressed map.
+ ec.uncompress();
+ EXPECT_EQ(0u, ec.findLeader(0));
+ EXPECT_EQ(0u, ec.findLeader(1));
+ EXPECT_EQ(0u, ec.findLeader(2));
+ EXPECT_EQ(0u, ec.findLeader(3));
+ EXPECT_EQ(4u, ec.findLeader(4));
+ EXPECT_EQ(4u, ec.findLeader(5));
+ EXPECT_EQ(6u, ec.findLeader(6));
+ EXPECT_EQ(6u, ec.findLeader(7));
+ EXPECT_EQ(4u, ec.findLeader(8));
+ EXPECT_EQ(0u, ec.findLeader(9));
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IntervalMapTest.cpp b/src/llvm-project/llvm/unittests/ADT/IntervalMapTest.cpp
new file mode 100644
index 0000000..513c063
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IntervalMapTest.cpp
@@ -0,0 +1,807 @@
+//===---- ADT/IntervalMapTest.cpp - IntervalMap unit tests ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/IntervalMap.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+typedef IntervalMap<unsigned, unsigned, 4> UUMap;
+typedef IntervalMap<unsigned, unsigned, 4,
+ IntervalMapHalfOpenInfo<unsigned>> UUHalfOpenMap;
+
+// Empty map tests
+TEST(IntervalMapTest, EmptyMap) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+ EXPECT_TRUE(map.empty());
+
+ // Lookup on empty map.
+ EXPECT_EQ(0u, map.lookup(0));
+ EXPECT_EQ(7u, map.lookup(0, 7));
+ EXPECT_EQ(0u, map.lookup(~0u-1));
+ EXPECT_EQ(7u, map.lookup(~0u-1, 7));
+
+ // Iterators.
+ EXPECT_TRUE(map.begin() == map.begin());
+ EXPECT_TRUE(map.begin() == map.end());
+ EXPECT_TRUE(map.end() == map.end());
+ EXPECT_FALSE(map.begin() != map.begin());
+ EXPECT_FALSE(map.begin() != map.end());
+ EXPECT_FALSE(map.end() != map.end());
+ EXPECT_FALSE(map.begin().valid());
+ EXPECT_FALSE(map.end().valid());
+ UUMap::iterator I = map.begin();
+ EXPECT_FALSE(I.valid());
+ EXPECT_TRUE(I == map.end());
+
+ // Default constructor and cross-constness compares.
+ UUMap::const_iterator CI;
+ CI = map.begin();
+ EXPECT_TRUE(CI == I);
+ UUMap::iterator I2;
+ I2 = map.end();
+ EXPECT_TRUE(I2 == CI);
+}
+
+// Single entry map tests
+TEST(IntervalMapTest, SingleEntryMap) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+ map.insert(100, 150, 1);
+ EXPECT_FALSE(map.empty());
+
+ // Lookup around interval.
+ EXPECT_EQ(0u, map.lookup(0));
+ EXPECT_EQ(0u, map.lookup(99));
+ EXPECT_EQ(1u, map.lookup(100));
+ EXPECT_EQ(1u, map.lookup(101));
+ EXPECT_EQ(1u, map.lookup(125));
+ EXPECT_EQ(1u, map.lookup(149));
+ EXPECT_EQ(1u, map.lookup(150));
+ EXPECT_EQ(0u, map.lookup(151));
+ EXPECT_EQ(0u, map.lookup(200));
+ EXPECT_EQ(0u, map.lookup(~0u-1));
+
+ // Iterators.
+ EXPECT_TRUE(map.begin() == map.begin());
+ EXPECT_FALSE(map.begin() == map.end());
+ EXPECT_TRUE(map.end() == map.end());
+ EXPECT_TRUE(map.begin().valid());
+ EXPECT_FALSE(map.end().valid());
+
+ // Iter deref.
+ UUMap::iterator I = map.begin();
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(1u, I.value());
+
+ // Preincrement.
+ ++I;
+ EXPECT_FALSE(I.valid());
+ EXPECT_FALSE(I == map.begin());
+ EXPECT_TRUE(I == map.end());
+
+ // PreDecrement.
+ --I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(1u, I.value());
+ EXPECT_TRUE(I == map.begin());
+ EXPECT_FALSE(I == map.end());
+
+ // Change the value.
+ I.setValue(2);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Grow the bounds.
+ I.setStart(0);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(0u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ I.setStop(200);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(0u, I.start());
+ EXPECT_EQ(200u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Shrink the bounds.
+ I.setStart(150);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(150u, I.start());
+ EXPECT_EQ(200u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Shrink the interval to have a length of 1
+ I.setStop(150);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(150u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ I.setStop(160);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(150u, I.start());
+ EXPECT_EQ(160u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Shrink the interval to have a length of 1
+ I.setStart(160);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(160u, I.start());
+ EXPECT_EQ(160u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Erase last elem.
+ I.erase();
+ EXPECT_TRUE(map.empty());
+ EXPECT_EQ(0, std::distance(map.begin(), map.end()));
+}
+
+// Single entry half-open map tests
+TEST(IntervalMapTest, SingleEntryHalfOpenMap) {
+ UUHalfOpenMap::Allocator allocator;
+ UUHalfOpenMap map(allocator);
+ map.insert(100, 150, 1);
+ EXPECT_FALSE(map.empty());
+
+ UUHalfOpenMap::iterator I = map.begin();
+ ASSERT_TRUE(I.valid());
+
+ // Shrink the interval to have a length of 1
+ I.setStart(149);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(149u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(1u, I.value());
+
+ I.setStop(160);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(149u, I.start());
+ EXPECT_EQ(160u, I.stop());
+ EXPECT_EQ(1u, I.value());
+
+ // Shrink the interval to have a length of 1
+ I.setStop(150);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(149u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ EXPECT_EQ(1u, I.value());
+}
+
+// Flat coalescing tests.
+TEST(IntervalMapTest, RootCoalescing) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+ map.insert(100, 150, 1);
+
+ // Coalesce from the left.
+ map.insert(90, 99, 1);
+ EXPECT_EQ(1, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(90u, map.start());
+ EXPECT_EQ(150u, map.stop());
+
+ // Coalesce from the right.
+ map.insert(151, 200, 1);
+ EXPECT_EQ(1, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(90u, map.start());
+ EXPECT_EQ(200u, map.stop());
+
+ // Non-coalesce from the left.
+ map.insert(60, 89, 2);
+ EXPECT_EQ(2, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(60u, map.start());
+ EXPECT_EQ(200u, map.stop());
+ EXPECT_EQ(2u, map.lookup(89));
+ EXPECT_EQ(1u, map.lookup(90));
+
+ UUMap::iterator I = map.begin();
+ EXPECT_EQ(60u, I.start());
+ EXPECT_EQ(89u, I.stop());
+ EXPECT_EQ(2u, I.value());
+ ++I;
+ EXPECT_EQ(90u, I.start());
+ EXPECT_EQ(200u, I.stop());
+ EXPECT_EQ(1u, I.value());
+ ++I;
+ EXPECT_FALSE(I.valid());
+
+ // Non-coalesce from the right.
+ map.insert(201, 210, 2);
+ EXPECT_EQ(3, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(60u, map.start());
+ EXPECT_EQ(210u, map.stop());
+ EXPECT_EQ(2u, map.lookup(201));
+ EXPECT_EQ(1u, map.lookup(200));
+
+ // Erase from the left.
+ map.begin().erase();
+ EXPECT_EQ(2, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(90u, map.start());
+ EXPECT_EQ(210u, map.stop());
+
+ // Erase from the right.
+ (--map.end()).erase();
+ EXPECT_EQ(1, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(90u, map.start());
+ EXPECT_EQ(200u, map.stop());
+
+ // Add non-coalescing, then trigger coalescing with setValue.
+ map.insert(80, 89, 2);
+ map.insert(201, 210, 2);
+ EXPECT_EQ(3, std::distance(map.begin(), map.end()));
+ (++map.begin()).setValue(2);
+ EXPECT_EQ(1, std::distance(map.begin(), map.end()));
+ I = map.begin();
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(80u, I.start());
+ EXPECT_EQ(210u, I.stop());
+ EXPECT_EQ(2u, I.value());
+}
+
+// Flat multi-coalescing tests.
+TEST(IntervalMapTest, RootMultiCoalescing) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+ map.insert(140, 150, 1);
+ map.insert(160, 170, 1);
+ map.insert(100, 110, 1);
+ map.insert(120, 130, 1);
+ EXPECT_EQ(4, std::distance(map.begin(), map.end()));
+ EXPECT_EQ(100u, map.start());
+ EXPECT_EQ(170u, map.stop());
+
+ // Verify inserts.
+ UUMap::iterator I = map.begin();
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(110u, I.stop());
+ ++I;
+ EXPECT_EQ(120u, I.start());
+ EXPECT_EQ(130u, I.stop());
+ ++I;
+ EXPECT_EQ(140u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ ++I;
+ EXPECT_EQ(160u, I.start());
+ EXPECT_EQ(170u, I.stop());
+ ++I;
+ EXPECT_FALSE(I.valid());
+
+ // Test advanceTo on flat tree.
+ I = map.begin();
+ I.advanceTo(135);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(140u, I.start());
+ EXPECT_EQ(150u, I.stop());
+
+ I.advanceTo(145);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(140u, I.start());
+ EXPECT_EQ(150u, I.stop());
+
+ I.advanceTo(200);
+ EXPECT_FALSE(I.valid());
+
+ I.advanceTo(300);
+ EXPECT_FALSE(I.valid());
+
+ // Coalesce left with followers.
+ // [100;110] [120;130] [140;150] [160;170]
+ map.insert(111, 115, 1);
+ I = map.begin();
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(115u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(120u, I.start());
+ EXPECT_EQ(130u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(140u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(160u, I.start());
+ EXPECT_EQ(170u, I.stop());
+ ++I;
+ EXPECT_FALSE(I.valid());
+
+ // Coalesce right with followers.
+ // [100;115] [120;130] [140;150] [160;170]
+ map.insert(135, 139, 1);
+ I = map.begin();
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(115u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(120u, I.start());
+ EXPECT_EQ(130u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(135u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(160u, I.start());
+ EXPECT_EQ(170u, I.stop());
+ ++I;
+ EXPECT_FALSE(I.valid());
+
+ // Coalesce left and right with followers.
+ // [100;115] [120;130] [135;150] [160;170]
+ map.insert(131, 134, 1);
+ I = map.begin();
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(100u, I.start());
+ EXPECT_EQ(115u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(120u, I.start());
+ EXPECT_EQ(150u, I.stop());
+ ++I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(160u, I.start());
+ EXPECT_EQ(170u, I.stop());
+ ++I;
+ EXPECT_FALSE(I.valid());
+
+ // Test clear() on non-branched map.
+ map.clear();
+ EXPECT_TRUE(map.empty());
+ EXPECT_TRUE(map.begin() == map.end());
+}
+
+// Branched, non-coalescing tests.
+TEST(IntervalMapTest, Branched) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+
+ // Insert enough intervals to force a branched tree.
+ // This creates 9 leaf nodes with 11 elements each, tree height = 1.
+ for (unsigned i = 1; i < 100; ++i) {
+ map.insert(10*i, 10*i+5, i);
+ EXPECT_EQ(10u, map.start());
+ EXPECT_EQ(10*i+5, map.stop());
+ }
+
+ // Tree limits.
+ EXPECT_FALSE(map.empty());
+ EXPECT_EQ(10u, map.start());
+ EXPECT_EQ(995u, map.stop());
+
+ // Tree lookup.
+ for (unsigned i = 1; i < 100; ++i) {
+ EXPECT_EQ(0u, map.lookup(10*i-1));
+ EXPECT_EQ(i, map.lookup(10*i));
+ EXPECT_EQ(i, map.lookup(10*i+5));
+ EXPECT_EQ(0u, map.lookup(10*i+6));
+ }
+
+ // Forward iteration.
+ UUMap::iterator I = map.begin();
+ for (unsigned i = 1; i < 100; ++i) {
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ ++I;
+ }
+ EXPECT_FALSE(I.valid());
+ EXPECT_TRUE(I == map.end());
+
+ // Backwards iteration.
+ for (unsigned i = 99; i; --i) {
+ --I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ }
+ EXPECT_TRUE(I == map.begin());
+
+ // Test advanceTo in same node.
+ I.advanceTo(20);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(25u, I.stop());
+
+ // Change value, no coalescing.
+ I.setValue(0);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(25u, I.stop());
+ EXPECT_EQ(0u, I.value());
+
+ // Close the gap right, no coalescing.
+ I.setStop(29);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(29u, I.stop());
+ EXPECT_EQ(0u, I.value());
+
+ // Change value, no coalescing.
+ I.setValue(2);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(29u, I.stop());
+ EXPECT_EQ(2u, I.value());
+
+ // Change value, now coalescing.
+ I.setValue(3);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(35u, I.stop());
+ EXPECT_EQ(3u, I.value());
+
+ // Close the gap, now coalescing.
+ I.setValue(4);
+ ASSERT_TRUE(I.valid());
+ I.setStop(39);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(45u, I.stop());
+ EXPECT_EQ(4u, I.value());
+
+ // advanceTo another node.
+ I.advanceTo(200);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(200u, I.start());
+ EXPECT_EQ(205u, I.stop());
+
+ // Close the gap left, no coalescing.
+ I.setStart(196);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(196u, I.start());
+ EXPECT_EQ(205u, I.stop());
+ EXPECT_EQ(20u, I.value());
+
+ // Change value, no coalescing.
+ I.setValue(0);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(196u, I.start());
+ EXPECT_EQ(205u, I.stop());
+ EXPECT_EQ(0u, I.value());
+
+ // Change value, now coalescing.
+ I.setValue(19);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(190u, I.start());
+ EXPECT_EQ(205u, I.stop());
+ EXPECT_EQ(19u, I.value());
+
+ // Close the gap, now coalescing.
+ I.setValue(18);
+ ASSERT_TRUE(I.valid());
+ I.setStart(186);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(180u, I.start());
+ EXPECT_EQ(205u, I.stop());
+ EXPECT_EQ(18u, I.value());
+
+ // Erase from the front.
+ I = map.begin();
+ for (unsigned i = 0; i != 20; ++i) {
+ I.erase();
+ EXPECT_TRUE(I == map.begin());
+ EXPECT_FALSE(map.empty());
+ EXPECT_EQ(I.start(), map.start());
+ EXPECT_EQ(995u, map.stop());
+ }
+
+ // Test clear() on branched map.
+ map.clear();
+ EXPECT_TRUE(map.empty());
+ EXPECT_TRUE(map.begin() == map.end());
+}
+
+// Branched, high, non-coalescing tests.
+TEST(IntervalMapTest, Branched2) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+
+ // Insert enough intervals to force a height >= 2 tree.
+ for (unsigned i = 1; i < 1000; ++i)
+ map.insert(10*i, 10*i+5, i);
+
+ // Tree limits.
+ EXPECT_FALSE(map.empty());
+ EXPECT_EQ(10u, map.start());
+ EXPECT_EQ(9995u, map.stop());
+
+ // Tree lookup.
+ for (unsigned i = 1; i < 1000; ++i) {
+ EXPECT_EQ(0u, map.lookup(10*i-1));
+ EXPECT_EQ(i, map.lookup(10*i));
+ EXPECT_EQ(i, map.lookup(10*i+5));
+ EXPECT_EQ(0u, map.lookup(10*i+6));
+ }
+
+ // Forward iteration.
+ UUMap::iterator I = map.begin();
+ for (unsigned i = 1; i < 1000; ++i) {
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ ++I;
+ }
+ EXPECT_FALSE(I.valid());
+ EXPECT_TRUE(I == map.end());
+
+ // Backwards iteration.
+ for (unsigned i = 999; i; --i) {
+ --I;
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(10*i, I.start());
+ EXPECT_EQ(10*i+5, I.stop());
+ EXPECT_EQ(i, *I);
+ }
+ EXPECT_TRUE(I == map.begin());
+
+ // Test advanceTo in same node.
+ I.advanceTo(20);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(20u, I.start());
+ EXPECT_EQ(25u, I.stop());
+
+ // advanceTo sibling leaf node.
+ I.advanceTo(200);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(200u, I.start());
+ EXPECT_EQ(205u, I.stop());
+
+ // advanceTo further.
+ I.advanceTo(2000);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(2000u, I.start());
+ EXPECT_EQ(2005u, I.stop());
+
+ // advanceTo beyond end()
+ I.advanceTo(20000);
+ EXPECT_FALSE(I.valid());
+
+ // end().advanceTo() is valid as long as x > map.stop()
+ I.advanceTo(30000);
+ EXPECT_FALSE(I.valid());
+
+ // Test clear() on branched map.
+ map.clear();
+ EXPECT_TRUE(map.empty());
+ EXPECT_TRUE(map.begin() == map.end());
+}
+
+// Random insertions, coalescing to a single interval.
+TEST(IntervalMapTest, RandomCoalescing) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+
+ // This is a poor PRNG with maximal period:
+ // x_n = 5 x_{n-1} + 1 mod 2^N
+
+ unsigned x = 100;
+ for (unsigned i = 0; i != 4096; ++i) {
+ map.insert(10*x, 10*x+9, 1);
+ EXPECT_GE(10*x, map.start());
+ EXPECT_LE(10*x+9, map.stop());
+ x = (5*x+1)%4096;
+ }
+
+ // Map should be fully coalesced after that exercise.
+ EXPECT_FALSE(map.empty());
+ EXPECT_EQ(0u, map.start());
+ EXPECT_EQ(40959u, map.stop());
+ EXPECT_EQ(1, std::distance(map.begin(), map.end()));
+
+}
+
+TEST(IntervalMapTest, Overlaps) {
+ UUMap::Allocator allocator;
+ UUMap map(allocator);
+ map.insert(10, 20, 0);
+ map.insert(30, 40, 0);
+ map.insert(50, 60, 0);
+
+ EXPECT_FALSE(map.overlaps(0, 9));
+ EXPECT_TRUE(map.overlaps(0, 10));
+ EXPECT_TRUE(map.overlaps(0, 15));
+ EXPECT_TRUE(map.overlaps(0, 25));
+ EXPECT_TRUE(map.overlaps(0, 45));
+ EXPECT_TRUE(map.overlaps(10, 45));
+ EXPECT_TRUE(map.overlaps(30, 45));
+ EXPECT_TRUE(map.overlaps(35, 36));
+ EXPECT_TRUE(map.overlaps(40, 45));
+ EXPECT_FALSE(map.overlaps(45, 45));
+ EXPECT_TRUE(map.overlaps(60, 60));
+ EXPECT_TRUE(map.overlaps(60, 66));
+ EXPECT_FALSE(map.overlaps(66, 66));
+}
+
+TEST(IntervalMapTest, OverlapsHalfOpen) {
+ UUHalfOpenMap::Allocator allocator;
+ UUHalfOpenMap map(allocator);
+ map.insert(10, 20, 0);
+ map.insert(30, 40, 0);
+ map.insert(50, 60, 0);
+
+ EXPECT_FALSE(map.overlaps(0, 9));
+ EXPECT_FALSE(map.overlaps(0, 10));
+ EXPECT_TRUE(map.overlaps(0, 15));
+ EXPECT_TRUE(map.overlaps(0, 25));
+ EXPECT_TRUE(map.overlaps(0, 45));
+ EXPECT_TRUE(map.overlaps(10, 45));
+ EXPECT_TRUE(map.overlaps(30, 45));
+ EXPECT_TRUE(map.overlaps(35, 36));
+ EXPECT_FALSE(map.overlaps(40, 45));
+ EXPECT_FALSE(map.overlaps(45, 46));
+ EXPECT_FALSE(map.overlaps(60, 61));
+ EXPECT_FALSE(map.overlaps(60, 66));
+ EXPECT_FALSE(map.overlaps(66, 67));
+}
+
+TEST(IntervalMapOverlapsTest, SmallMaps) {
+ typedef IntervalMapOverlaps<UUMap,UUMap> UUOverlaps;
+ UUMap::Allocator allocator;
+ UUMap mapA(allocator);
+ UUMap mapB(allocator);
+
+ // empty, empty.
+ EXPECT_FALSE(UUOverlaps(mapA, mapB).valid());
+
+ mapA.insert(1, 2, 3);
+
+ // full, empty
+ EXPECT_FALSE(UUOverlaps(mapA, mapB).valid());
+ // empty, full
+ EXPECT_FALSE(UUOverlaps(mapB, mapA).valid());
+
+ mapB.insert(3, 4, 5);
+
+ // full, full, non-overlapping
+ EXPECT_FALSE(UUOverlaps(mapA, mapB).valid());
+ EXPECT_FALSE(UUOverlaps(mapB, mapA).valid());
+
+ // Add an overlapping segment.
+ mapA.insert(4, 5, 6);
+
+ UUOverlaps AB(mapA, mapB);
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(4u, AB.a().start());
+ EXPECT_EQ(3u, AB.b().start());
+ ++AB;
+ EXPECT_FALSE(AB.valid());
+
+ UUOverlaps BA(mapB, mapA);
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(3u, BA.a().start());
+ EXPECT_EQ(4u, BA.b().start());
+ // advance past end.
+ BA.advanceTo(6);
+ EXPECT_FALSE(BA.valid());
+ // advance an invalid iterator.
+ BA.advanceTo(7);
+ EXPECT_FALSE(BA.valid());
+}
+
+TEST(IntervalMapOverlapsTest, BigMaps) {
+ typedef IntervalMapOverlaps<UUMap,UUMap> UUOverlaps;
+ UUMap::Allocator allocator;
+ UUMap mapA(allocator);
+ UUMap mapB(allocator);
+
+ // [0;4] [10;14] [20;24] ...
+ for (unsigned n = 0; n != 100; ++n)
+ mapA.insert(10*n, 10*n+4, n);
+
+ // [5;6] [15;16] [25;26] ...
+ for (unsigned n = 10; n != 20; ++n)
+ mapB.insert(10*n+5, 10*n+6, n);
+
+ // [208;209] [218;219] ...
+ for (unsigned n = 20; n != 30; ++n)
+ mapB.insert(10*n+8, 10*n+9, n);
+
+ // insert some overlapping segments.
+ mapB.insert(400, 400, 400);
+ mapB.insert(401, 401, 401);
+ mapB.insert(402, 500, 402);
+ mapB.insert(600, 601, 402);
+
+ UUOverlaps AB(mapA, mapB);
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(400u, AB.a().start());
+ EXPECT_EQ(400u, AB.b().start());
+ ++AB;
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(400u, AB.a().start());
+ EXPECT_EQ(401u, AB.b().start());
+ ++AB;
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(400u, AB.a().start());
+ EXPECT_EQ(402u, AB.b().start());
+ ++AB;
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(410u, AB.a().start());
+ EXPECT_EQ(402u, AB.b().start());
+ ++AB;
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(420u, AB.a().start());
+ EXPECT_EQ(402u, AB.b().start());
+ AB.skipB();
+ ASSERT_TRUE(AB.valid());
+ EXPECT_EQ(600u, AB.a().start());
+ EXPECT_EQ(600u, AB.b().start());
+ ++AB;
+ EXPECT_FALSE(AB.valid());
+
+ // Test advanceTo.
+ UUOverlaps AB2(mapA, mapB);
+ AB2.advanceTo(410);
+ ASSERT_TRUE(AB2.valid());
+ EXPECT_EQ(410u, AB2.a().start());
+ EXPECT_EQ(402u, AB2.b().start());
+
+ // It is valid to advanceTo with any monotonic sequence.
+ AB2.advanceTo(411);
+ ASSERT_TRUE(AB2.valid());
+ EXPECT_EQ(410u, AB2.a().start());
+ EXPECT_EQ(402u, AB2.b().start());
+
+ // Check reversed maps.
+ UUOverlaps BA(mapB, mapA);
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(400u, BA.b().start());
+ EXPECT_EQ(400u, BA.a().start());
+ ++BA;
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(400u, BA.b().start());
+ EXPECT_EQ(401u, BA.a().start());
+ ++BA;
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(400u, BA.b().start());
+ EXPECT_EQ(402u, BA.a().start());
+ ++BA;
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(410u, BA.b().start());
+ EXPECT_EQ(402u, BA.a().start());
+ ++BA;
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(420u, BA.b().start());
+ EXPECT_EQ(402u, BA.a().start());
+ BA.skipA();
+ ASSERT_TRUE(BA.valid());
+ EXPECT_EQ(600u, BA.b().start());
+ EXPECT_EQ(600u, BA.a().start());
+ ++BA;
+ EXPECT_FALSE(BA.valid());
+
+ // Test advanceTo.
+ UUOverlaps BA2(mapB, mapA);
+ BA2.advanceTo(410);
+ ASSERT_TRUE(BA2.valid());
+ EXPECT_EQ(410u, BA2.b().start());
+ EXPECT_EQ(402u, BA2.a().start());
+
+ BA2.advanceTo(411);
+ ASSERT_TRUE(BA2.valid());
+ EXPECT_EQ(410u, BA2.b().start());
+ EXPECT_EQ(402u, BA2.a().start());
+}
+
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/src/llvm-project/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
new file mode 100644
index 0000000..83dc137
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
@@ -0,0 +1,67 @@
+//===- unittest/ADT/IntrusiveRefCntPtrTest.cpp ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+
+namespace {
+struct SimpleRefCounted : public RefCountedBase<SimpleRefCounted> {
+ SimpleRefCounted() { ++NumInstances; }
+ SimpleRefCounted(const SimpleRefCounted &) : RefCountedBase() {
+ ++NumInstances;
+ }
+ ~SimpleRefCounted() { --NumInstances; }
+
+ static int NumInstances;
+};
+int SimpleRefCounted::NumInstances = 0;
+} // anonymous namespace
+
+TEST(IntrusiveRefCntPtr, RefCountedBaseCopyDoesNotLeak) {
+ EXPECT_EQ(0, SimpleRefCounted::NumInstances);
+ {
+ SimpleRefCounted *S1 = new SimpleRefCounted;
+ IntrusiveRefCntPtr<SimpleRefCounted> R1 = S1;
+ SimpleRefCounted *S2 = new SimpleRefCounted(*S1);
+ IntrusiveRefCntPtr<SimpleRefCounted> R2 = S2;
+ EXPECT_EQ(2, SimpleRefCounted::NumInstances);
+ }
+ EXPECT_EQ(0, SimpleRefCounted::NumInstances);
+}
+
+struct InterceptRefCounted : public RefCountedBase<InterceptRefCounted> {
+ InterceptRefCounted(bool *Released, bool *Retained)
+ : Released(Released), Retained(Retained) {}
+ bool * const Released;
+ bool * const Retained;
+};
+template <> struct IntrusiveRefCntPtrInfo<InterceptRefCounted> {
+ static void retain(InterceptRefCounted *I) {
+ *I->Retained = true;
+ I->Retain();
+ }
+ static void release(InterceptRefCounted *I) {
+ *I->Released = true;
+ I->Release();
+ }
+};
+TEST(IntrusiveRefCntPtr, UsesTraitsToRetainAndRelease) {
+ bool Released = false;
+ bool Retained = false;
+ {
+ InterceptRefCounted *I = new InterceptRefCounted(&Released, &Retained);
+ IntrusiveRefCntPtr<InterceptRefCounted> R = I;
+ }
+ EXPECT_TRUE(Released);
+ EXPECT_TRUE(Retained);
+}
+
+} // end namespace llvm
diff --git a/src/llvm-project/llvm/unittests/ADT/IteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/IteratorTest.cpp
new file mode 100644
index 0000000..902ddfb
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/IteratorTest.cpp
@@ -0,0 +1,466 @@
+//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <int> struct Shadow;
+
+struct WeirdIter : std::iterator<std::input_iterator_tag, Shadow<0>, Shadow<1>,
+ Shadow<2>, Shadow<3>> {};
+
+struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};
+
+// Test that iterator_adaptor_base forwards typedefs, if value_type is
+// unchanged.
+static_assert(std::is_same<typename AdaptedIter::value_type, Shadow<0>>::value,
+ "");
+static_assert(
+ std::is_same<typename AdaptedIter::difference_type, Shadow<1>>::value, "");
+static_assert(std::is_same<typename AdaptedIter::pointer, Shadow<2>>::value,
+ "");
+static_assert(std::is_same<typename AdaptedIter::reference, Shadow<3>>::value,
+ "");
+
+// Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
+// the underlying iterator.
+
+using RandomAccessIter = SmallVectorImpl<int*>::iterator;
+using BidiIter = ilist<int*>::iterator;
+
+template<class T>
+using pointee_iterator_defaulted = pointee_iterator<T>;
+template<class T>
+using pointer_iterator_defaulted = pointer_iterator<T>;
+
+// Ensures that an iterator and its adaptation have the same iterator_category.
+template<template<typename> class A, typename It>
+using IsAdaptedIterCategorySame =
+ std::is_same<typename std::iterator_traits<It>::iterator_category,
+ typename std::iterator_traits<A<It>>::iterator_category>;
+
+// pointeE_iterator
+static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
+ RandomAccessIter>::value, "");
+static_assert(IsAdaptedIterCategorySame<pointee_iterator_defaulted,
+ BidiIter>::value, "");
+// pointeR_iterator
+static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
+ RandomAccessIter>::value, "");
+static_assert(IsAdaptedIterCategorySame<pointer_iterator_defaulted,
+ BidiIter>::value, "");
+
+TEST(PointeeIteratorTest, Basic) {
+ int arr[4] = {1, 2, 3, 4};
+ SmallVector<int *, 4> V;
+ V.push_back(&arr[0]);
+ V.push_back(&arr[1]);
+ V.push_back(&arr[2]);
+ V.push_back(&arr[3]);
+
+ typedef pointee_iterator<SmallVectorImpl<int *>::const_iterator>
+ test_iterator;
+
+ test_iterator Begin, End;
+ Begin = V.begin();
+ End = test_iterator(V.end());
+
+ test_iterator I = Begin;
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_EQ(*V[i], *I);
+
+ EXPECT_EQ(I, Begin + i);
+ EXPECT_EQ(I, std::next(Begin, i));
+ test_iterator J = Begin;
+ J += i;
+ EXPECT_EQ(I, J);
+ EXPECT_EQ(*V[i], Begin[i]);
+
+ EXPECT_NE(I, End);
+ EXPECT_GT(End, I);
+ EXPECT_LT(I, End);
+ EXPECT_GE(I, Begin);
+ EXPECT_LE(Begin, I);
+
+ EXPECT_EQ(i, I - Begin);
+ EXPECT_EQ(i, std::distance(Begin, I));
+ EXPECT_EQ(Begin, I - i);
+
+ test_iterator K = I++;
+ EXPECT_EQ(K, std::prev(I));
+ }
+ EXPECT_EQ(End, I);
+}
+
+TEST(PointeeIteratorTest, SmartPointer) {
+ SmallVector<std::unique_ptr<int>, 4> V;
+ V.push_back(make_unique<int>(1));
+ V.push_back(make_unique<int>(2));
+ V.push_back(make_unique<int>(3));
+ V.push_back(make_unique<int>(4));
+
+ typedef pointee_iterator<
+ SmallVectorImpl<std::unique_ptr<int>>::const_iterator>
+ test_iterator;
+
+ test_iterator Begin, End;
+ Begin = V.begin();
+ End = test_iterator(V.end());
+
+ test_iterator I = Begin;
+ for (int i = 0; i < 4; ++i) {
+ EXPECT_EQ(*V[i], *I);
+
+ EXPECT_EQ(I, Begin + i);
+ EXPECT_EQ(I, std::next(Begin, i));
+ test_iterator J = Begin;
+ J += i;
+ EXPECT_EQ(I, J);
+ EXPECT_EQ(*V[i], Begin[i]);
+
+ EXPECT_NE(I, End);
+ EXPECT_GT(End, I);
+ EXPECT_LT(I, End);
+ EXPECT_GE(I, Begin);
+ EXPECT_LE(Begin, I);
+
+ EXPECT_EQ(i, I - Begin);
+ EXPECT_EQ(i, std::distance(Begin, I));
+ EXPECT_EQ(Begin, I - i);
+
+ test_iterator K = I++;
+ EXPECT_EQ(K, std::prev(I));
+ }
+ EXPECT_EQ(End, I);
+}
+
+TEST(PointeeIteratorTest, Range) {
+ int A[] = {1, 2, 3, 4};
+ SmallVector<int *, 4> V{&A[0], &A[1], &A[2], &A[3]};
+
+ int I = 0;
+ for (int II : make_pointee_range(V))
+ EXPECT_EQ(A[I++], II);
+}
+
+TEST(PointeeIteratorTest, PointeeType) {
+ struct S {
+ int X;
+ bool operator==(const S &RHS) const { return X == RHS.X; };
+ };
+ S A[] = {S{0}, S{1}};
+ SmallVector<S *, 2> V{&A[0], &A[1]};
+
+ pointee_iterator<SmallVectorImpl<S *>::const_iterator, const S> I = V.begin();
+ for (int j = 0; j < 2; ++j, ++I) {
+ EXPECT_EQ(*V[j], *I);
+ }
+}
+
+TEST(FilterIteratorTest, Lambda) {
+ auto IsOdd = [](int N) { return N % 2 == 1; };
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+ auto Range = make_filter_range(A, IsOdd);
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, CallableObject) {
+ int Counter = 0;
+ struct Callable {
+ int &Counter;
+
+ Callable(int &Counter) : Counter(Counter) {}
+
+ bool operator()(int N) {
+ Counter++;
+ return N % 2 == 1;
+ }
+ };
+ Callable IsOdd(Counter);
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+ auto Range = make_filter_range(A, IsOdd);
+ EXPECT_EQ(2, Counter);
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_GE(Counter, 7);
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, FunctionPointer) {
+ bool (*IsOdd)(int) = [](int N) { return N % 2 == 1; };
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+ auto Range = make_filter_range(A, IsOdd);
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, Composition) {
+ auto IsOdd = [](int N) { return N % 2 == 1; };
+ std::unique_ptr<int> A[] = {make_unique<int>(0), make_unique<int>(1),
+ make_unique<int>(2), make_unique<int>(3),
+ make_unique<int>(4), make_unique<int>(5),
+ make_unique<int>(6)};
+ using PointeeIterator = pointee_iterator<std::unique_ptr<int> *>;
+ auto Range = make_filter_range(
+ make_range(PointeeIterator(std::begin(A)), PointeeIterator(std::end(A))),
+ IsOdd);
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, InputIterator) {
+ struct InputIterator
+ : iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag> {
+ using BaseT =
+ iterator_adaptor_base<InputIterator, int *, std::input_iterator_tag>;
+
+ InputIterator(int *It) : BaseT(It) {}
+ };
+
+ auto IsOdd = [](int N) { return N % 2 == 1; };
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+ auto Range = make_filter_range(
+ make_range(InputIterator(std::begin(A)), InputIterator(std::end(A))),
+ IsOdd);
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual);
+}
+
+TEST(FilterIteratorTest, ReverseFilterRange) {
+ auto IsOdd = [](int N) { return N % 2 == 1; };
+ int A[] = {0, 1, 2, 3, 4, 5, 6};
+
+ // Check basic reversal.
+ auto Range = reverse(make_filter_range(A, IsOdd));
+ SmallVector<int, 3> Actual(Range.begin(), Range.end());
+ EXPECT_EQ((SmallVector<int, 3>{5, 3, 1}), Actual);
+
+ // Check that the reverse of the reverse is the original.
+ auto Range2 = reverse(reverse(make_filter_range(A, IsOdd)));
+ SmallVector<int, 3> Actual2(Range2.begin(), Range2.end());
+ EXPECT_EQ((SmallVector<int, 3>{1, 3, 5}), Actual2);
+
+ // Check empty ranges.
+ auto Range3 = reverse(make_filter_range(ArrayRef<int>(), IsOdd));
+ SmallVector<int, 0> Actual3(Range3.begin(), Range3.end());
+ EXPECT_EQ((SmallVector<int, 0>{}), Actual3);
+
+ // Check that we don't skip the first element, provided it isn't filtered
+ // away.
+ auto IsEven = [](int N) { return N % 2 == 0; };
+ auto Range4 = reverse(make_filter_range(A, IsEven));
+ SmallVector<int, 4> Actual4(Range4.begin(), Range4.end());
+ EXPECT_EQ((SmallVector<int, 4>{6, 4, 2, 0}), Actual4);
+}
+
+TEST(PointerIterator, Basic) {
+ int A[] = {1, 2, 3, 4};
+ pointer_iterator<int *> Begin(std::begin(A)), End(std::end(A));
+ EXPECT_EQ(A, *Begin);
+ ++Begin;
+ EXPECT_EQ(A + 1, *Begin);
+ ++Begin;
+ EXPECT_EQ(A + 2, *Begin);
+ ++Begin;
+ EXPECT_EQ(A + 3, *Begin);
+ ++Begin;
+ EXPECT_EQ(Begin, End);
+}
+
+TEST(PointerIterator, Const) {
+ int A[] = {1, 2, 3, 4};
+ const pointer_iterator<int *> Begin(std::begin(A));
+ EXPECT_EQ(A, *Begin);
+ EXPECT_EQ(A + 1, std::next(*Begin, 1));
+ EXPECT_EQ(A + 2, std::next(*Begin, 2));
+ EXPECT_EQ(A + 3, std::next(*Begin, 3));
+ EXPECT_EQ(A + 4, std::next(*Begin, 4));
+}
+
+TEST(PointerIterator, Range) {
+ int A[] = {1, 2, 3, 4};
+ int I = 0;
+ for (int *P : make_pointer_range(A))
+ EXPECT_EQ(A + I++, P);
+}
+
+TEST(ZipIteratorTest, Basic) {
+ using namespace std;
+ const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
+ SmallVector<bool, 6> odd{1, 1, 0, 1, 1, 1};
+ const char message[] = "yynyyy\0";
+
+ for (auto tup : zip(pi, odd, message)) {
+ EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
+ EXPECT_EQ(get<0>(tup) & 0x01 ? 'y' : 'n', get<2>(tup));
+ }
+
+ // note the rvalue
+ for (auto tup : zip(pi, SmallVector<bool, 0>{1, 1, 0, 1, 1})) {
+ EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
+ }
+}
+
+TEST(ZipIteratorTest, ZipFirstBasic) {
+ using namespace std;
+ const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
+ unsigned iters = 0;
+
+ for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
+ EXPECT_EQ(get<0>(tup), get<1>(tup) & 0x01);
+ iters += 1;
+ }
+
+ EXPECT_EQ(iters, 4u);
+}
+
+TEST(ZipIteratorTest, ZipLongestBasic) {
+ using namespace std;
+ const vector<unsigned> pi{3, 1, 4, 1, 5, 9};
+ const vector<StringRef> e{"2", "7", "1", "8"};
+
+ {
+ // Check left range longer than right.
+ const vector<tuple<Optional<unsigned>, Optional<StringRef>>> expected{
+ make_tuple(3, StringRef("2")), make_tuple(1, StringRef("7")),
+ make_tuple(4, StringRef("1")), make_tuple(1, StringRef("8")),
+ make_tuple(5, None), make_tuple(9, None)};
+ size_t iters = 0;
+ for (auto tup : zip_longest(pi, e)) {
+ EXPECT_EQ(tup, expected[iters]);
+ iters += 1;
+ }
+ EXPECT_EQ(iters, expected.size());
+ }
+
+ {
+ // Check right range longer than left.
+ const vector<tuple<Optional<StringRef>, Optional<unsigned>>> expected{
+ make_tuple(StringRef("2"), 3), make_tuple(StringRef("7"), 1),
+ make_tuple(StringRef("1"), 4), make_tuple(StringRef("8"), 1),
+ make_tuple(None, 5), make_tuple(None, 9)};
+ size_t iters = 0;
+ for (auto tup : zip_longest(e, pi)) {
+ EXPECT_EQ(tup, expected[iters]);
+ iters += 1;
+ }
+ EXPECT_EQ(iters, expected.size());
+ }
+}
+
+TEST(ZipIteratorTest, Mutability) {
+ using namespace std;
+ const SmallVector<unsigned, 4> pi{3, 1, 4, 1, 5, 9};
+ char message[] = "hello zip\0";
+
+ for (auto tup : zip(pi, message, message)) {
+ EXPECT_EQ(get<1>(tup), get<2>(tup));
+ get<2>(tup) = get<0>(tup) & 0x01 ? 'y' : 'n';
+ }
+
+ // note the rvalue
+ for (auto tup : zip(message, "yynyyyzip\0")) {
+ EXPECT_EQ(get<0>(tup), get<1>(tup));
+ }
+}
+
+TEST(ZipIteratorTest, ZipFirstMutability) {
+ using namespace std;
+ vector<unsigned> pi{3, 1, 4, 1, 5, 9};
+ unsigned iters = 0;
+
+ for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
+ get<1>(tup) = get<0>(tup);
+ iters += 1;
+ }
+
+ EXPECT_EQ(iters, 4u);
+
+ for (auto tup : zip_first(SmallVector<bool, 0>{1, 1, 0, 1}, pi)) {
+ EXPECT_EQ(get<0>(tup), get<1>(tup));
+ }
+}
+
+TEST(ZipIteratorTest, Filter) {
+ using namespace std;
+ vector<unsigned> pi{3, 1, 4, 1, 5, 9};
+
+ unsigned iters = 0;
+ // pi is length 6, but the zip RHS is length 7.
+ auto zipped = zip_first(pi, vector<bool>{1, 1, 0, 1, 1, 1, 0});
+ for (auto tup : make_filter_range(
+ zipped, [](decltype(zipped)::value_type t) { return get<1>(t); })) {
+ EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
+ get<0>(tup) += 1;
+ iters += 1;
+ }
+
+ // Should have skipped pi[2].
+ EXPECT_EQ(iters, 5u);
+
+ // Ensure that in-place mutation works.
+ EXPECT_TRUE(all_of(pi, [](unsigned n) { return (n & 0x01) == 0; }));
+}
+
+TEST(ZipIteratorTest, Reverse) {
+ using namespace std;
+ vector<unsigned> ascending{0, 1, 2, 3, 4, 5};
+
+ auto zipped = zip_first(ascending, vector<bool>{0, 1, 0, 1, 0, 1});
+ unsigned last = 6;
+ for (auto tup : reverse(zipped)) {
+ // Check that this is in reverse.
+ EXPECT_LT(get<0>(tup), last);
+ last = get<0>(tup);
+ EXPECT_EQ(get<0>(tup) & 0x01, get<1>(tup));
+ }
+
+ auto odds = [](decltype(zipped)::value_type tup) { return get<1>(tup); };
+ last = 6;
+ for (auto tup : make_filter_range(reverse(zipped), odds)) {
+ EXPECT_LT(get<0>(tup), last);
+ last = get<0>(tup);
+ EXPECT_TRUE(get<0>(tup) & 0x01);
+ get<0>(tup) += 1;
+ }
+
+ // Ensure that in-place mutation works.
+ EXPECT_TRUE(all_of(ascending, [](unsigned n) { return (n & 0x01) == 0; }));
+}
+
+TEST(RangeTest, Distance) {
+ std::vector<int> v1;
+ std::vector<int> v2{1, 2, 3};
+
+ EXPECT_EQ(std::distance(v1.begin(), v1.end()), size(v1));
+ EXPECT_EQ(std::distance(v2.begin(), v2.end()), size(v2));
+}
+
+TEST(IteratorRangeTest, DropBegin) {
+ SmallVector<int, 5> vec{0, 1, 2, 3, 4};
+
+ for (int n = 0; n < 5; ++n) {
+ int i = n;
+ for (auto &v : drop_begin(vec, n)) {
+ EXPECT_EQ(v, i);
+ i += 1;
+ }
+ EXPECT_EQ(i, 5);
+ }
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/MakeUniqueTest.cpp b/src/llvm-project/llvm/unittests/ADT/MakeUniqueTest.cpp
new file mode 100644
index 0000000..3b4938a
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/MakeUniqueTest.cpp
@@ -0,0 +1,76 @@
+//===- llvm/unittest/ADT/MakeUniqueTest.cpp - make_unique unit tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+#include <tuple>
+using namespace llvm;
+
+namespace {
+
+TEST(MakeUniqueTest, SingleObject) {
+ auto p0 = make_unique<int>();
+ EXPECT_TRUE((bool)p0);
+ EXPECT_EQ(0, *p0);
+
+ auto p1 = make_unique<int>(5);
+ EXPECT_TRUE((bool)p1);
+ EXPECT_EQ(5, *p1);
+
+ auto p2 = make_unique<std::tuple<int, int>>(0, 1);
+ EXPECT_TRUE((bool)p2);
+ EXPECT_EQ(std::make_tuple(0, 1), *p2);
+
+ auto p3 = make_unique<std::tuple<int, int, int>>(0, 1, 2);
+ EXPECT_TRUE((bool)p3);
+ EXPECT_EQ(std::make_tuple(0, 1, 2), *p3);
+
+ auto p4 = make_unique<std::tuple<int, int, int, int>>(0, 1, 2, 3);
+ EXPECT_TRUE((bool)p4);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3), *p4);
+
+ auto p5 = make_unique<std::tuple<int, int, int, int, int>>(0, 1, 2, 3, 4);
+ EXPECT_TRUE((bool)p5);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4), *p5);
+
+ auto p6 =
+ make_unique<std::tuple<int, int, int, int, int, int>>(0, 1, 2, 3, 4, 5);
+ EXPECT_TRUE((bool)p6);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5), *p6);
+
+ auto p7 = make_unique<std::tuple<int, int, int, int, int, int, int>>(
+ 0, 1, 2, 3, 4, 5, 6);
+ EXPECT_TRUE((bool)p7);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6), *p7);
+
+ auto p8 = make_unique<std::tuple<int, int, int, int, int, int, int, int>>(
+ 0, 1, 2, 3, 4, 5, 6, 7);
+ EXPECT_TRUE((bool)p8);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7), *p8);
+
+ auto p9 =
+ make_unique<std::tuple<int, int, int, int, int, int, int, int, int>>(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8);
+ EXPECT_TRUE((bool)p9);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8), *p9);
+
+ auto p10 =
+ make_unique<std::tuple<int, int, int, int, int, int, int, int, int, int>>(
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
+ EXPECT_TRUE((bool)p10);
+ EXPECT_EQ(std::make_tuple(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), *p10);
+}
+
+TEST(MakeUniqueTest, Array) {
+ auto p1 = make_unique<int[]>(2);
+ EXPECT_TRUE((bool)p1);
+ EXPECT_EQ(0, p1[0]);
+ EXPECT_EQ(0, p1[1]);
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/MapVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/MapVectorTest.cpp
new file mode 100644
index 0000000..16e9b5a
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/MapVectorTest.cpp
@@ -0,0 +1,424 @@
+//===- unittest/ADT/MapVectorTest.cpp - MapVector unit tests ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/iterator_range.h"
+#include "gtest/gtest.h"
+#include <utility>
+
+using namespace llvm;
+
+TEST(MapVectorTest, swap) {
+ MapVector<int, int> MV1, MV2;
+ std::pair<MapVector<int, int>::iterator, bool> R;
+
+ R = MV1.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV1.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_FALSE(MV1.empty());
+ EXPECT_TRUE(MV2.empty());
+ MV2.swap(MV1);
+ EXPECT_TRUE(MV1.empty());
+ EXPECT_FALSE(MV2.empty());
+
+ auto I = MV1.find(1);
+ ASSERT_EQ(MV1.end(), I);
+
+ I = MV2.find(1);
+ ASSERT_EQ(I, MV2.begin());
+ EXPECT_EQ(I->first, 1);
+ EXPECT_EQ(I->second, 2);
+}
+
+TEST(MapVectorTest, insert_pop) {
+ MapVector<int, int> MV;
+ std::pair<MapVector<int, int>::iterator, bool> R;
+
+ R = MV.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ R = MV.insert(std::make_pair(1, 3));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_FALSE(R.second);
+
+ R = MV.insert(std::make_pair(4, 5));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 5);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 5);
+
+ MV.pop_back();
+ EXPECT_EQ(MV.size(), 1u);
+ EXPECT_EQ(MV[1], 2);
+
+ R = MV.insert(std::make_pair(4, 7));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 7);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 7);
+}
+
+TEST(MapVectorTest, erase) {
+ MapVector<int, int> MV;
+
+ MV.insert(std::make_pair(1, 2));
+ MV.insert(std::make_pair(3, 4));
+ MV.insert(std::make_pair(5, 6));
+ ASSERT_EQ(MV.size(), 3u);
+
+ MV.erase(MV.find(1));
+ ASSERT_EQ(MV.size(), 2u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV[3], 4);
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(3), 1u);
+ ASSERT_EQ(MV.size(), 1u);
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(79), 0u);
+ ASSERT_EQ(MV.size(), 1u);
+}
+
+TEST(MapVectorTest, remove_if) {
+ MapVector<int, int> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
+ ASSERT_EQ(MV.size(), 3u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV.find(5), MV.end());
+ ASSERT_EQ(MV[2], 12);
+ ASSERT_EQ(MV[4], 14);
+ ASSERT_EQ(MV[6], 16);
+}
+
+TEST(MapVectorTest, iteration_test) {
+ MapVector<int, int> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ int count = 1;
+ for (auto P : make_range(MV.begin(), MV.end())) {
+ ASSERT_EQ(P.first, count);
+ count++;
+ }
+
+ count = 6;
+ for (auto P : make_range(MV.rbegin(), MV.rend())) {
+ ASSERT_EQ(P.first, count);
+ count--;
+ }
+}
+
+TEST(MapVectorTest, NonCopyable) {
+ MapVector<int, std::unique_ptr<int>> MV;
+ MV.insert(std::make_pair(1, llvm::make_unique<int>(1)));
+ MV.insert(std::make_pair(2, llvm::make_unique<int>(2)));
+
+ ASSERT_EQ(MV.count(1), 1u);
+ ASSERT_EQ(*MV.find(2)->second, 2);
+}
+
+template <class IntType> struct MapVectorMappedTypeTest : ::testing::Test {
+ using int_type = IntType;
+};
+
+using MapIntTypes = ::testing::Types<int, long, long long, unsigned,
+ unsigned long, unsigned long long>;
+TYPED_TEST_CASE(MapVectorMappedTypeTest, MapIntTypes);
+
+TYPED_TEST(MapVectorMappedTypeTest, DifferentDenseMap) {
+ // Test that using a map with a mapped type other than 'unsigned' compiles
+ // and works.
+ using IntType = typename TestFixture::int_type;
+ using MapVectorType = MapVector<int, int, DenseMap<int, IntType>>;
+
+ MapVectorType MV;
+ std::pair<typename MapVectorType::iterator, bool> R;
+
+ R = MV.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ const std::pair<int, int> Elem(1, 3);
+ R = MV.insert(Elem);
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_FALSE(R.second);
+
+ int& value = MV[4];
+ EXPECT_EQ(value, 0);
+ value = 5;
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 5);
+}
+
+TEST(SmallMapVectorSmallTest, insert_pop) {
+ SmallMapVector<int, int, 32> MV;
+ std::pair<SmallMapVector<int, int, 32>::iterator, bool> R;
+
+ R = MV.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ R = MV.insert(std::make_pair(1, 3));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_FALSE(R.second);
+
+ R = MV.insert(std::make_pair(4, 5));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 5);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 5);
+
+ MV.pop_back();
+ EXPECT_EQ(MV.size(), 1u);
+ EXPECT_EQ(MV[1], 2);
+
+ R = MV.insert(std::make_pair(4, 7));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 7);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 7);
+}
+
+TEST(SmallMapVectorSmallTest, erase) {
+ SmallMapVector<int, int, 32> MV;
+
+ MV.insert(std::make_pair(1, 2));
+ MV.insert(std::make_pair(3, 4));
+ MV.insert(std::make_pair(5, 6));
+ ASSERT_EQ(MV.size(), 3u);
+
+ MV.erase(MV.find(1));
+ ASSERT_EQ(MV.size(), 2u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV[3], 4);
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(3), 1u);
+ ASSERT_EQ(MV.size(), 1u);
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(79), 0u);
+ ASSERT_EQ(MV.size(), 1u);
+}
+
+TEST(SmallMapVectorSmallTest, remove_if) {
+ SmallMapVector<int, int, 32> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
+ ASSERT_EQ(MV.size(), 3u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV.find(5), MV.end());
+ ASSERT_EQ(MV[2], 12);
+ ASSERT_EQ(MV[4], 14);
+ ASSERT_EQ(MV[6], 16);
+}
+
+TEST(SmallMapVectorSmallTest, iteration_test) {
+ SmallMapVector<int, int, 32> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ int count = 1;
+ for (auto P : make_range(MV.begin(), MV.end())) {
+ ASSERT_EQ(P.first, count);
+ count++;
+ }
+
+ count = 6;
+ for (auto P : make_range(MV.rbegin(), MV.rend())) {
+ ASSERT_EQ(P.first, count);
+ count--;
+ }
+}
+
+TEST(SmallMapVectorSmallTest, NonCopyable) {
+ SmallMapVector<int, std::unique_ptr<int>, 8> MV;
+ MV.insert(std::make_pair(1, llvm::make_unique<int>(1)));
+ MV.insert(std::make_pair(2, llvm::make_unique<int>(2)));
+
+ ASSERT_EQ(MV.count(1), 1u);
+ ASSERT_EQ(*MV.find(2)->second, 2);
+}
+
+TEST(SmallMapVectorLargeTest, insert_pop) {
+ SmallMapVector<int, int, 1> MV;
+ std::pair<SmallMapVector<int, int, 1>::iterator, bool> R;
+
+ R = MV.insert(std::make_pair(1, 2));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_TRUE(R.second);
+
+ R = MV.insert(std::make_pair(1, 3));
+ ASSERT_EQ(R.first, MV.begin());
+ EXPECT_EQ(R.first->first, 1);
+ EXPECT_EQ(R.first->second, 2);
+ EXPECT_FALSE(R.second);
+
+ R = MV.insert(std::make_pair(4, 5));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 5);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 5);
+
+ MV.pop_back();
+ EXPECT_EQ(MV.size(), 1u);
+ EXPECT_EQ(MV[1], 2);
+
+ R = MV.insert(std::make_pair(4, 7));
+ ASSERT_NE(R.first, MV.end());
+ EXPECT_EQ(R.first->first, 4);
+ EXPECT_EQ(R.first->second, 7);
+ EXPECT_TRUE(R.second);
+
+ EXPECT_EQ(MV.size(), 2u);
+ EXPECT_EQ(MV[1], 2);
+ EXPECT_EQ(MV[4], 7);
+}
+
+TEST(SmallMapVectorLargeTest, erase) {
+ SmallMapVector<int, int, 1> MV;
+
+ MV.insert(std::make_pair(1, 2));
+ MV.insert(std::make_pair(3, 4));
+ MV.insert(std::make_pair(5, 6));
+ ASSERT_EQ(MV.size(), 3u);
+
+ MV.erase(MV.find(1));
+ ASSERT_EQ(MV.size(), 2u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV[3], 4);
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(3), 1u);
+ ASSERT_EQ(MV.size(), 1u);
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV[5], 6);
+
+ ASSERT_EQ(MV.erase(79), 0u);
+ ASSERT_EQ(MV.size(), 1u);
+}
+
+TEST(SmallMapVectorLargeTest, remove_if) {
+ SmallMapVector<int, int, 1> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ MV.remove_if([](const std::pair<int, int> &Val) { return Val.second % 2; });
+ ASSERT_EQ(MV.size(), 3u);
+ ASSERT_EQ(MV.find(1), MV.end());
+ ASSERT_EQ(MV.find(3), MV.end());
+ ASSERT_EQ(MV.find(5), MV.end());
+ ASSERT_EQ(MV[2], 12);
+ ASSERT_EQ(MV[4], 14);
+ ASSERT_EQ(MV[6], 16);
+}
+
+TEST(SmallMapVectorLargeTest, iteration_test) {
+ SmallMapVector<int, int, 1> MV;
+
+ MV.insert(std::make_pair(1, 11));
+ MV.insert(std::make_pair(2, 12));
+ MV.insert(std::make_pair(3, 13));
+ MV.insert(std::make_pair(4, 14));
+ MV.insert(std::make_pair(5, 15));
+ MV.insert(std::make_pair(6, 16));
+ ASSERT_EQ(MV.size(), 6u);
+
+ int count = 1;
+ for (auto P : make_range(MV.begin(), MV.end())) {
+ ASSERT_EQ(P.first, count);
+ count++;
+ }
+
+ count = 6;
+ for (auto P : make_range(MV.rbegin(), MV.rend())) {
+ ASSERT_EQ(P.first, count);
+ count--;
+ }
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/MappedIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/MappedIteratorTest.cpp
new file mode 100644
index 0000000..d8c48a7
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/MappedIteratorTest.cpp
@@ -0,0 +1,51 @@
+//===------ MappedIteratorTest.cpp - Unit tests for mapped_iterator -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(MappedIteratorTest, ApplyFunctionOnDereference) {
+ std::vector<int> V({0});
+
+ auto I = map_iterator(V.begin(), [](int X) { return X + 1; });
+
+ EXPECT_EQ(*I, 1) << "should have applied function in dereference";
+}
+
+TEST(MappedIteratorTest, ApplyFunctionOnArrow) {
+ struct S {
+ int Z = 0;
+ };
+
+ std::vector<int> V({0});
+ S Y;
+ S* P = &Y;
+
+ auto I = map_iterator(V.begin(), [&](int X) -> S& { return *(P + X); });
+
+ I->Z = 42;
+
+ EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";
+}
+
+TEST(MappedIteratorTest, FunctionPreservesReferences) {
+ std::vector<int> V({1});
+ std::map<int, int> M({ {1, 1} });
+
+ auto I = map_iterator(V.begin(), [&](int X) -> int& { return M[X]; });
+ *I = 42;
+
+ EXPECT_EQ(M[1], 42) << "assignment should have modified M";
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/OptionalTest.cpp b/src/llvm-project/llvm/unittests/ADT/OptionalTest.cpp
new file mode 100644
index 0000000..20bc9da
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/OptionalTest.cpp
@@ -0,0 +1,522 @@
+//===- llvm/unittest/ADT/OptionalTest.cpp - Optional unit tests -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Optional.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+struct NonDefaultConstructible {
+ static unsigned CopyConstructions;
+ static unsigned Destructions;
+ static unsigned CopyAssignments;
+ explicit NonDefaultConstructible(int) {
+ }
+ NonDefaultConstructible(const NonDefaultConstructible&) {
+ ++CopyConstructions;
+ }
+ NonDefaultConstructible &operator=(const NonDefaultConstructible&) {
+ ++CopyAssignments;
+ return *this;
+ }
+ ~NonDefaultConstructible() {
+ ++Destructions;
+ }
+ static void ResetCounts() {
+ CopyConstructions = 0;
+ Destructions = 0;
+ CopyAssignments = 0;
+ }
+};
+
+unsigned NonDefaultConstructible::CopyConstructions = 0;
+unsigned NonDefaultConstructible::Destructions = 0;
+unsigned NonDefaultConstructible::CopyAssignments = 0;
+
+// Test fixture
+class OptionalTest : public testing::Test {
+};
+
+TEST_F(OptionalTest, NonDefaultConstructibleTest) {
+ Optional<NonDefaultConstructible> O;
+ EXPECT_FALSE(O);
+}
+
+TEST_F(OptionalTest, ResetTest) {
+ NonDefaultConstructible::ResetCounts();
+ Optional<NonDefaultConstructible> O(NonDefaultConstructible(3));
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ O.reset();
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, InitializationLeakTest) {
+ NonDefaultConstructible::ResetCounts();
+ Optional<NonDefaultConstructible>(NonDefaultConstructible(3));
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, CopyConstructionTest) {
+ NonDefaultConstructible::ResetCounts();
+ {
+ Optional<NonDefaultConstructible> A(NonDefaultConstructible(3));
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ Optional<NonDefaultConstructible> B(A);
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ }
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, ConstructingCopyAssignmentTest) {
+ NonDefaultConstructible::ResetCounts();
+ {
+ Optional<NonDefaultConstructible> A(NonDefaultConstructible(3));
+ Optional<NonDefaultConstructible> B;
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ B = A;
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ }
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, CopyingCopyAssignmentTest) {
+ NonDefaultConstructible::ResetCounts();
+ {
+ Optional<NonDefaultConstructible> A(NonDefaultConstructible(3));
+ Optional<NonDefaultConstructible> B(NonDefaultConstructible(4));
+ EXPECT_EQ(2u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ B = A;
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ }
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(2u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, DeletingCopyAssignmentTest) {
+ NonDefaultConstructible::ResetCounts();
+ {
+ Optional<NonDefaultConstructible> A;
+ Optional<NonDefaultConstructible> B(NonDefaultConstructible(3));
+ EXPECT_EQ(1u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ B = A;
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(1u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ }
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, NullCopyConstructionTest) {
+ NonDefaultConstructible::ResetCounts();
+ {
+ Optional<NonDefaultConstructible> A;
+ Optional<NonDefaultConstructible> B;
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ B = A;
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+ NonDefaultConstructible::ResetCounts();
+ }
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyConstructions);
+ EXPECT_EQ(0u, NonDefaultConstructible::CopyAssignments);
+ EXPECT_EQ(0u, NonDefaultConstructible::Destructions);
+}
+
+TEST_F(OptionalTest, GetValueOr) {
+ Optional<int> A;
+ EXPECT_EQ(42, A.getValueOr(42));
+
+ A = 5;
+ EXPECT_EQ(5, A.getValueOr(42));
+}
+
+struct MultiArgConstructor {
+ int x, y;
+ MultiArgConstructor(int x, int y) : x(x), y(y) {}
+ explicit MultiArgConstructor(int x, bool positive)
+ : x(x), y(positive ? x : -x) {}
+
+ MultiArgConstructor(const MultiArgConstructor &) = delete;
+ MultiArgConstructor(MultiArgConstructor &&) = delete;
+ MultiArgConstructor &operator=(const MultiArgConstructor &) = delete;
+ MultiArgConstructor &operator=(MultiArgConstructor &&) = delete;
+
+ static unsigned Destructions;
+ ~MultiArgConstructor() {
+ ++Destructions;
+ }
+ static void ResetCounts() {
+ Destructions = 0;
+ }
+};
+unsigned MultiArgConstructor::Destructions = 0;
+
+TEST_F(OptionalTest, Emplace) {
+ MultiArgConstructor::ResetCounts();
+ Optional<MultiArgConstructor> A;
+
+ A.emplace(1, 2);
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_EQ(1, A->x);
+ EXPECT_EQ(2, A->y);
+ EXPECT_EQ(0u, MultiArgConstructor::Destructions);
+
+ A.emplace(5, false);
+ EXPECT_TRUE(A.hasValue());
+ EXPECT_EQ(5, A->x);
+ EXPECT_EQ(-5, A->y);
+ EXPECT_EQ(1u, MultiArgConstructor::Destructions);
+}
+
+struct MoveOnly {
+ static unsigned MoveConstructions;
+ static unsigned Destructions;
+ static unsigned MoveAssignments;
+ int val;
+ explicit MoveOnly(int val) : val(val) {
+ }
+ MoveOnly(MoveOnly&& other) {
+ val = other.val;
+ ++MoveConstructions;
+ }
+ MoveOnly &operator=(MoveOnly&& other) {
+ val = other.val;
+ ++MoveAssignments;
+ return *this;
+ }
+ ~MoveOnly() {
+ ++Destructions;
+ }
+ static void ResetCounts() {
+ MoveConstructions = 0;
+ Destructions = 0;
+ MoveAssignments = 0;
+ }
+};
+
+unsigned MoveOnly::MoveConstructions = 0;
+unsigned MoveOnly::Destructions = 0;
+unsigned MoveOnly::MoveAssignments = 0;
+
+TEST_F(OptionalTest, MoveOnlyNull) {
+ MoveOnly::ResetCounts();
+ Optional<MoveOnly> O;
+ EXPECT_EQ(0u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyConstruction) {
+ MoveOnly::ResetCounts();
+ Optional<MoveOnly> O(MoveOnly(3));
+ EXPECT_TRUE((bool)O);
+ EXPECT_EQ(3, O->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyMoveConstruction) {
+ Optional<MoveOnly> A(MoveOnly(3));
+ MoveOnly::ResetCounts();
+ Optional<MoveOnly> B(std::move(A));
+ EXPECT_TRUE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyAssignment) {
+ MoveOnly::ResetCounts();
+ Optional<MoveOnly> O;
+ O = MoveOnly(3);
+ EXPECT_TRUE((bool)O);
+ EXPECT_EQ(3, O->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyInitializingAssignment) {
+ Optional<MoveOnly> A(MoveOnly(3));
+ Optional<MoveOnly> B;
+ MoveOnly::ResetCounts();
+ B = std::move(A);
+ EXPECT_TRUE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyNullingAssignment) {
+ Optional<MoveOnly> A;
+ Optional<MoveOnly> B(MoveOnly(3));
+ MoveOnly::ResetCounts();
+ B = std::move(A);
+ EXPECT_FALSE((bool)A);
+ EXPECT_FALSE((bool)B);
+ EXPECT_EQ(0u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, MoveOnly::Destructions);
+}
+
+TEST_F(OptionalTest, MoveOnlyAssigningAssignment) {
+ Optional<MoveOnly> A(MoveOnly(3));
+ Optional<MoveOnly> B(MoveOnly(4));
+ MoveOnly::ResetCounts();
+ B = std::move(A);
+ EXPECT_TRUE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(0u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(1u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(0u, MoveOnly::Destructions);
+}
+
+struct Immovable {
+ static unsigned Constructions;
+ static unsigned Destructions;
+ int val;
+ explicit Immovable(int val) : val(val) {
+ ++Constructions;
+ }
+ ~Immovable() {
+ ++Destructions;
+ }
+ static void ResetCounts() {
+ Constructions = 0;
+ Destructions = 0;
+ }
+private:
+ // This should disable all move/copy operations.
+ Immovable(Immovable&& other) = delete;
+};
+
+unsigned Immovable::Constructions = 0;
+unsigned Immovable::Destructions = 0;
+
+TEST_F(OptionalTest, ImmovableEmplace) {
+ Optional<Immovable> A;
+ Immovable::ResetCounts();
+ A.emplace(4);
+ EXPECT_TRUE((bool)A);
+ EXPECT_EQ(4, A->val);
+ EXPECT_EQ(1u, Immovable::Constructions);
+ EXPECT_EQ(0u, Immovable::Destructions);
+}
+
+#if LLVM_HAS_RVALUE_REFERENCE_THIS
+
+TEST_F(OptionalTest, MoveGetValueOr) {
+ Optional<MoveOnly> A;
+
+ MoveOnly::ResetCounts();
+ EXPECT_EQ(42, std::move(A).getValueOr(MoveOnly(42)).val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(2u, MoveOnly::Destructions);
+
+ A = MoveOnly(5);
+ MoveOnly::ResetCounts();
+ EXPECT_EQ(5, std::move(A).getValueOr(MoveOnly(42)).val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(2u, MoveOnly::Destructions);
+}
+
+#endif // LLVM_HAS_RVALUE_REFERENCE_THIS
+
+struct EqualTo {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X == Y;
+ }
+};
+
+struct NotEqualTo {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X != Y;
+ }
+};
+
+struct Less {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X < Y;
+ }
+};
+
+struct Greater {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X > Y;
+ }
+};
+
+struct LessEqual {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X <= Y;
+ }
+};
+
+struct GreaterEqual {
+ template <typename T, typename U> static bool apply(const T &X, const U &Y) {
+ return X >= Y;
+ }
+};
+
+template <typename OperatorT, typename T>
+void CheckRelation(const Optional<T> &Lhs, const Optional<T> &Rhs,
+ bool Expected) {
+ EXPECT_EQ(Expected, OperatorT::apply(Lhs, Rhs));
+
+ if (Lhs)
+ EXPECT_EQ(Expected, OperatorT::apply(*Lhs, Rhs));
+ else
+ EXPECT_EQ(Expected, OperatorT::apply(None, Rhs));
+
+ if (Rhs)
+ EXPECT_EQ(Expected, OperatorT::apply(Lhs, *Rhs));
+ else
+ EXPECT_EQ(Expected, OperatorT::apply(Lhs, None));
+}
+
+struct EqualityMock {};
+const Optional<EqualityMock> NoneEq, EqualityLhs((EqualityMock())),
+ EqualityRhs((EqualityMock()));
+bool IsEqual;
+
+bool operator==(const EqualityMock &Lhs, const EqualityMock &Rhs) {
+ EXPECT_EQ(&*EqualityLhs, &Lhs);
+ EXPECT_EQ(&*EqualityRhs, &Rhs);
+ return IsEqual;
+}
+
+TEST_F(OptionalTest, OperatorEqual) {
+ CheckRelation<EqualTo>(NoneEq, NoneEq, true);
+ CheckRelation<EqualTo>(NoneEq, EqualityRhs, false);
+ CheckRelation<EqualTo>(EqualityLhs, NoneEq, false);
+
+ IsEqual = false;
+ CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual);
+ IsEqual = true;
+ CheckRelation<EqualTo>(EqualityLhs, EqualityRhs, IsEqual);
+}
+
+TEST_F(OptionalTest, OperatorNotEqual) {
+ CheckRelation<NotEqualTo>(NoneEq, NoneEq, false);
+ CheckRelation<NotEqualTo>(NoneEq, EqualityRhs, true);
+ CheckRelation<NotEqualTo>(EqualityLhs, NoneEq, true);
+
+ IsEqual = false;
+ CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual);
+ IsEqual = true;
+ CheckRelation<NotEqualTo>(EqualityLhs, EqualityRhs, !IsEqual);
+}
+
+struct InequalityMock {};
+const Optional<InequalityMock> NoneIneq, InequalityLhs((InequalityMock())),
+ InequalityRhs((InequalityMock()));
+bool IsLess;
+
+bool operator<(const InequalityMock &Lhs, const InequalityMock &Rhs) {
+ EXPECT_EQ(&*InequalityLhs, &Lhs);
+ EXPECT_EQ(&*InequalityRhs, &Rhs);
+ return IsLess;
+}
+
+TEST_F(OptionalTest, OperatorLess) {
+ CheckRelation<Less>(NoneIneq, NoneIneq, false);
+ CheckRelation<Less>(NoneIneq, InequalityRhs, true);
+ CheckRelation<Less>(InequalityLhs, NoneIneq, false);
+
+ IsLess = false;
+ CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess);
+ IsLess = true;
+ CheckRelation<Less>(InequalityLhs, InequalityRhs, IsLess);
+}
+
+TEST_F(OptionalTest, OperatorGreater) {
+ CheckRelation<Greater>(NoneIneq, NoneIneq, false);
+ CheckRelation<Greater>(NoneIneq, InequalityRhs, false);
+ CheckRelation<Greater>(InequalityLhs, NoneIneq, true);
+
+ IsLess = false;
+ CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess);
+ IsLess = true;
+ CheckRelation<Greater>(InequalityRhs, InequalityLhs, IsLess);
+}
+
+TEST_F(OptionalTest, OperatorLessEqual) {
+ CheckRelation<LessEqual>(NoneIneq, NoneIneq, true);
+ CheckRelation<LessEqual>(NoneIneq, InequalityRhs, true);
+ CheckRelation<LessEqual>(InequalityLhs, NoneIneq, false);
+
+ IsLess = false;
+ CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess);
+ IsLess = true;
+ CheckRelation<LessEqual>(InequalityRhs, InequalityLhs, !IsLess);
+}
+
+TEST_F(OptionalTest, OperatorGreaterEqual) {
+ CheckRelation<GreaterEqual>(NoneIneq, NoneIneq, true);
+ CheckRelation<GreaterEqual>(NoneIneq, InequalityRhs, false);
+ CheckRelation<GreaterEqual>(InequalityLhs, NoneIneq, true);
+
+ IsLess = false;
+ CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
+ IsLess = true;
+ CheckRelation<GreaterEqual>(InequalityLhs, InequalityRhs, !IsLess);
+}
+
+} // end anonymous namespace
+
diff --git a/src/llvm-project/llvm/unittests/ADT/PackedVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/PackedVectorTest.cpp
new file mode 100644
index 0000000..199a670
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PackedVectorTest.cpp
@@ -0,0 +1,103 @@
+//===- llvm/unittest/ADT/PackedVectorTest.cpp - PackedVector tests --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// BitVectorTest tests fail on PowerPC for unknown reasons, so disable this
+// as well since it depends on a BitVector.
+#ifndef __ppc__
+
+#include "llvm/ADT/PackedVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(PackedVectorTest, Operation) {
+ PackedVector<unsigned, 2> Vec;
+ EXPECT_EQ(0U, Vec.size());
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.resize(5);
+ EXPECT_EQ(5U, Vec.size());
+ EXPECT_FALSE(Vec.empty());
+
+ Vec.resize(11);
+ EXPECT_EQ(11U, Vec.size());
+ EXPECT_FALSE(Vec.empty());
+
+ PackedVector<unsigned, 2> Vec2(3);
+ EXPECT_EQ(3U, Vec2.size());
+ EXPECT_FALSE(Vec2.empty());
+
+ Vec.clear();
+ EXPECT_EQ(0U, Vec.size());
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.push_back(2);
+ Vec.push_back(0);
+ Vec.push_back(1);
+ Vec.push_back(3);
+
+ EXPECT_EQ(2U, Vec[0]);
+ EXPECT_EQ(0U, Vec[1]);
+ EXPECT_EQ(1U, Vec[2]);
+ EXPECT_EQ(3U, Vec[3]);
+
+ EXPECT_FALSE(Vec == Vec2);
+ EXPECT_TRUE(Vec != Vec2);
+
+ Vec = Vec2;
+ EXPECT_TRUE(Vec == Vec2);
+ EXPECT_FALSE(Vec != Vec2);
+
+ Vec[1] = 1;
+ Vec2[1] = 2;
+ Vec |= Vec2;
+ EXPECT_EQ(3U, Vec[1]);
+}
+
+#ifdef EXPECT_DEBUG_DEATH
+
+TEST(PackedVectorTest, UnsignedValues) {
+ PackedVector<unsigned, 2> Vec(1);
+ Vec[0] = 0;
+ Vec[0] = 1;
+ Vec[0] = 2;
+ Vec[0] = 3;
+ EXPECT_DEBUG_DEATH(Vec[0] = 4, "value is too big");
+ EXPECT_DEBUG_DEATH(Vec[0] = -1, "value is too big");
+ EXPECT_DEBUG_DEATH(Vec[0] = 0x100, "value is too big");
+
+ PackedVector<unsigned, 3> Vec2(1);
+ Vec2[0] = 0;
+ Vec2[0] = 7;
+ EXPECT_DEBUG_DEATH(Vec[0] = 8, "value is too big");
+}
+
+TEST(PackedVectorTest, SignedValues) {
+ PackedVector<signed, 2> Vec(1);
+ Vec[0] = -2;
+ Vec[0] = -1;
+ Vec[0] = 0;
+ Vec[0] = 1;
+ EXPECT_DEBUG_DEATH(Vec[0] = -3, "value is too big");
+ EXPECT_DEBUG_DEATH(Vec[0] = 2, "value is too big");
+
+ PackedVector<signed, 3> Vec2(1);
+ Vec2[0] = -4;
+ Vec2[0] = 3;
+ EXPECT_DEBUG_DEATH(Vec[0] = -5, "value is too big");
+ EXPECT_DEBUG_DEATH(Vec[0] = 4, "value is too big");
+}
+
+#endif
+
+}
+
+#endif
diff --git a/src/llvm-project/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp b/src/llvm-project/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp
new file mode 100644
index 0000000..695ea12
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp
@@ -0,0 +1,80 @@
+//===- llvm/unittest/ADT/PointerEmbeddedIntTest.cpp -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/PointerEmbeddedInt.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(PointerEmbeddedIntTest, Basic) {
+ PointerEmbeddedInt<int, CHAR_BIT> I = 42, J = 43;
+
+ EXPECT_EQ(42, I);
+ EXPECT_EQ(43, I + 1);
+ EXPECT_EQ(sizeof(uintptr_t) * CHAR_BIT - CHAR_BIT,
+ PointerLikeTypeTraits<decltype(I)>::NumLowBitsAvailable);
+
+ EXPECT_FALSE(I == J);
+ EXPECT_TRUE(I != J);
+ EXPECT_TRUE(I < J);
+ EXPECT_FALSE(I > J);
+ EXPECT_TRUE(I <= J);
+ EXPECT_FALSE(I >= J);
+
+ EXPECT_FALSE(I == 43);
+ EXPECT_TRUE(I != 43);
+ EXPECT_TRUE(I < 43);
+ EXPECT_FALSE(I > 43);
+ EXPECT_TRUE(I <= 43);
+ EXPECT_FALSE(I >= 43);
+
+ EXPECT_FALSE(42 == J);
+ EXPECT_TRUE(42 != J);
+ EXPECT_TRUE(42 < J);
+ EXPECT_FALSE(42 > J);
+ EXPECT_TRUE(42 <= J);
+ EXPECT_FALSE(42 >= J);
+}
+
+TEST(PointerEmbeddedIntTest, intptr_t) {
+ PointerEmbeddedInt<intptr_t, CHAR_BIT> IPos = 42, INeg = -42;
+ EXPECT_EQ(42, IPos);
+ EXPECT_EQ(-42, INeg);
+
+ PointerEmbeddedInt<uintptr_t, CHAR_BIT> U = 42, USaturated = 255;
+ EXPECT_EQ(42U, U);
+ EXPECT_EQ(255U, USaturated);
+
+ PointerEmbeddedInt<intptr_t, std::numeric_limits<intptr_t>::digits>
+ IMax = std::numeric_limits<intptr_t>::max() >> 1,
+ IMin = std::numeric_limits<intptr_t>::min() >> 1;
+ EXPECT_EQ(std::numeric_limits<intptr_t>::max() >> 1, IMax);
+ EXPECT_EQ(std::numeric_limits<intptr_t>::min() >> 1, IMin);
+
+ PointerEmbeddedInt<uintptr_t, std::numeric_limits<uintptr_t>::digits - 1>
+ UMax = std::numeric_limits<uintptr_t>::max() >> 1,
+ UMin = std::numeric_limits<uintptr_t>::min() >> 1;
+ EXPECT_EQ(std::numeric_limits<uintptr_t>::max() >> 1, UMax);
+ EXPECT_EQ(std::numeric_limits<uintptr_t>::min() >> 1, UMin);
+}
+
+TEST(PointerEmbeddedIntTest, PointerLikeTypeTraits) {
+ PointerEmbeddedInt<int, CHAR_BIT> I = 42;
+ using ITraits = PointerLikeTypeTraits<decltype(I)>;
+ EXPECT_EQ(42, ITraits::getFromVoidPointer(ITraits::getAsVoidPointer(I)));
+
+ PointerEmbeddedInt<uintptr_t, std::numeric_limits<uintptr_t>::digits - 1>
+ Max = std::numeric_limits<uintptr_t>::max() >> 1;
+ using MaxTraits = PointerLikeTypeTraits<decltype(Max)>;
+ EXPECT_EQ(std::numeric_limits<uintptr_t>::max() >> 1,
+ MaxTraits::getFromVoidPointer(MaxTraits::getAsVoidPointer(Max)));
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/PointerIntPairTest.cpp b/src/llvm-project/llvm/unittests/ADT/PointerIntPairTest.cpp
new file mode 100644
index 0000000..985fdba
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PointerIntPairTest.cpp
@@ -0,0 +1,102 @@
+//===- llvm/unittest/ADT/PointerIntPairTest.cpp - Unit tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/PointerIntPair.h"
+#include "gtest/gtest.h"
+#include <limits>
+using namespace llvm;
+
+namespace {
+
+TEST(PointerIntPairTest, GetSet) {
+ struct S {
+ int i;
+ };
+ S s;
+
+ PointerIntPair<S *, 2> Pair(&s, 1U);
+ EXPECT_EQ(&s, Pair.getPointer());
+ EXPECT_EQ(1U, Pair.getInt());
+
+ Pair.setInt(2);
+ EXPECT_EQ(&s, Pair.getPointer());
+ EXPECT_EQ(2U, Pair.getInt());
+
+ Pair.setPointer(nullptr);
+ EXPECT_EQ(nullptr, Pair.getPointer());
+ EXPECT_EQ(2U, Pair.getInt());
+
+ Pair.setPointerAndInt(&s, 3U);
+ EXPECT_EQ(&s, Pair.getPointer());
+ EXPECT_EQ(3U, Pair.getInt());
+
+ // Make sure that we can perform all of our operations on enum classes.
+ //
+ // The concern is that enum classes are only explicitly convertible to
+ // integers. This means that if we assume in PointerIntPair this, a
+ // compilation error will result. This group of tests exercises the enum class
+ // code to make sure that we do not run into such issues in the future.
+ enum class E : unsigned {
+ Case1,
+ Case2,
+ Case3,
+ };
+ PointerIntPair<S *, 2, E> Pair2(&s, E::Case1);
+ EXPECT_EQ(&s, Pair2.getPointer());
+ EXPECT_EQ(E::Case1, Pair2.getInt());
+
+ Pair2.setInt(E::Case2);
+ EXPECT_EQ(&s, Pair2.getPointer());
+ EXPECT_EQ(E::Case2, Pair2.getInt());
+
+ Pair2.setPointer(nullptr);
+ EXPECT_EQ(nullptr, Pair2.getPointer());
+ EXPECT_EQ(E::Case2, Pair2.getInt());
+
+ Pair2.setPointerAndInt(&s, E::Case3);
+ EXPECT_EQ(&s, Pair2.getPointer());
+ EXPECT_EQ(E::Case3, Pair2.getInt());
+}
+
+TEST(PointerIntPairTest, DefaultInitialize) {
+ PointerIntPair<float *, 2> Pair;
+ EXPECT_EQ(nullptr, Pair.getPointer());
+ EXPECT_EQ(0U, Pair.getInt());
+}
+
+TEST(PointerIntPairTest, ManyUnusedBits) {
+ // In real code this would be a word-sized integer limited to 31 bits.
+ struct Fixnum31 {
+ uintptr_t Value;
+ };
+ class FixnumPointerTraits {
+ public:
+ static inline void *getAsVoidPointer(Fixnum31 Num) {
+ return reinterpret_cast<void *>(Num.Value << NumLowBitsAvailable);
+ }
+ static inline Fixnum31 getFromVoidPointer(void *P) {
+ // In real code this would assert that the value is in range.
+ return { reinterpret_cast<uintptr_t>(P) >> NumLowBitsAvailable };
+ }
+ enum { NumLowBitsAvailable = std::numeric_limits<uintptr_t>::digits - 31 };
+ };
+
+ PointerIntPair<Fixnum31, 1, bool, FixnumPointerTraits> pair;
+ EXPECT_EQ((uintptr_t)0, pair.getPointer().Value);
+ EXPECT_FALSE(pair.getInt());
+
+ pair.setPointerAndInt({ 0x7FFFFFFF }, true );
+ EXPECT_EQ((uintptr_t)0x7FFFFFFF, pair.getPointer().Value);
+ EXPECT_TRUE(pair.getInt());
+
+ EXPECT_EQ(FixnumPointerTraits::NumLowBitsAvailable - 1,
+ PointerLikeTypeTraits<decltype(pair)>::NumLowBitsAvailable);
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/PointerSumTypeTest.cpp b/src/llvm-project/llvm/unittests/ADT/PointerSumTypeTest.cpp
new file mode 100644
index 0000000..a4faea6
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PointerSumTypeTest.cpp
@@ -0,0 +1,113 @@
+//===- llvm/unittest/ADT/PointerSumTypeTest.cpp ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/PointerSumType.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+struct PointerSumTypeTest : public testing::Test {
+ enum Kinds { Float, Int1, Int2 };
+ float f;
+ int i1, i2;
+
+ typedef PointerSumType<Kinds, PointerSumTypeMember<Float, float *>,
+ PointerSumTypeMember<Int1, int *>,
+ PointerSumTypeMember<Int2, int *>>
+ SumType;
+ SumType a, b, c, n;
+
+ PointerSumTypeTest()
+ : f(3.14f), i1(42), i2(-1), a(SumType::create<Float>(&f)),
+ b(SumType::create<Int1>(&i1)), c(SumType::create<Int2>(&i2)), n() {}
+};
+
+TEST_F(PointerSumTypeTest, NullTest) {
+ EXPECT_TRUE(a);
+ EXPECT_TRUE(b);
+ EXPECT_TRUE(c);
+ EXPECT_FALSE(n);
+}
+
+TEST_F(PointerSumTypeTest, GetTag) {
+ EXPECT_EQ(Float, a.getTag());
+ EXPECT_EQ(Int1, b.getTag());
+ EXPECT_EQ(Int2, c.getTag());
+ EXPECT_EQ((Kinds)0, n.getTag());
+}
+
+TEST_F(PointerSumTypeTest, Is) {
+ EXPECT_TRUE(a.is<Float>());
+ EXPECT_FALSE(a.is<Int1>());
+ EXPECT_FALSE(a.is<Int2>());
+ EXPECT_FALSE(b.is<Float>());
+ EXPECT_TRUE(b.is<Int1>());
+ EXPECT_FALSE(b.is<Int2>());
+ EXPECT_FALSE(c.is<Float>());
+ EXPECT_FALSE(c.is<Int1>());
+ EXPECT_TRUE(c.is<Int2>());
+}
+
+TEST_F(PointerSumTypeTest, Get) {
+ EXPECT_EQ(&f, a.get<Float>());
+ EXPECT_EQ(nullptr, a.get<Int1>());
+ EXPECT_EQ(nullptr, a.get<Int2>());
+ EXPECT_EQ(nullptr, b.get<Float>());
+ EXPECT_EQ(&i1, b.get<Int1>());
+ EXPECT_EQ(nullptr, b.get<Int2>());
+ EXPECT_EQ(nullptr, c.get<Float>());
+ EXPECT_EQ(nullptr, c.get<Int1>());
+ EXPECT_EQ(&i2, c.get<Int2>());
+
+ // Note that we can use .get even on a null sum type. It just always produces
+ // a null pointer, even if one of the discriminants is null.
+ EXPECT_EQ(nullptr, n.get<Float>());
+ EXPECT_EQ(nullptr, n.get<Int1>());
+ EXPECT_EQ(nullptr, n.get<Int2>());
+}
+
+TEST_F(PointerSumTypeTest, Cast) {
+ EXPECT_EQ(&f, a.cast<Float>());
+ EXPECT_EQ(&i1, b.cast<Int1>());
+ EXPECT_EQ(&i2, c.cast<Int2>());
+}
+
+TEST_F(PointerSumTypeTest, Assignment) {
+ b = SumType::create<Int2>(&i2);
+ EXPECT_EQ(nullptr, b.get<Float>());
+ EXPECT_EQ(nullptr, b.get<Int1>());
+ EXPECT_EQ(&i2, b.get<Int2>());
+
+ b = SumType::create<Int2>(&i1);
+ EXPECT_EQ(nullptr, b.get<Float>());
+ EXPECT_EQ(nullptr, b.get<Int1>());
+ EXPECT_EQ(&i1, b.get<Int2>());
+
+ float Local = 1.616f;
+ b = SumType::create<Float>(&Local);
+ EXPECT_EQ(&Local, b.get<Float>());
+ EXPECT_EQ(nullptr, b.get<Int1>());
+ EXPECT_EQ(nullptr, b.get<Int2>());
+
+ n = SumType::create<Int1>(&i2);
+ EXPECT_TRUE(n);
+ EXPECT_EQ(nullptr, n.get<Float>());
+ EXPECT_EQ(&i2, n.get<Int1>());
+ EXPECT_EQ(nullptr, n.get<Int2>());
+
+ n = SumType::create<Float>(nullptr);
+ EXPECT_FALSE(n);
+ EXPECT_EQ(nullptr, n.get<Float>());
+ EXPECT_EQ(nullptr, n.get<Int1>());
+ EXPECT_EQ(nullptr, n.get<Int2>());
+}
+
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/PointerUnionTest.cpp b/src/llvm-project/llvm/unittests/ADT/PointerUnionTest.cpp
new file mode 100644
index 0000000..360c371
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PointerUnionTest.cpp
@@ -0,0 +1,72 @@
+//===- llvm/unittest/ADT/PointerUnionTest.cpp - Optional unit tests -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/PointerUnion.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+typedef PointerUnion<int *, float *> PU;
+
+struct PointerUnionTest : public testing::Test {
+ float f;
+ int i;
+
+ PU a, b, c, n;
+
+ PointerUnionTest() : f(3.14f), i(42), a(&f), b(&i), c(&i), n() {}
+};
+
+TEST_F(PointerUnionTest, Comparison) {
+ EXPECT_TRUE(a == a);
+ EXPECT_FALSE(a != a);
+ EXPECT_TRUE(a != b);
+ EXPECT_FALSE(a == b);
+ EXPECT_TRUE(b == c);
+ EXPECT_FALSE(b != c);
+ EXPECT_TRUE(b != n);
+ EXPECT_FALSE(b == n);
+}
+
+TEST_F(PointerUnionTest, Null) {
+ EXPECT_FALSE(a.isNull());
+ EXPECT_FALSE(b.isNull());
+ EXPECT_TRUE(n.isNull());
+ EXPECT_FALSE(!a);
+ EXPECT_FALSE(!b);
+ EXPECT_TRUE(!n);
+ // workaround an issue with EXPECT macros and explicit bool
+ EXPECT_TRUE((bool)a);
+ EXPECT_TRUE((bool)b);
+ EXPECT_FALSE(n);
+
+ EXPECT_NE(n, b);
+ EXPECT_EQ(b, c);
+ b = nullptr;
+ EXPECT_EQ(n, b);
+ EXPECT_NE(b, c);
+}
+
+TEST_F(PointerUnionTest, Is) {
+ EXPECT_FALSE(a.is<int *>());
+ EXPECT_TRUE(a.is<float *>());
+ EXPECT_TRUE(b.is<int *>());
+ EXPECT_FALSE(b.is<float *>());
+ EXPECT_TRUE(n.is<int *>());
+ EXPECT_FALSE(n.is<float *>());
+}
+
+TEST_F(PointerUnionTest, Get) {
+ EXPECT_EQ(a.get<float *>(), &f);
+ EXPECT_EQ(b.get<int *>(), &i);
+ EXPECT_EQ(n.get<int *>(), (int *)nullptr);
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/PostOrderIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/PostOrderIteratorTest.cpp
new file mode 100644
index 0000000..20c938e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PostOrderIteratorTest.cpp
@@ -0,0 +1,37 @@
+//===- PostOrderIteratorTest.cpp - PostOrderIterator unit tests -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CFG.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+// Whether we're able to compile
+TEST(PostOrderIteratorTest, Compiles) {
+ typedef SmallPtrSet<void *, 4> ExtSetTy;
+
+ // Tests that template specializations are kept up to date
+ void *Null = nullptr;
+ po_iterator_storage<std::set<void *>, false> PIS;
+ PIS.insertEdge(Optional<void *>(), Null);
+ ExtSetTy Ext;
+ po_iterator_storage<ExtSetTy, true> PISExt(Ext);
+ PIS.insertEdge(Optional<void *>(), Null);
+
+ // Test above, but going through po_iterator (which inherits from template
+ // base)
+ BasicBlock *NullBB = nullptr;
+ auto PI = po_end(NullBB);
+ PI.insertEdge(Optional<BasicBlock *>(), NullBB);
+ auto PIExt = po_ext_end(NullBB, Ext);
+ PIExt.insertEdge(Optional<BasicBlock *>(), NullBB);
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/PriorityWorklistTest.cpp b/src/llvm-project/llvm/unittests/ADT/PriorityWorklistTest.cpp
new file mode 100644
index 0000000..040a11f
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/PriorityWorklistTest.cpp
@@ -0,0 +1,153 @@
+//===- llvm/unittest/ADT/PriorityWorklist.cpp -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// PriorityWorklist unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/PriorityWorklist.h"
+#include "gtest/gtest.h"
+#include <list>
+#include <vector>
+
+namespace {
+
+using namespace llvm;
+
+template <typename T> class PriorityWorklistTest : public ::testing::Test {};
+typedef ::testing::Types<PriorityWorklist<int>, SmallPriorityWorklist<int, 2>>
+ TestTypes;
+TYPED_TEST_CASE(PriorityWorklistTest, TestTypes);
+
+TYPED_TEST(PriorityWorklistTest, Basic) {
+ TypeParam W;
+ EXPECT_TRUE(W.empty());
+ EXPECT_EQ(0u, W.size());
+ EXPECT_FALSE(W.count(42));
+
+ EXPECT_TRUE(W.insert(21));
+ EXPECT_TRUE(W.insert(42));
+ EXPECT_TRUE(W.insert(17));
+
+ EXPECT_FALSE(W.empty());
+ EXPECT_EQ(3u, W.size());
+ EXPECT_TRUE(W.count(42));
+
+ EXPECT_FALSE(W.erase(75));
+ EXPECT_EQ(3u, W.size());
+ EXPECT_EQ(17, W.back());
+
+ EXPECT_TRUE(W.erase(17));
+ EXPECT_FALSE(W.count(17));
+ EXPECT_EQ(2u, W.size());
+ EXPECT_EQ(42, W.back());
+
+ W.clear();
+ EXPECT_TRUE(W.empty());
+ EXPECT_EQ(0u, W.size());
+
+ EXPECT_TRUE(W.insert(21));
+ EXPECT_TRUE(W.insert(42));
+ EXPECT_TRUE(W.insert(12));
+ EXPECT_TRUE(W.insert(17));
+ EXPECT_TRUE(W.count(12));
+ EXPECT_TRUE(W.count(17));
+ EXPECT_EQ(4u, W.size());
+ EXPECT_EQ(17, W.back());
+ EXPECT_TRUE(W.erase(12));
+ EXPECT_FALSE(W.count(12));
+ EXPECT_TRUE(W.count(17));
+ EXPECT_EQ(3u, W.size());
+ EXPECT_EQ(17, W.back());
+
+ EXPECT_FALSE(W.insert(42));
+ EXPECT_EQ(3u, W.size());
+ EXPECT_EQ(42, W.pop_back_val());
+ EXPECT_EQ(17, W.pop_back_val());
+ EXPECT_EQ(21, W.pop_back_val());
+ EXPECT_TRUE(W.empty());
+}
+
+TYPED_TEST(PriorityWorklistTest, InsertSequence) {
+ TypeParam W;
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(4));
+ ASSERT_TRUE(W.insert(7));
+ // Insert a sequence that has internal duplicates and a duplicate among
+ // existing entries.
+ W.insert(std::vector<int>({42, 13, 42, 7, 8}));
+ EXPECT_EQ(8, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(42, W.pop_back_val());
+ EXPECT_EQ(13, W.pop_back_val());
+ EXPECT_EQ(4, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+
+ // Simpler tests with various other input types.
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(7));
+ // Use a non-random-access container.
+ W.insert(std::list<int>({7, 5}));
+ EXPECT_EQ(5, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(7));
+ // Use a raw array.
+ int A[] = {7, 5};
+ W.insert(A);
+ EXPECT_EQ(5, W.pop_back_val());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+
+ ASSERT_TRUE(W.insert(2));
+ ASSERT_TRUE(W.insert(7));
+ // Inserting an empty sequence does nothing.
+ W.insert(std::vector<int>());
+ EXPECT_EQ(7, W.pop_back_val());
+ EXPECT_EQ(2, W.pop_back_val());
+ ASSERT_TRUE(W.empty());
+}
+
+TYPED_TEST(PriorityWorklistTest, EraseIf) {
+ TypeParam W;
+ W.insert(23);
+ W.insert(10);
+ W.insert(47);
+ W.insert(42);
+ W.insert(23);
+ W.insert(13);
+ W.insert(26);
+ W.insert(42);
+ EXPECT_EQ(6u, W.size());
+
+ EXPECT_FALSE(W.erase_if([](int i) { return i > 100; }));
+ EXPECT_EQ(6u, W.size());
+ EXPECT_EQ(42, W.back());
+
+ EXPECT_TRUE(W.erase_if([](int i) {
+ assert(i != 0 && "Saw a null value!");
+ return (i & 1) == 0;
+ }));
+ EXPECT_EQ(3u, W.size());
+ EXPECT_FALSE(W.count(42));
+ EXPECT_FALSE(W.count(26));
+ EXPECT_FALSE(W.count(10));
+ EXPECT_FALSE(W.insert(47));
+ EXPECT_FALSE(W.insert(23));
+ EXPECT_EQ(23, W.pop_back_val());
+ EXPECT_EQ(47, W.pop_back_val());
+ EXPECT_EQ(13, W.pop_back_val());
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/RangeAdapterTest.cpp b/src/llvm-project/llvm/unittests/ADT/RangeAdapterTest.cpp
new file mode 100644
index 0000000..edc1ced
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/RangeAdapterTest.cpp
@@ -0,0 +1,172 @@
+//===- RangeAdapterTest.cpp - Unit tests for range adapters --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/iterator_range.h"
+#include "gtest/gtest.h"
+
+#include <iterator>
+#include <list>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+// A wrapper around vector which exposes rbegin(), rend().
+class ReverseOnlyVector {
+ std::vector<int> Vec;
+
+public:
+ ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {}
+
+ typedef std::vector<int>::reverse_iterator reverse_iterator;
+ typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
+ reverse_iterator rbegin() { return Vec.rbegin(); }
+ reverse_iterator rend() { return Vec.rend(); }
+ const_reverse_iterator rbegin() const { return Vec.rbegin(); }
+ const_reverse_iterator rend() const { return Vec.rend(); }
+};
+
+// A wrapper around vector which exposes begin(), end(), rbegin() and rend().
+// begin() and end() don't have implementations as this ensures that we will
+// get a linker error if reverse() chooses begin()/end() over rbegin(), rend().
+class BidirectionalVector {
+ mutable std::vector<int> Vec;
+
+public:
+ BidirectionalVector(std::initializer_list<int> list) : Vec(list) {}
+
+ typedef std::vector<int>::iterator iterator;
+ iterator begin() const;
+ iterator end() const;
+
+ typedef std::vector<int>::reverse_iterator reverse_iterator;
+ reverse_iterator rbegin() const { return Vec.rbegin(); }
+ reverse_iterator rend() const { return Vec.rend(); }
+};
+
+/// This is the same as BidirectionalVector but with the addition of const
+/// begin/rbegin methods to ensure that the type traits for has_rbegin works.
+class BidirectionalVectorConsts {
+ std::vector<int> Vec;
+
+public:
+ BidirectionalVectorConsts(std::initializer_list<int> list) : Vec(list) {}
+
+ typedef std::vector<int>::iterator iterator;
+ typedef std::vector<int>::const_iterator const_iterator;
+ iterator begin();
+ iterator end();
+ const_iterator begin() const;
+ const_iterator end() const;
+
+ typedef std::vector<int>::reverse_iterator reverse_iterator;
+ typedef std::vector<int>::const_reverse_iterator const_reverse_iterator;
+ reverse_iterator rbegin() { return Vec.rbegin(); }
+ reverse_iterator rend() { return Vec.rend(); }
+ const_reverse_iterator rbegin() const { return Vec.rbegin(); }
+ const_reverse_iterator rend() const { return Vec.rend(); }
+};
+
+/// Check that types with custom iterators work.
+class CustomIteratorVector {
+ mutable std::vector<int> V;
+
+public:
+ CustomIteratorVector(std::initializer_list<int> list) : V(list) {}
+
+ typedef std::vector<int>::iterator iterator;
+ class reverse_iterator {
+ std::vector<int>::iterator I;
+
+ public:
+ reverse_iterator() = default;
+ reverse_iterator(const reverse_iterator &) = default;
+ reverse_iterator &operator=(const reverse_iterator &) = default;
+
+ explicit reverse_iterator(std::vector<int>::iterator I) : I(I) {}
+
+ reverse_iterator &operator++() {
+ --I;
+ return *this;
+ }
+ reverse_iterator &operator--() {
+ ++I;
+ return *this;
+ }
+ int &operator*() const { return *std::prev(I); }
+ int *operator->() const { return &*std::prev(I); }
+ friend bool operator==(const reverse_iterator &L,
+ const reverse_iterator &R) {
+ return L.I == R.I;
+ }
+ friend bool operator!=(const reverse_iterator &L,
+ const reverse_iterator &R) {
+ return !(L == R);
+ }
+ };
+
+ iterator begin() const { return V.begin(); }
+ iterator end() const { return V.end(); }
+ reverse_iterator rbegin() const { return reverse_iterator(V.end()); }
+ reverse_iterator rend() const { return reverse_iterator(V.begin()); }
+};
+
+template <typename R> void TestRev(const R &r) {
+ int counter = 3;
+ for (int i : r)
+ EXPECT_EQ(i, counter--);
+}
+
+// Test fixture
+template <typename T> class RangeAdapterLValueTest : public ::testing::Test {};
+
+typedef ::testing::Types<std::vector<int>, std::list<int>, int[4]>
+ RangeAdapterLValueTestTypes;
+TYPED_TEST_CASE(RangeAdapterLValueTest, RangeAdapterLValueTestTypes);
+
+TYPED_TEST(RangeAdapterLValueTest, TrivialOperation) {
+ TypeParam v = {0, 1, 2, 3};
+ TestRev(reverse(v));
+
+ const TypeParam c = {0, 1, 2, 3};
+ TestRev(reverse(c));
+}
+
+template <typename T> struct RangeAdapterRValueTest : testing::Test {};
+
+typedef ::testing::Types<std::vector<int>, std::list<int>, CustomIteratorVector,
+ ReverseOnlyVector, BidirectionalVector,
+ BidirectionalVectorConsts>
+ RangeAdapterRValueTestTypes;
+TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes);
+
+TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {
+ TestRev(reverse(TypeParam({0, 1, 2, 3})));
+}
+
+TYPED_TEST(RangeAdapterRValueTest, HasRbegin) {
+ static_assert(has_rbegin<TypeParam>::value, "rbegin() should be defined");
+}
+
+TYPED_TEST(RangeAdapterRValueTest, RangeType) {
+ static_assert(
+ std::is_same<
+ decltype(reverse(*static_cast<TypeParam *>(nullptr)).begin()),
+ decltype(static_cast<TypeParam *>(nullptr)->rbegin())>::value,
+ "reverse().begin() should have the same type as rbegin()");
+ static_assert(
+ std::is_same<
+ decltype(reverse(*static_cast<const TypeParam *>(nullptr)).begin()),
+ decltype(static_cast<const TypeParam *>(nullptr)->rbegin())>::value,
+ "reverse().begin() should have the same type as rbegin() [const]");
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SCCIteratorTest.cpp b/src/llvm-project/llvm/unittests/ADT/SCCIteratorTest.cpp
new file mode 100644
index 0000000..57a999b
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SCCIteratorTest.cpp
@@ -0,0 +1,121 @@
+//===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SCCIterator.h"
+#include "TestGraph.h"
+#include "gtest/gtest.h"
+#include <limits.h>
+
+using namespace llvm;
+
+namespace llvm {
+
+TEST(SCCIteratorTest, AllSmallGraphs) {
+ // Test SCC computation against every graph with NUM_NODES nodes or less.
+ // Since SCC considers every node to have an implicit self-edge, we only
+ // create graphs for which every node has a self-edge.
+#define NUM_NODES 4
+#define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))
+ typedef Graph<NUM_NODES> GT;
+
+ /// Enumerate all graphs using NUM_GRAPHS bits.
+ static_assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT, "Too many graphs!");
+ for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS);
+ ++GraphDescriptor) {
+ GT G;
+
+ // Add edges as specified by the descriptor.
+ unsigned DescriptorCopy = GraphDescriptor;
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ for (unsigned j = 0; j != NUM_NODES; ++j) {
+ // Always add a self-edge.
+ if (i == j) {
+ G.AddEdge(i, j);
+ continue;
+ }
+ if (DescriptorCopy & 1)
+ G.AddEdge(i, j);
+ DescriptorCopy >>= 1;
+ }
+
+ // Test the SCC logic on this graph.
+
+ /// NodesInSomeSCC - Those nodes which are in some SCC.
+ GT::NodeSubset NodesInSomeSCC;
+
+ for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
+ const std::vector<GT::NodeType *> &SCC = *I;
+
+ // Get the nodes in this SCC as a NodeSubset rather than a vector.
+ GT::NodeSubset NodesInThisSCC;
+ for (unsigned i = 0, e = SCC.size(); i != e; ++i)
+ NodesInThisSCC.AddNode(SCC[i]->first);
+
+ // There should be at least one node in every SCC.
+ EXPECT_FALSE(NodesInThisSCC.isEmpty());
+
+ // Check that every node in the SCC is reachable from every other node in
+ // the SCC.
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i)) {
+ EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));
+ }
+
+ // OK, now that we now that every node in the SCC is reachable from every
+ // other, this means that the set of nodes reachable from any node in the
+ // SCC is the same as the set of nodes reachable from every node in the
+ // SCC. Check that for every node N not in the SCC but reachable from the
+ // SCC, no element of the SCC is reachable from N.
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i)) {
+ GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
+ GT::NodeSubset ReachableButNotInSCC =
+ NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());
+
+ for (unsigned j = 0; j != NUM_NODES; ++j)
+ if (ReachableButNotInSCC.count(j)) {
+ EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());
+ }
+
+ // The result must be the same for all other nodes in this SCC, so
+ // there is no point in checking them.
+ break;
+ }
+
+ // This is indeed a SCC: a maximal set of nodes for which each node is
+ // reachable from every other.
+
+ // Check that we didn't already see this SCC.
+ EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty());
+
+ NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC);
+
+ // Check a property that is specific to the LLVM SCC iterator and
+ // guaranteed by it: if a node in SCC S1 has an edge to a node in
+ // SCC S2, then S1 is visited *after* S2. This means that the set
+ // of nodes reachable from this SCC must be contained either in the
+ // union of this SCC and all previously visited SCC's.
+
+ for (unsigned i = 0; i != NUM_NODES; ++i)
+ if (NodesInThisSCC.count(i)) {
+ GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
+ EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC));
+ // The result must be the same for all other nodes in this SCC, so
+ // there is no point in checking them.
+ break;
+ }
+ }
+
+ // Finally, check that the nodes in some SCC are exactly those that are
+ // reachable from the initial node.
+ EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0));
+ }
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/STLExtrasTest.cpp b/src/llvm-project/llvm/unittests/ADT/STLExtrasTest.cpp
new file mode 100644
index 0000000..e65e71f
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/STLExtrasTest.cpp
@@ -0,0 +1,450 @@
+//===- STLExtrasTest.cpp - Unit tests for STL extras ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "gtest/gtest.h"
+
+#include <list>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+int f(rank<0>) { return 0; }
+int f(rank<1>) { return 1; }
+int f(rank<2>) { return 2; }
+int f(rank<4>) { return 4; }
+
+TEST(STLExtrasTest, Rank) {
+ // We shouldn't get ambiguities and should select the overload of the same
+ // rank as the argument.
+ EXPECT_EQ(0, f(rank<0>()));
+ EXPECT_EQ(1, f(rank<1>()));
+ EXPECT_EQ(2, f(rank<2>()));
+
+ // This overload is missing so we end up back at 2.
+ EXPECT_EQ(2, f(rank<3>()));
+
+ // But going past 3 should work fine.
+ EXPECT_EQ(4, f(rank<4>()));
+
+ // And we can even go higher and just fall back to the last overload.
+ EXPECT_EQ(4, f(rank<5>()));
+ EXPECT_EQ(4, f(rank<6>()));
+}
+
+TEST(STLExtrasTest, EnumerateLValue) {
+ // Test that a simple LValue can be enumerated and gives correct results with
+ // multiple types, including the empty container.
+ std::vector<char> foo = {'a', 'b', 'c'};
+ typedef std::pair<std::size_t, char> CharPairType;
+ std::vector<CharPairType> CharResults;
+
+ for (auto X : llvm::enumerate(foo)) {
+ CharResults.emplace_back(X.index(), X.value());
+ }
+ ASSERT_EQ(3u, CharResults.size());
+ EXPECT_EQ(CharPairType(0u, 'a'), CharResults[0]);
+ EXPECT_EQ(CharPairType(1u, 'b'), CharResults[1]);
+ EXPECT_EQ(CharPairType(2u, 'c'), CharResults[2]);
+
+ // Test a const range of a different type.
+ typedef std::pair<std::size_t, int> IntPairType;
+ std::vector<IntPairType> IntResults;
+ const std::vector<int> bar = {1, 2, 3};
+ for (auto X : llvm::enumerate(bar)) {
+ IntResults.emplace_back(X.index(), X.value());
+ }
+ ASSERT_EQ(3u, IntResults.size());
+ EXPECT_EQ(IntPairType(0u, 1), IntResults[0]);
+ EXPECT_EQ(IntPairType(1u, 2), IntResults[1]);
+ EXPECT_EQ(IntPairType(2u, 3), IntResults[2]);
+
+ // Test an empty range.
+ IntResults.clear();
+ const std::vector<int> baz{};
+ for (auto X : llvm::enumerate(baz)) {
+ IntResults.emplace_back(X.index(), X.value());
+ }
+ EXPECT_TRUE(IntResults.empty());
+}
+
+TEST(STLExtrasTest, EnumerateModifyLValue) {
+ // Test that you can modify the underlying entries of an lvalue range through
+ // the enumeration iterator.
+ std::vector<char> foo = {'a', 'b', 'c'};
+
+ for (auto X : llvm::enumerate(foo)) {
+ ++X.value();
+ }
+ EXPECT_EQ('b', foo[0]);
+ EXPECT_EQ('c', foo[1]);
+ EXPECT_EQ('d', foo[2]);
+}
+
+TEST(STLExtrasTest, EnumerateRValueRef) {
+ // Test that an rvalue can be enumerated.
+ typedef std::pair<std::size_t, int> PairType;
+ std::vector<PairType> Results;
+
+ auto Enumerator = llvm::enumerate(std::vector<int>{1, 2, 3});
+
+ for (auto X : llvm::enumerate(std::vector<int>{1, 2, 3})) {
+ Results.emplace_back(X.index(), X.value());
+ }
+
+ ASSERT_EQ(3u, Results.size());
+ EXPECT_EQ(PairType(0u, 1), Results[0]);
+ EXPECT_EQ(PairType(1u, 2), Results[1]);
+ EXPECT_EQ(PairType(2u, 3), Results[2]);
+}
+
+TEST(STLExtrasTest, EnumerateModifyRValue) {
+ // Test that when enumerating an rvalue, modification still works (even if
+ // this isn't terribly useful, it at least shows that we haven't snuck an
+ // extra const in there somewhere.
+ typedef std::pair<std::size_t, char> PairType;
+ std::vector<PairType> Results;
+
+ for (auto X : llvm::enumerate(std::vector<char>{'1', '2', '3'})) {
+ ++X.value();
+ Results.emplace_back(X.index(), X.value());
+ }
+
+ ASSERT_EQ(3u, Results.size());
+ EXPECT_EQ(PairType(0u, '2'), Results[0]);
+ EXPECT_EQ(PairType(1u, '3'), Results[1]);
+ EXPECT_EQ(PairType(2u, '4'), Results[2]);
+}
+
+template <bool B> struct CanMove {};
+template <> struct CanMove<false> {
+ CanMove(CanMove &&) = delete;
+
+ CanMove() = default;
+ CanMove(const CanMove &) = default;
+};
+
+template <bool B> struct CanCopy {};
+template <> struct CanCopy<false> {
+ CanCopy(const CanCopy &) = delete;
+
+ CanCopy() = default;
+ CanCopy(CanCopy &&) = default;
+};
+
+template <bool Moveable, bool Copyable>
+struct Range : CanMove<Moveable>, CanCopy<Copyable> {
+ explicit Range(int &C, int &M, int &D) : C(C), M(M), D(D) {}
+ Range(const Range &R) : CanCopy<Copyable>(R), C(R.C), M(R.M), D(R.D) { ++C; }
+ Range(Range &&R) : CanMove<Moveable>(std::move(R)), C(R.C), M(R.M), D(R.D) {
+ ++M;
+ }
+ ~Range() { ++D; }
+
+ int &C;
+ int &M;
+ int &D;
+
+ int *begin() { return nullptr; }
+ int *end() { return nullptr; }
+};
+
+TEST(STLExtrasTest, EnumerateLifetimeSemantics) {
+ // Test that when enumerating lvalues and rvalues, there are no surprise
+ // copies or moves.
+
+ // With an rvalue, it should not be destroyed until the end of the scope.
+ int Copies = 0;
+ int Moves = 0;
+ int Destructors = 0;
+ {
+ auto E1 = enumerate(Range<true, false>(Copies, Moves, Destructors));
+ // Doesn't compile. rvalue ranges must be moveable.
+ // auto E2 = enumerate(Range<false, true>(Copies, Moves, Destructors));
+ EXPECT_EQ(0, Copies);
+ EXPECT_EQ(1, Moves);
+ EXPECT_EQ(1, Destructors);
+ }
+ EXPECT_EQ(0, Copies);
+ EXPECT_EQ(1, Moves);
+ EXPECT_EQ(2, Destructors);
+
+ Copies = Moves = Destructors = 0;
+ // With an lvalue, it should not be destroyed even after the end of the scope.
+ // lvalue ranges need be neither copyable nor moveable.
+ Range<false, false> R(Copies, Moves, Destructors);
+ {
+ auto Enumerator = enumerate(R);
+ (void)Enumerator;
+ EXPECT_EQ(0, Copies);
+ EXPECT_EQ(0, Moves);
+ EXPECT_EQ(0, Destructors);
+ }
+ EXPECT_EQ(0, Copies);
+ EXPECT_EQ(0, Moves);
+ EXPECT_EQ(0, Destructors);
+}
+
+TEST(STLExtrasTest, ApplyTuple) {
+ auto T = std::make_tuple(1, 3, 7);
+ auto U = llvm::apply_tuple(
+ [](int A, int B, int C) { return std::make_tuple(A - B, B - C, C - A); },
+ T);
+
+ EXPECT_EQ(-2, std::get<0>(U));
+ EXPECT_EQ(-4, std::get<1>(U));
+ EXPECT_EQ(6, std::get<2>(U));
+
+ auto V = llvm::apply_tuple(
+ [](int A, int B, int C) {
+ return std::make_tuple(std::make_pair(A, char('A' + A)),
+ std::make_pair(B, char('A' + B)),
+ std::make_pair(C, char('A' + C)));
+ },
+ T);
+
+ EXPECT_EQ(std::make_pair(1, 'B'), std::get<0>(V));
+ EXPECT_EQ(std::make_pair(3, 'D'), std::get<1>(V));
+ EXPECT_EQ(std::make_pair(7, 'H'), std::get<2>(V));
+}
+
+class apply_variadic {
+ static int apply_one(int X) { return X + 1; }
+ static char apply_one(char C) { return C + 1; }
+ static StringRef apply_one(StringRef S) { return S.drop_back(); }
+
+public:
+ template <typename... Ts>
+ auto operator()(Ts &&... Items)
+ -> decltype(std::make_tuple(apply_one(Items)...)) {
+ return std::make_tuple(apply_one(Items)...);
+ }
+};
+
+TEST(STLExtrasTest, ApplyTupleVariadic) {
+ auto Items = std::make_tuple(1, llvm::StringRef("Test"), 'X');
+ auto Values = apply_tuple(apply_variadic(), Items);
+
+ EXPECT_EQ(2, std::get<0>(Values));
+ EXPECT_EQ("Tes", std::get<1>(Values));
+ EXPECT_EQ('Y', std::get<2>(Values));
+}
+
+TEST(STLExtrasTest, CountAdaptor) {
+ std::vector<int> v;
+
+ v.push_back(1);
+ v.push_back(2);
+ v.push_back(1);
+ v.push_back(4);
+ v.push_back(3);
+ v.push_back(2);
+ v.push_back(1);
+
+ EXPECT_EQ(3, count(v, 1));
+ EXPECT_EQ(2, count(v, 2));
+ EXPECT_EQ(1, count(v, 3));
+ EXPECT_EQ(1, count(v, 4));
+}
+
+TEST(STLExtrasTest, for_each) {
+ std::vector<int> v{0, 1, 2, 3, 4};
+ int count = 0;
+
+ llvm::for_each(v, [&count](int) { ++count; });
+ EXPECT_EQ(5, count);
+}
+
+TEST(STLExtrasTest, ToVector) {
+ std::vector<char> v = {'a', 'b', 'c'};
+ auto Enumerated = to_vector<4>(enumerate(v));
+ ASSERT_EQ(3u, Enumerated.size());
+ for (size_t I = 0; I < v.size(); ++I) {
+ EXPECT_EQ(I, Enumerated[I].index());
+ EXPECT_EQ(v[I], Enumerated[I].value());
+ }
+}
+
+TEST(STLExtrasTest, ConcatRange) {
+ std::vector<int> Expected = {1, 2, 3, 4, 5, 6, 7, 8};
+ std::vector<int> Test;
+
+ std::vector<int> V1234 = {1, 2, 3, 4};
+ std::list<int> L56 = {5, 6};
+ SmallVector<int, 2> SV78 = {7, 8};
+
+ // Use concat across different sized ranges of different types with different
+ // iterators.
+ for (int &i : concat<int>(V1234, L56, SV78))
+ Test.push_back(i);
+ EXPECT_EQ(Expected, Test);
+
+ // Use concat between a temporary, an L-value, and an R-value to make sure
+ // complex lifetimes work well.
+ Test.clear();
+ for (int &i : concat<int>(std::vector<int>(V1234), L56, std::move(SV78)))
+ Test.push_back(i);
+ EXPECT_EQ(Expected, Test);
+}
+
+TEST(STLExtrasTest, PartitionAdaptor) {
+ std::vector<int> V = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ auto I = partition(V, [](int i) { return i % 2 == 0; });
+ ASSERT_EQ(V.begin() + 4, I);
+
+ // Sort the two halves as partition may have messed with the order.
+ llvm::sort(V.begin(), I);
+ llvm::sort(I, V.end());
+
+ EXPECT_EQ(2, V[0]);
+ EXPECT_EQ(4, V[1]);
+ EXPECT_EQ(6, V[2]);
+ EXPECT_EQ(8, V[3]);
+ EXPECT_EQ(1, V[4]);
+ EXPECT_EQ(3, V[5]);
+ EXPECT_EQ(5, V[6]);
+ EXPECT_EQ(7, V[7]);
+}
+
+TEST(STLExtrasTest, EraseIf) {
+ std::vector<int> V = {1, 2, 3, 4, 5, 6, 7, 8};
+
+ erase_if(V, [](int i) { return i % 2 == 0; });
+ EXPECT_EQ(4u, V.size());
+ EXPECT_EQ(1, V[0]);
+ EXPECT_EQ(3, V[1]);
+ EXPECT_EQ(5, V[2]);
+ EXPECT_EQ(7, V[3]);
+}
+
+namespace some_namespace {
+struct some_struct {
+ std::vector<int> data;
+ std::string swap_val;
+};
+
+std::vector<int>::const_iterator begin(const some_struct &s) {
+ return s.data.begin();
+}
+
+std::vector<int>::const_iterator end(const some_struct &s) {
+ return s.data.end();
+}
+
+void swap(some_struct &lhs, some_struct &rhs) {
+ // make swap visible as non-adl swap would even seem to
+ // work with std::swap which defaults to moving
+ lhs.swap_val = "lhs";
+ rhs.swap_val = "rhs";
+}
+} // namespace some_namespace
+
+TEST(STLExtrasTest, ADLTest) {
+ some_namespace::some_struct s{{1, 2, 3, 4, 5}, ""};
+ some_namespace::some_struct s2{{2, 4, 6, 8, 10}, ""};
+
+ EXPECT_EQ(*adl_begin(s), 1);
+ EXPECT_EQ(*(adl_end(s) - 1), 5);
+
+ adl_swap(s, s2);
+ EXPECT_EQ(s.swap_val, "lhs");
+ EXPECT_EQ(s2.swap_val, "rhs");
+
+ int count = 0;
+ llvm::for_each(s, [&count](int) { ++count; });
+ EXPECT_EQ(5, count);
+}
+
+TEST(STLExtrasTest, EmptyTest) {
+ std::vector<void*> V;
+ EXPECT_TRUE(llvm::empty(V));
+ V.push_back(nullptr);
+ EXPECT_FALSE(llvm::empty(V));
+
+ std::initializer_list<int> E = {};
+ std::initializer_list<int> NotE = {7, 13, 42};
+ EXPECT_TRUE(llvm::empty(E));
+ EXPECT_FALSE(llvm::empty(NotE));
+
+ auto R0 = make_range(V.begin(), V.begin());
+ EXPECT_TRUE(llvm::empty(R0));
+ auto R1 = make_range(V.begin(), V.end());
+ EXPECT_FALSE(llvm::empty(R1));
+}
+
+TEST(STLExtrasTest, EarlyIncrementTest) {
+ std::list<int> L = {1, 2, 3, 4};
+
+ auto EIR = make_early_inc_range(L);
+
+ auto I = EIR.begin();
+ auto EI = EIR.end();
+ EXPECT_NE(I, EI);
+
+ EXPECT_EQ(1, *I);
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+#ifndef NDEBUG
+ // Repeated dereferences are not allowed.
+ EXPECT_DEATH(*I, "Cannot dereference");
+ // Comparison after dereference is not allowed.
+ EXPECT_DEATH((void)(I == EI), "Cannot compare");
+ EXPECT_DEATH((void)(I != EI), "Cannot compare");
+#endif
+#endif
+
+ ++I;
+ EXPECT_NE(I, EI);
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+#ifndef NDEBUG
+ // You cannot increment prior to dereference.
+ EXPECT_DEATH(++I, "Cannot increment");
+#endif
+#endif
+ EXPECT_EQ(2, *I);
+#if LLVM_ENABLE_ABI_BREAKING_CHECKS
+#ifndef NDEBUG
+ // Repeated dereferences are not allowed.
+ EXPECT_DEATH(*I, "Cannot dereference");
+#endif
+#endif
+
+ // Inserting shouldn't break anything. We should be able to keep dereferencing
+ // the currrent iterator and increment. The increment to go to the "next"
+ // iterator from before we inserted.
+ L.insert(std::next(L.begin(), 2), -1);
+ ++I;
+ EXPECT_EQ(3, *I);
+
+ // Erasing the front including the current doesn't break incrementing.
+ L.erase(L.begin(), std::prev(L.end()));
+ ++I;
+ EXPECT_EQ(4, *I);
+ ++I;
+ EXPECT_EQ(EIR.end(), I);
+}
+
+TEST(STLExtrasTest, splat) {
+ std::vector<int> V;
+ EXPECT_FALSE(is_splat(V));
+
+ V.push_back(1);
+ EXPECT_TRUE(is_splat(V));
+
+ V.push_back(1);
+ V.push_back(1);
+ EXPECT_TRUE(is_splat(V));
+
+ V.push_back(2);
+ EXPECT_FALSE(is_splat(V));
+}
+
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/ScopeExitTest.cpp b/src/llvm-project/llvm/unittests/ADT/ScopeExitTest.cpp
new file mode 100644
index 0000000..ab11dff
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/ScopeExitTest.cpp
@@ -0,0 +1,49 @@
+//===- llvm/unittest/ADT/ScopeExit.cpp - Scope exit unit tests --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ScopeExit.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(ScopeExitTest, Basic) {
+ struct Callable {
+ bool &Called;
+ Callable(bool &Called) : Called(Called) {}
+ Callable(Callable &&RHS) : Called(RHS.Called) {}
+ void operator()() { Called = true; }
+ };
+ bool Called = false;
+ {
+ auto g = make_scope_exit(Callable(Called));
+ EXPECT_FALSE(Called);
+ }
+ EXPECT_TRUE(Called);
+}
+
+TEST(ScopeExitTest, Release) {
+ int Count = 0;
+ auto Increment = [&] { ++Count; };
+ {
+ auto G = make_scope_exit(Increment);
+ auto H = std::move(G);
+ auto I = std::move(G);
+ EXPECT_EQ(0, Count);
+ }
+ EXPECT_EQ(1, Count);
+ {
+ auto G = make_scope_exit(Increment);
+ G.release();
+ }
+ EXPECT_EQ(1, Count);
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SequenceTest.cpp b/src/llvm-project/llvm/unittests/ADT/SequenceTest.cpp
new file mode 100644
index 0000000..cc82f86
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SequenceTest.cpp
@@ -0,0 +1,41 @@
+//===- SequenceTest.cpp - Unit tests for a sequence abstraciton -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Sequence.h"
+#include "gtest/gtest.h"
+
+#include <list>
+
+using namespace llvm;
+
+namespace {
+
+TEST(SequenceTest, Basic) {
+ int x = 0;
+ for (int i : seq(0, 10)) {
+ EXPECT_EQ(x, i);
+ x++;
+ }
+ EXPECT_EQ(10, x);
+
+ auto my_seq = seq(0, 4);
+ EXPECT_EQ(4, my_seq.end() - my_seq.begin());
+ for (int i : {0, 1, 2, 3})
+ EXPECT_EQ(i, (int)my_seq.begin()[i]);
+
+ EXPECT_TRUE(my_seq.begin() < my_seq.end());
+
+ auto adjusted_begin = my_seq.begin() + 2;
+ auto adjusted_end = my_seq.end() - 2;
+ EXPECT_TRUE(adjusted_begin == adjusted_end);
+ EXPECT_EQ(2, *adjusted_begin);
+ EXPECT_EQ(2, *adjusted_end);
+}
+
+} // anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SetVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/SetVectorTest.cpp
new file mode 100644
index 0000000..b8cac0d
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SetVectorTest.cpp
@@ -0,0 +1,34 @@
+//===- llvm/unittest/ADT/SetVector.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SetVector unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SetVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(SetVector, EraseTest) {
+ SetVector<int> S;
+ S.insert(0);
+ S.insert(1);
+ S.insert(2);
+
+ auto I = S.erase(std::next(S.begin()));
+
+ // Test that the returned iterator is the expected one-after-erase
+ // and the size/contents is the expected sequence {0, 2}.
+ EXPECT_EQ(std::next(S.begin()), I);
+ EXPECT_EQ(2u, S.size());
+ EXPECT_EQ(0, *S.begin());
+ EXPECT_EQ(2, *std::next(S.begin()));
+}
+
diff --git a/src/llvm-project/llvm/unittests/ADT/SimpleIListTest.cpp b/src/llvm-project/llvm/unittests/ADT/SimpleIListTest.cpp
new file mode 100644
index 0000000..a354f33
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SimpleIListTest.cpp
@@ -0,0 +1,654 @@
+//===- unittests/ADT/SimpleIListTest.cpp - simple_ilist unit tests --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/simple_ilist.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+struct Node : ilist_node<Node> {};
+bool operator<(const Node &L, const Node &R) { return &L < &R; }
+bool makeFalse(const Node &, const Node &) { return false; }
+
+struct deleteNode : std::default_delete<Node> {};
+void doNothing(Node *) {}
+
+TEST(SimpleIListTest, DefaultConstructor) {
+ simple_ilist<Node> L;
+ EXPECT_EQ(L.begin(), L.end());
+ EXPECT_TRUE(L.empty());
+ EXPECT_EQ(0u, L.size());
+}
+
+TEST(SimpleIListTest, pushPopFront) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.push_front(B);
+ L.push_front(A);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &L.back());
+ EXPECT_FALSE(L.empty());
+ EXPECT_EQ(2u, L.size());
+
+ // Pop front and check the new front.
+ L.pop_front();
+ EXPECT_EQ(&B, &L.front());
+
+ // Pop to empty.
+ L.pop_front();
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(SimpleIListTest, pushPopBack) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.push_back(A);
+ L.push_back(B);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &L.back());
+ EXPECT_FALSE(L.empty());
+ EXPECT_EQ(2u, L.size());
+
+ // Pop back and check the new front.
+ L.pop_back();
+ EXPECT_EQ(&A, &L.back());
+
+ // Pop to empty.
+ L.pop_back();
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(SimpleIListTest, swap) {
+ simple_ilist<Node> L1, L2;
+ Node A, B;
+ L1.push_back(A);
+ L1.push_back(B);
+ L1.swap(L2);
+ EXPECT_TRUE(L1.empty());
+ EXPECT_EQ(0u, L1.size());
+ EXPECT_EQ(&A, &L2.front());
+ EXPECT_EQ(&B, &L2.back());
+ EXPECT_FALSE(L2.empty());
+ EXPECT_EQ(2u, L2.size());
+}
+
+TEST(SimpleIListTest, insertEraseAtEnd) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.insert(L.end(), A);
+ L.insert(L.end(), B);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &L.back());
+ EXPECT_FALSE(L.empty());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, insertAtBegin) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.insert(L.begin(), B);
+ L.insert(L.begin(), A);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &L.back());
+ EXPECT_FALSE(L.empty());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, remove) {
+ simple_ilist<Node> L;
+ Node A, B, C;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ L.remove(B);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+
+ L.remove(A);
+ EXPECT_EQ(&C, &L.front());
+ EXPECT_EQ(1u, L.size());
+
+ L.remove(C);
+ EXPECT_TRUE(L.empty());
+}
+
+TEST(SimpleIListTest, removeAndDispose) {
+ simple_ilist<Node> L;
+ Node A, C;
+ Node *B = new Node;
+ L.push_back(A);
+ L.push_back(*B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ L.removeAndDispose(*B, deleteNode());
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, removeAndDisposeNullDeleter) {
+ simple_ilist<Node> L;
+ Node A, B, C;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ L.removeAndDispose(B, doNothing);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, erase) {
+ simple_ilist<Node> L;
+ Node A, B, C;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ EXPECT_EQ(C.getIterator(), L.erase(B.getIterator()));
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, reverse_iterator) {
+ simple_ilist<Node> L;
+ Node A, B, C;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+
+ auto ReverseIter = L.rbegin();
+ EXPECT_EQ(C.getReverseIterator(), ReverseIter);
+ ++ReverseIter;
+ EXPECT_EQ(B.getReverseIterator(), ReverseIter);
+ ++ReverseIter;
+ EXPECT_EQ(A.getReverseIterator(), ReverseIter);
+ ++ReverseIter;
+ EXPECT_EQ(L.rend(), ReverseIter);
+}
+
+TEST(SimpleIListTest, eraseAndDispose) {
+ simple_ilist<Node> L;
+ Node A, C;
+ Node *B = new Node;
+ L.push_back(A);
+ L.push_back(*B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ L.eraseAndDispose(B->getIterator(), deleteNode());
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, eraseAndDisposeNullDeleter) {
+ simple_ilist<Node> L;
+ Node A, B, C;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&B, &*++L.begin());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(3u, L.size());
+
+ L.eraseAndDispose(B.getIterator(), doNothing);
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&C, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, eraseRange) {
+ simple_ilist<Node> L;
+ Node A, B, C, D, E;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ L.push_back(D);
+ L.push_back(E);
+ auto I = L.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(&B, &*I++);
+ EXPECT_EQ(&C, &*I++);
+ EXPECT_EQ(&D, &*I++);
+ EXPECT_EQ(&E, &*I++);
+ EXPECT_EQ(L.end(), I);
+ EXPECT_EQ(5u, L.size());
+
+ // Erase a range.
+ EXPECT_EQ(E.getIterator(), L.erase(B.getIterator(), E.getIterator()));
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&E, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, eraseAndDisposeRange) {
+ simple_ilist<Node> L;
+ Node A, *B = new Node, *C = new Node, *D = new Node, E;
+ L.push_back(A);
+ L.push_back(*B);
+ L.push_back(*C);
+ L.push_back(*D);
+ L.push_back(E);
+ auto I = L.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(B, &*I++);
+ EXPECT_EQ(C, &*I++);
+ EXPECT_EQ(D, &*I++);
+ EXPECT_EQ(&E, &*I++);
+ EXPECT_EQ(L.end(), I);
+ EXPECT_EQ(5u, L.size());
+
+ // Erase a range.
+ EXPECT_EQ(E.getIterator(),
+ L.eraseAndDispose(B->getIterator(), E.getIterator(), deleteNode()));
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&E, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, eraseAndDisposeRangeNullDeleter) {
+ simple_ilist<Node> L;
+ Node A, B, C, D, E;
+ L.push_back(A);
+ L.push_back(B);
+ L.push_back(C);
+ L.push_back(D);
+ L.push_back(E);
+ auto I = L.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(&B, &*I++);
+ EXPECT_EQ(&C, &*I++);
+ EXPECT_EQ(&D, &*I++);
+ EXPECT_EQ(&E, &*I++);
+ EXPECT_EQ(L.end(), I);
+ EXPECT_EQ(5u, L.size());
+
+ // Erase a range.
+ EXPECT_EQ(E.getIterator(),
+ L.eraseAndDispose(B.getIterator(), E.getIterator(), doNothing));
+ EXPECT_EQ(&A, &L.front());
+ EXPECT_EQ(&E, &L.back());
+ EXPECT_EQ(2u, L.size());
+}
+
+TEST(SimpleIListTest, clear) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.push_back(A);
+ L.push_back(B);
+ L.clear();
+ EXPECT_TRUE(L.empty());
+ EXPECT_EQ(0u, L.size());
+}
+
+TEST(SimpleIListTest, clearAndDispose) {
+ simple_ilist<Node> L;
+ Node *A = new Node;
+ Node *B = new Node;
+ L.push_back(*A);
+ L.push_back(*B);
+ L.clearAndDispose(deleteNode());
+ EXPECT_TRUE(L.empty());
+ EXPECT_EQ(0u, L.size());
+}
+
+TEST(SimpleIListTest, clearAndDisposeNullDeleter) {
+ simple_ilist<Node> L;
+ Node A, B;
+ L.push_back(A);
+ L.push_back(B);
+ L.clearAndDispose(doNothing);
+ EXPECT_TRUE(L.empty());
+ EXPECT_EQ(0u, L.size());
+}
+
+TEST(SimpleIListTest, spliceList) {
+ simple_ilist<Node> L1, L2;
+ Node A, B, C, D;
+
+ // [A, D].
+ L1.push_back(A);
+ L1.push_back(D);
+
+ // [B, C].
+ L2.push_back(B);
+ L2.push_back(C);
+
+ // Splice in L2, giving [A, B, C, D].
+ L1.splice(--L1.end(), L2);
+ EXPECT_TRUE(L2.empty());
+ EXPECT_EQ(4u, L1.size());
+ auto I = L1.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(&B, &*I++);
+ EXPECT_EQ(&C, &*I++);
+ EXPECT_EQ(&D, &*I++);
+ EXPECT_EQ(L1.end(), I);
+}
+
+TEST(SimpleIListTest, spliceSingle) {
+ simple_ilist<Node> L1, L2;
+ Node A, B, C, D, E;
+
+ // [A, C].
+ L1.push_back(A);
+ L1.push_back(C);
+
+ // [D, B, E].
+ L2.push_back(D);
+ L2.push_back(B);
+ L2.push_back(E);
+
+ // Splice B from L2 to L1, giving [A, B, C] and [D, E].
+ L1.splice(--L1.end(), L2, ++L2.begin());
+ auto I = L1.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(&B, &*I++);
+ EXPECT_EQ(&C, &*I++);
+ EXPECT_EQ(L1.end(), I);
+
+ I = L2.begin();
+ EXPECT_EQ(&D, &*I++);
+ EXPECT_EQ(&E, &*I++);
+ EXPECT_EQ(L2.end(), I);
+}
+
+TEST(SimpleIListTest, spliceRange) {
+ simple_ilist<Node> L1, L2;
+ Node A, B, C, D, E, F;
+
+ // [A, D].
+ L1.push_back(A);
+ L1.push_back(D);
+
+ // [E, B, C, F].
+ L2.push_back(E);
+ L2.push_back(B);
+ L2.push_back(C);
+ L2.push_back(F);
+
+ // Splice B from L2 to L1, giving [A, B, C, D] and [E, F].
+ L1.splice(--L1.end(), L2, ++L2.begin(), --L2.end());
+ auto I = L1.begin();
+ EXPECT_EQ(&A, &*I++);
+ EXPECT_EQ(&B, &*I++);
+ EXPECT_EQ(&C, &*I++);
+ EXPECT_EQ(&D, &*I++);
+ EXPECT_EQ(L1.end(), I);
+
+ I = L2.begin();
+ EXPECT_EQ(&E, &*I++);
+ EXPECT_EQ(&F, &*I++);
+ EXPECT_EQ(L2.end(), I);
+}
+
+TEST(SimpleIListTest, merge) {
+ for (bool IsL1LHS : {false, true}) {
+ simple_ilist<Node> L1, L2;
+ Node Ns[10];
+
+ // Fill L1.
+ L1.push_back(Ns[0]);
+ L1.push_back(Ns[3]);
+ L1.push_back(Ns[4]);
+ L1.push_back(Ns[8]);
+
+ // Fill L2.
+ L2.push_back(Ns[1]);
+ L2.push_back(Ns[2]);
+ L2.push_back(Ns[5]);
+ L2.push_back(Ns[6]);
+ L2.push_back(Ns[7]);
+ L2.push_back(Ns[9]);
+
+ // Check setup.
+ EXPECT_EQ(4u, L1.size());
+ EXPECT_EQ(6u, L2.size());
+ EXPECT_TRUE(std::is_sorted(L1.begin(), L1.end()));
+ EXPECT_TRUE(std::is_sorted(L2.begin(), L2.end()));
+
+ // Merge.
+ auto &LHS = IsL1LHS ? L1 : L2;
+ auto &RHS = IsL1LHS ? L2 : L1;
+ LHS.merge(RHS);
+ EXPECT_TRUE(RHS.empty());
+ EXPECT_FALSE(LHS.empty());
+ EXPECT_TRUE(std::is_sorted(LHS.begin(), LHS.end()));
+ auto I = LHS.begin();
+ for (Node &N : Ns)
+ EXPECT_EQ(&N, &*I++);
+ EXPECT_EQ(LHS.end(), I);
+ }
+}
+
+TEST(SimpleIListTest, mergeIsStable) {
+ simple_ilist<Node> L1, L2;
+ Node Ns[5];
+
+ auto setup = [&]() {
+ EXPECT_TRUE(L1.empty());
+ EXPECT_TRUE(L2.empty());
+
+ // Fill L1.
+ L1.push_back(Ns[0]);
+ L1.push_back(Ns[3]);
+ L1.push_back(Ns[4]);
+
+ // Fill L2.
+ L2.push_back(Ns[1]);
+ L2.push_back(Ns[2]);
+
+ // Check setup.
+ EXPECT_EQ(3u, L1.size());
+ EXPECT_EQ(2u, L2.size());
+ EXPECT_TRUE(std::is_sorted(L1.begin(), L1.end(), makeFalse));
+ EXPECT_TRUE(std::is_sorted(L2.begin(), L2.end(), makeFalse));
+ };
+
+ // Merge. Should be stable.
+ setup();
+ L1.merge(L2, makeFalse);
+ EXPECT_TRUE(L2.empty());
+ EXPECT_FALSE(L1.empty());
+ EXPECT_TRUE(std::is_sorted(L1.begin(), L1.end(), makeFalse));
+ auto I = L1.begin();
+ EXPECT_EQ(&Ns[0], &*I++);
+ EXPECT_EQ(&Ns[3], &*I++);
+ EXPECT_EQ(&Ns[4], &*I++);
+ EXPECT_EQ(&Ns[1], &*I++);
+ EXPECT_EQ(&Ns[2], &*I++);
+ EXPECT_EQ(L1.end(), I);
+
+ // Merge the other way. Should be stable.
+ L1.clear();
+ setup();
+ L2.merge(L1, makeFalse);
+ EXPECT_TRUE(L1.empty());
+ EXPECT_FALSE(L2.empty());
+ EXPECT_TRUE(std::is_sorted(L2.begin(), L2.end(), makeFalse));
+ I = L2.begin();
+ EXPECT_EQ(&Ns[1], &*I++);
+ EXPECT_EQ(&Ns[2], &*I++);
+ EXPECT_EQ(&Ns[0], &*I++);
+ EXPECT_EQ(&Ns[3], &*I++);
+ EXPECT_EQ(&Ns[4], &*I++);
+ EXPECT_EQ(L2.end(), I);
+}
+
+TEST(SimpleIListTest, mergeEmpty) {
+ for (bool IsL1LHS : {false, true}) {
+ simple_ilist<Node> L1, L2;
+ Node Ns[4];
+
+ // Fill L1.
+ L1.push_back(Ns[0]);
+ L1.push_back(Ns[1]);
+ L1.push_back(Ns[2]);
+ L1.push_back(Ns[3]);
+
+ // Check setup.
+ EXPECT_EQ(4u, L1.size());
+ EXPECT_TRUE(L2.empty());
+ EXPECT_TRUE(std::is_sorted(L1.begin(), L1.end()));
+
+ // Merge.
+ auto &LHS = IsL1LHS ? L1 : L2;
+ auto &RHS = IsL1LHS ? L2 : L1;
+ LHS.merge(RHS);
+ EXPECT_TRUE(RHS.empty());
+ EXPECT_FALSE(LHS.empty());
+ EXPECT_TRUE(std::is_sorted(LHS.begin(), LHS.end()));
+ auto I = LHS.begin();
+ for (Node &N : Ns)
+ EXPECT_EQ(&N, &*I++);
+ EXPECT_EQ(LHS.end(), I);
+ }
+}
+
+TEST(SimpleIListTest, mergeBothEmpty) {
+ simple_ilist<Node> L1, L2;
+ L1.merge(L2);
+ EXPECT_TRUE(L1.empty());
+ EXPECT_TRUE(L2.empty());
+}
+
+TEST(SimpleIListTest, sort) {
+ simple_ilist<Node> L;
+ Node Ns[10];
+
+ // Fill L.
+ for (int I : {3, 4, 0, 8, 1, 2, 6, 7, 9, 5})
+ L.push_back(Ns[I]);
+
+ // Check setup.
+ EXPECT_EQ(10u, L.size());
+ EXPECT_FALSE(std::is_sorted(L.begin(), L.end()));
+
+ // Sort.
+ L.sort();
+ EXPECT_TRUE(std::is_sorted(L.begin(), L.end()));
+ auto I = L.begin();
+ for (Node &N : Ns)
+ EXPECT_EQ(&N, &*I++);
+ EXPECT_EQ(L.end(), I);
+}
+
+TEST(SimpleIListTest, sortIsStable) {
+ simple_ilist<Node> L;
+ Node Ns[10];
+
+ // Compare such that nodes are partitioned but not fully sorted.
+ auto partition = [&](const Node &N) { return &N >= &Ns[5]; };
+ auto compare = [&](const Node &L, const Node &R) {
+ return partition(L) < partition(R);
+ };
+
+ // Fill L.
+ for (int I : {3, 4, 7, 8, 1, 2, 6, 0, 9, 5})
+ L.push_back(Ns[I]);
+
+ // Check setup.
+ EXPECT_EQ(10u, L.size());
+ EXPECT_FALSE(std::is_sorted(L.begin(), L.end(), compare));
+
+ // Sort.
+ L.sort(compare);
+ EXPECT_TRUE(std::is_sorted(L.begin(), L.end(), compare));
+ auto I = L.begin();
+ for (int O : {3, 4, 1, 2, 0})
+ EXPECT_EQ(&Ns[O], &*I++);
+ for (int O : {7, 8, 6, 9, 5})
+ EXPECT_EQ(&Ns[O], &*I++);
+ EXPECT_EQ(L.end(), I);
+}
+
+TEST(SimpleIListTest, sortEmpty) {
+ simple_ilist<Node> L;
+ L.sort();
+}
+
+struct Tag1 {};
+struct Tag2 {};
+
+struct DoubleNode : ilist_node<DoubleNode, ilist_tag<Tag1>>,
+ ilist_node<DoubleNode, ilist_tag<Tag2>> {
+ typedef ilist_node<DoubleNode, ilist_tag<Tag1>> Node1Type;
+ typedef ilist_node<DoubleNode, ilist_tag<Tag2>> Node2Type;
+
+ Node1Type::self_iterator getIterator1() { return Node1Type::getIterator(); }
+ Node2Type::self_iterator getIterator2() { return Node2Type::getIterator(); }
+ Node1Type::const_self_iterator getIterator1() const {
+ return Node1Type::getIterator();
+ }
+ Node2Type::const_self_iterator getIterator2() const {
+ return Node2Type::getIterator();
+ }
+};
+typedef simple_ilist<DoubleNode, ilist_tag<Tag1>> TaggedList1Type;
+typedef simple_ilist<DoubleNode, ilist_tag<Tag2>> TaggedList2Type;
+
+TEST(SimpleIListTest, TaggedLists) {
+ TaggedList1Type L1;
+ TaggedList2Type L2;
+
+ // Build the two lists, sharing a couple of nodes.
+ DoubleNode Ns[10];
+ int Order1[] = {0, 1, 2, 3, 4, 7, 9};
+ int Order2[] = {2, 5, 6, 7, 8, 4, 9, 1};
+ for (int I : Order1)
+ L1.push_back(Ns[I]);
+ for (int I : Order2)
+ L2.push_back(Ns[I]);
+
+ // Check that each list is correct.
+ EXPECT_EQ(sizeof(Order1) / sizeof(int), L1.size());
+ auto I1 = L1.begin();
+ for (int I : Order1) {
+ EXPECT_EQ(Ns[I].getIterator1(), I1);
+ EXPECT_EQ(&Ns[I], &*I1++);
+ }
+ EXPECT_EQ(L1.end(), I1);
+
+ EXPECT_EQ(sizeof(Order2) / sizeof(int), L2.size());
+ auto I2 = L2.begin();
+ for (int I : Order2) {
+ EXPECT_EQ(Ns[I].getIterator2(), I2);
+ EXPECT_EQ(&Ns[I], &*I2++);
+ }
+ EXPECT_EQ(L2.end(), I2);
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SmallPtrSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/SmallPtrSetTest.cpp
new file mode 100644
index 0000000..76f9cf7
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SmallPtrSetTest.cpp
@@ -0,0 +1,332 @@
+//===- llvm/unittest/ADT/SmallPtrSetTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SmallPtrSet unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/PointerLikeTypeTraits.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(SmallPtrSetTest, Assignment) {
+ int buf[8];
+ for (int i = 0; i < 8; ++i)
+ buf[i] = 0;
+
+ SmallPtrSet<int *, 4> s1 = {&buf[0], &buf[1]};
+ SmallPtrSet<int *, 4> s2;
+ (s2 = s1).insert(&buf[2]);
+
+ // Self assign as well.
+ (s2 = static_cast<SmallPtrSet<int *, 4> &>(s2)).insert(&buf[3]);
+
+ s1 = s2;
+ EXPECT_EQ(4U, s1.size());
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_TRUE(s1.count(&buf[i]));
+ else
+ EXPECT_FALSE(s1.count(&buf[i]));
+
+ // Assign and insert with initializer lists, and ones that contain both
+ // duplicates and out-of-order elements.
+ (s2 = {&buf[6], &buf[7], &buf[6]}).insert({&buf[5], &buf[4]});
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_FALSE(s2.count(&buf[i]));
+ else
+ EXPECT_TRUE(s2.count(&buf[i]));
+}
+
+TEST(SmallPtrSetTest, GrowthTest) {
+ int i;
+ int buf[8];
+ for(i=0; i<8; ++i) buf[i]=0;
+
+
+ SmallPtrSet<int *, 4> s;
+ typedef SmallPtrSet<int *, 4>::iterator iter;
+
+ s.insert(&buf[0]);
+ s.insert(&buf[1]);
+ s.insert(&buf[2]);
+ s.insert(&buf[3]);
+ EXPECT_EQ(4U, s.size());
+
+ i = 0;
+ for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
+ (**I)++;
+ EXPECT_EQ(4, i);
+ for(i=0; i<8; ++i)
+ EXPECT_EQ(i<4?1:0,buf[i]);
+
+ s.insert(&buf[4]);
+ s.insert(&buf[5]);
+ s.insert(&buf[6]);
+ s.insert(&buf[7]);
+
+ i = 0;
+ for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
+ (**I)++;
+ EXPECT_EQ(8, i);
+ s.erase(&buf[4]);
+ s.erase(&buf[5]);
+ s.erase(&buf[6]);
+ s.erase(&buf[7]);
+ EXPECT_EQ(4U, s.size());
+
+ i = 0;
+ for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
+ (**I)++;
+ EXPECT_EQ(4, i);
+ for(i=0; i<8; ++i)
+ EXPECT_EQ(i<4?3:1,buf[i]);
+
+ s.clear();
+ for(i=0; i<8; ++i) buf[i]=0;
+ for(i=0; i<128; ++i) s.insert(&buf[i%8]); // test repeated entires
+ EXPECT_EQ(8U, s.size());
+ for(iter I=s.begin(), E=s.end(); I!=E; ++I, ++i)
+ (**I)++;
+ for(i=0; i<8; ++i)
+ EXPECT_EQ(1,buf[i]);
+}
+
+TEST(SmallPtrSetTest, CopyAndMoveTest) {
+ int buf[8];
+ for (int i = 0; i < 8; ++i)
+ buf[i] = 0;
+
+ SmallPtrSet<int *, 4> s1;
+ s1.insert(&buf[0]);
+ s1.insert(&buf[1]);
+ s1.insert(&buf[2]);
+ s1.insert(&buf[3]);
+ EXPECT_EQ(4U, s1.size());
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_TRUE(s1.count(&buf[i]));
+ else
+ EXPECT_FALSE(s1.count(&buf[i]));
+
+ SmallPtrSet<int *, 4> s2(s1);
+ EXPECT_EQ(4U, s2.size());
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_TRUE(s2.count(&buf[i]));
+ else
+ EXPECT_FALSE(s2.count(&buf[i]));
+
+ s1 = s2;
+ EXPECT_EQ(4U, s1.size());
+ EXPECT_EQ(4U, s2.size());
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_TRUE(s1.count(&buf[i]));
+ else
+ EXPECT_FALSE(s1.count(&buf[i]));
+
+ SmallPtrSet<int *, 4> s3(std::move(s1));
+ EXPECT_EQ(4U, s3.size());
+ EXPECT_TRUE(s1.empty());
+ for (int i = 0; i < 8; ++i)
+ if (i < 4)
+ EXPECT_TRUE(s3.count(&buf[i]));
+ else
+ EXPECT_FALSE(s3.count(&buf[i]));
+
+ // Move assign into the moved-from object. Also test move of a non-small
+ // container.
+ s3.insert(&buf[4]);
+ s3.insert(&buf[5]);
+ s3.insert(&buf[6]);
+ s3.insert(&buf[7]);
+ s1 = std::move(s3);
+ EXPECT_EQ(8U, s1.size());
+ EXPECT_TRUE(s3.empty());
+ for (int i = 0; i < 8; ++i)
+ EXPECT_TRUE(s1.count(&buf[i]));
+
+ // Copy assign into a moved-from object.
+ s3 = s1;
+ EXPECT_EQ(8U, s3.size());
+ EXPECT_EQ(8U, s1.size());
+ for (int i = 0; i < 8; ++i)
+ EXPECT_TRUE(s3.count(&buf[i]));
+}
+
+TEST(SmallPtrSetTest, SwapTest) {
+ int buf[10];
+
+ SmallPtrSet<int *, 2> a;
+ SmallPtrSet<int *, 2> b;
+
+ a.insert(&buf[0]);
+ a.insert(&buf[1]);
+ b.insert(&buf[2]);
+
+ EXPECT_EQ(2U, a.size());
+ EXPECT_EQ(1U, b.size());
+ EXPECT_TRUE(a.count(&buf[0]));
+ EXPECT_TRUE(a.count(&buf[1]));
+ EXPECT_FALSE(a.count(&buf[2]));
+ EXPECT_FALSE(a.count(&buf[3]));
+ EXPECT_FALSE(b.count(&buf[0]));
+ EXPECT_FALSE(b.count(&buf[1]));
+ EXPECT_TRUE(b.count(&buf[2]));
+ EXPECT_FALSE(b.count(&buf[3]));
+
+ std::swap(a, b);
+
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(2U, b.size());
+ EXPECT_FALSE(a.count(&buf[0]));
+ EXPECT_FALSE(a.count(&buf[1]));
+ EXPECT_TRUE(a.count(&buf[2]));
+ EXPECT_FALSE(a.count(&buf[3]));
+ EXPECT_TRUE(b.count(&buf[0]));
+ EXPECT_TRUE(b.count(&buf[1]));
+ EXPECT_FALSE(b.count(&buf[2]));
+ EXPECT_FALSE(b.count(&buf[3]));
+
+ b.insert(&buf[3]);
+ std::swap(a, b);
+
+ EXPECT_EQ(3U, a.size());
+ EXPECT_EQ(1U, b.size());
+ EXPECT_TRUE(a.count(&buf[0]));
+ EXPECT_TRUE(a.count(&buf[1]));
+ EXPECT_FALSE(a.count(&buf[2]));
+ EXPECT_TRUE(a.count(&buf[3]));
+ EXPECT_FALSE(b.count(&buf[0]));
+ EXPECT_FALSE(b.count(&buf[1]));
+ EXPECT_TRUE(b.count(&buf[2]));
+ EXPECT_FALSE(b.count(&buf[3]));
+
+ std::swap(a, b);
+
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(3U, b.size());
+ EXPECT_FALSE(a.count(&buf[0]));
+ EXPECT_FALSE(a.count(&buf[1]));
+ EXPECT_TRUE(a.count(&buf[2]));
+ EXPECT_FALSE(a.count(&buf[3]));
+ EXPECT_TRUE(b.count(&buf[0]));
+ EXPECT_TRUE(b.count(&buf[1]));
+ EXPECT_FALSE(b.count(&buf[2]));
+ EXPECT_TRUE(b.count(&buf[3]));
+
+ a.insert(&buf[4]);
+ a.insert(&buf[5]);
+ a.insert(&buf[6]);
+
+ std::swap(b, a);
+
+ EXPECT_EQ(3U, a.size());
+ EXPECT_EQ(4U, b.size());
+ EXPECT_TRUE(b.count(&buf[2]));
+ EXPECT_TRUE(b.count(&buf[4]));
+ EXPECT_TRUE(b.count(&buf[5]));
+ EXPECT_TRUE(b.count(&buf[6]));
+ EXPECT_TRUE(a.count(&buf[0]));
+ EXPECT_TRUE(a.count(&buf[1]));
+ EXPECT_TRUE(a.count(&buf[3]));
+}
+
+void checkEraseAndIterators(SmallPtrSetImpl<int*> &S) {
+ int buf[3];
+
+ S.insert(&buf[0]);
+ S.insert(&buf[1]);
+ S.insert(&buf[2]);
+
+ // Iterators must still be valid after erase() calls;
+ auto B = S.begin();
+ auto M = std::next(B);
+ auto E = S.end();
+ EXPECT_TRUE(*B == &buf[0] || *B == &buf[1] || *B == &buf[2]);
+ EXPECT_TRUE(*M == &buf[0] || *M == &buf[1] || *M == &buf[2]);
+ EXPECT_TRUE(*B != *M);
+ int *Removable = *std::next(M);
+ // No iterator points to Removable now.
+ EXPECT_TRUE(Removable == &buf[0] || Removable == &buf[1] ||
+ Removable == &buf[2]);
+ EXPECT_TRUE(Removable != *B && Removable != *M);
+
+ S.erase(Removable);
+
+ // B,M,E iterators should still be valid
+ EXPECT_EQ(B, S.begin());
+ EXPECT_EQ(M, std::next(B));
+ EXPECT_EQ(E, S.end());
+ EXPECT_EQ(std::next(M), E);
+}
+
+TEST(SmallPtrSetTest, EraseTest) {
+ // Test when set stays small.
+ SmallPtrSet<int *, 8> B;
+ checkEraseAndIterators(B);
+
+ // Test when set grows big.
+ SmallPtrSet<int *, 2> A;
+ checkEraseAndIterators(A);
+}
+
+// Verify that dereferencing and iteration work.
+TEST(SmallPtrSetTest, dereferenceAndIterate) {
+ int Ints[] = {0, 1, 2, 3, 4, 5, 6, 7};
+ SmallPtrSet<const int *, 4> S;
+ for (int &I : Ints) {
+ EXPECT_EQ(&I, *S.insert(&I).first);
+ EXPECT_EQ(&I, *S.find(&I));
+ }
+
+ // Iterate from each and count how many times each element is found.
+ int Found[sizeof(Ints)/sizeof(int)] = {0};
+ for (int &I : Ints)
+ for (auto F = S.find(&I), E = S.end(); F != E; ++F)
+ ++Found[*F - Ints];
+
+ // Sort. We should hit the first element just once and the final element N
+ // times.
+ llvm::sort(std::begin(Found), std::end(Found));
+ for (auto F = std::begin(Found), E = std::end(Found); F != E; ++F)
+ EXPECT_EQ(F - Found + 1, *F);
+}
+
+// Verify that const pointers work for count and find even when the underlying
+// SmallPtrSet is not for a const pointer type.
+TEST(SmallPtrSetTest, ConstTest) {
+ SmallPtrSet<int *, 8> IntSet;
+ int A;
+ int *B = &A;
+ const int *C = &A;
+ IntSet.insert(B);
+ EXPECT_EQ(IntSet.count(B), 1u);
+ EXPECT_EQ(IntSet.count(C), 1u);
+ EXPECT_NE(IntSet.find(B), IntSet.end());
+ EXPECT_NE(IntSet.find(C), IntSet.end());
+}
+
+// Verify that we automatically get the const version of PointerLikeTypeTraits
+// filled in for us, even for a non-pointer type
+using TestPair = PointerIntPair<int *, 1>;
+
+TEST(SmallPtrSetTest, ConstNonPtrTest) {
+ SmallPtrSet<TestPair, 8> IntSet;
+ int A[1];
+ TestPair Pair(&A[0], 1);
+ IntSet.insert(Pair);
+ EXPECT_EQ(IntSet.count(Pair), 1u);
+ EXPECT_NE(IntSet.find(Pair), IntSet.end());
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/SmallSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/SmallSetTest.cpp
new file mode 100644
index 0000000..3391a5c
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SmallSetTest.cpp
@@ -0,0 +1,145 @@
+//===- llvm/unittest/ADT/SmallSetTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SmallSet unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallSet.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+TEST(SmallSetTest, Insert) {
+
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 4; i++)
+ s1.insert(i);
+
+ for (int i = 0; i < 4; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(4u, s1.size());
+
+ for (int i = 0; i < 4; i++)
+ EXPECT_EQ(1u, s1.count(i));
+
+ EXPECT_EQ(0u, s1.count(4));
+}
+
+TEST(SmallSetTest, Grow) {
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 8; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(8u, s1.size());
+
+ for (int i = 0; i < 8; i++)
+ EXPECT_EQ(1u, s1.count(i));
+
+ EXPECT_EQ(0u, s1.count(8));
+}
+
+TEST(SmallSetTest, Erase) {
+ SmallSet<int, 4> s1;
+
+ for (int i = 0; i < 8; i++)
+ s1.insert(i);
+
+ EXPECT_EQ(8u, s1.size());
+
+ // Remove elements one by one and check if all other elements are still there.
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(1u, s1.count(i));
+ EXPECT_TRUE(s1.erase(i));
+ EXPECT_EQ(0u, s1.count(i));
+ EXPECT_EQ(8u - i - 1, s1.size());
+ for (int j = i + 1; j < 8; j++)
+ EXPECT_EQ(1u, s1.count(j));
+ }
+
+ EXPECT_EQ(0u, s1.count(8));
+}
+
+TEST(SmallSetTest, IteratorInt) {
+ SmallSet<int, 4> s1;
+
+ // Test the 'small' case.
+ for (int i = 0; i < 3; i++)
+ s1.insert(i);
+
+ std::vector<int> V(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ for (int i = 0; i < 3; i++)
+ EXPECT_EQ(i, V[i]);
+
+ // Test the 'big' case by adding a few more elements to switch to std::set
+ // internally.
+ for (int i = 3; i < 6; i++)
+ s1.insert(i);
+
+ V.assign(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ for (int i = 0; i < 6; i++)
+ EXPECT_EQ(i, V[i]);
+}
+
+TEST(SmallSetTest, IteratorString) {
+ // Test SmallSetIterator for SmallSet with a type with non-trivial
+ // ctors/dtors.
+ SmallSet<std::string, 2> s1;
+
+ s1.insert("str 1");
+ s1.insert("str 2");
+ s1.insert("str 1");
+
+ std::vector<std::string> V(s1.begin(), s1.end());
+ std::sort(V.begin(), V.end());
+ EXPECT_EQ(2u, s1.size());
+ EXPECT_EQ("str 1", V[0]);
+ EXPECT_EQ("str 2", V[1]);
+
+ s1.insert("str 4");
+ s1.insert("str 0");
+ s1.insert("str 4");
+
+ V.assign(s1.begin(), s1.end());
+ // Make sure the elements are in the expected order.
+ std::sort(V.begin(), V.end());
+ EXPECT_EQ(4u, s1.size());
+ EXPECT_EQ("str 0", V[0]);
+ EXPECT_EQ("str 1", V[1]);
+ EXPECT_EQ("str 2", V[2]);
+ EXPECT_EQ("str 4", V[3]);
+}
+
+TEST(SmallSetTest, IteratorIncMoveCopy) {
+ // Test SmallSetIterator for SmallSet with a type with non-trivial
+ // ctors/dtors.
+ SmallSet<std::string, 2> s1;
+
+ s1.insert("str 1");
+ s1.insert("str 2");
+
+ auto Iter = s1.begin();
+ EXPECT_EQ("str 1", *Iter);
+ ++Iter;
+ EXPECT_EQ("str 2", *Iter);
+
+ s1.insert("str 4");
+ s1.insert("str 0");
+ auto Iter2 = s1.begin();
+ Iter = std::move(Iter2);
+ EXPECT_EQ("str 0", *Iter);
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/SmallStringTest.cpp b/src/llvm-project/llvm/unittests/ADT/SmallStringTest.cpp
new file mode 100644
index 0000000..995ef8e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SmallStringTest.cpp
@@ -0,0 +1,207 @@
+//===- llvm/unittest/ADT/SmallStringTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SmallString unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "gtest/gtest.h"
+#include <climits>
+#include <cstring>
+#include <stdarg.h>
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture class
+class SmallStringTest : public testing::Test {
+protected:
+ typedef SmallString<40> StringType;
+
+ StringType theString;
+
+ void assertEmpty(StringType & v) {
+ // Size tests
+ EXPECT_EQ(0u, v.size());
+ EXPECT_TRUE(v.empty());
+ // Iterator tests
+ EXPECT_TRUE(v.begin() == v.end());
+ }
+};
+
+// New string test.
+TEST_F(SmallStringTest, EmptyStringTest) {
+ SCOPED_TRACE("EmptyStringTest");
+ assertEmpty(theString);
+ EXPECT_TRUE(theString.rbegin() == theString.rend());
+}
+
+TEST_F(SmallStringTest, AssignRepeated) {
+ theString.assign(3, 'a');
+ EXPECT_EQ(3u, theString.size());
+ EXPECT_STREQ("aaa", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AssignIterPair) {
+ StringRef abc = "abc";
+ theString.assign(abc.begin(), abc.end());
+ EXPECT_EQ(3u, theString.size());
+ EXPECT_STREQ("abc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AssignStringRef) {
+ StringRef abc = "abc";
+ theString.assign(abc);
+ EXPECT_EQ(3u, theString.size());
+ EXPECT_STREQ("abc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AssignSmallVector) {
+ StringRef abc = "abc";
+ SmallVector<char, 10> abcVec(abc.begin(), abc.end());
+ theString.assign(abcVec);
+ EXPECT_EQ(3u, theString.size());
+ EXPECT_STREQ("abc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AppendIterPair) {
+ StringRef abc = "abc";
+ theString.append(abc.begin(), abc.end());
+ theString.append(abc.begin(), abc.end());
+ EXPECT_EQ(6u, theString.size());
+ EXPECT_STREQ("abcabc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AppendStringRef) {
+ StringRef abc = "abc";
+ theString.append(abc);
+ theString.append(abc);
+ EXPECT_EQ(6u, theString.size());
+ EXPECT_STREQ("abcabc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, AppendSmallVector) {
+ StringRef abc = "abc";
+ SmallVector<char, 10> abcVec(abc.begin(), abc.end());
+ theString.append(abcVec);
+ theString.append(abcVec);
+ EXPECT_EQ(6u, theString.size());
+ EXPECT_STREQ("abcabc", theString.c_str());
+}
+
+TEST_F(SmallStringTest, Substr) {
+ theString = "hello";
+ EXPECT_EQ("lo", theString.substr(3));
+ EXPECT_EQ("", theString.substr(100));
+ EXPECT_EQ("hello", theString.substr(0, 100));
+ EXPECT_EQ("o", theString.substr(4, 10));
+}
+
+TEST_F(SmallStringTest, Slice) {
+ theString = "hello";
+ EXPECT_EQ("l", theString.slice(2, 3));
+ EXPECT_EQ("ell", theString.slice(1, 4));
+ EXPECT_EQ("llo", theString.slice(2, 100));
+ EXPECT_EQ("", theString.slice(2, 1));
+ EXPECT_EQ("", theString.slice(10, 20));
+}
+
+TEST_F(SmallStringTest, Find) {
+ theString = "hello";
+ EXPECT_EQ(2U, theString.find('l'));
+ EXPECT_EQ(StringRef::npos, theString.find('z'));
+ EXPECT_EQ(StringRef::npos, theString.find("helloworld"));
+ EXPECT_EQ(0U, theString.find("hello"));
+ EXPECT_EQ(1U, theString.find("ello"));
+ EXPECT_EQ(StringRef::npos, theString.find("zz"));
+ EXPECT_EQ(2U, theString.find("ll", 2));
+ EXPECT_EQ(StringRef::npos, theString.find("ll", 3));
+ EXPECT_EQ(0U, theString.find(""));
+
+ EXPECT_EQ(3U, theString.rfind('l'));
+ EXPECT_EQ(StringRef::npos, theString.rfind('z'));
+ EXPECT_EQ(StringRef::npos, theString.rfind("helloworld"));
+ EXPECT_EQ(0U, theString.rfind("hello"));
+ EXPECT_EQ(1U, theString.rfind("ello"));
+ EXPECT_EQ(StringRef::npos, theString.rfind("zz"));
+
+ EXPECT_EQ(2U, theString.find_first_of('l'));
+ EXPECT_EQ(1U, theString.find_first_of("el"));
+ EXPECT_EQ(StringRef::npos, theString.find_first_of("xyz"));
+
+ EXPECT_EQ(1U, theString.find_first_not_of('h'));
+ EXPECT_EQ(4U, theString.find_first_not_of("hel"));
+ EXPECT_EQ(StringRef::npos, theString.find_first_not_of("hello"));
+
+ theString = "hellx xello hell ello world foo bar hello";
+ EXPECT_EQ(36U, theString.find("hello"));
+ EXPECT_EQ(28U, theString.find("foo"));
+ EXPECT_EQ(12U, theString.find("hell", 2));
+ EXPECT_EQ(0U, theString.find(""));
+}
+
+TEST_F(SmallStringTest, Count) {
+ theString = "hello";
+ EXPECT_EQ(2U, theString.count('l'));
+ EXPECT_EQ(1U, theString.count('o'));
+ EXPECT_EQ(0U, theString.count('z'));
+ EXPECT_EQ(0U, theString.count("helloworld"));
+ EXPECT_EQ(1U, theString.count("hello"));
+ EXPECT_EQ(1U, theString.count("ello"));
+ EXPECT_EQ(0U, theString.count("zz"));
+}
+
+TEST_F(SmallStringTest, Realloc) {
+ theString = "abcd";
+ theString.reserve(100);
+ EXPECT_EQ("abcd", theString);
+ unsigned const N = 100000;
+ theString.reserve(N);
+ for (unsigned i = 0; i < N - 4; ++i)
+ theString.push_back('y');
+ EXPECT_EQ("abcdyyy", theString.slice(0, 7));
+}
+
+TEST(StringRefTest, Comparisons) {
+ EXPECT_EQ(-1, SmallString<10>("aab").compare("aad"));
+ EXPECT_EQ( 0, SmallString<10>("aab").compare("aab"));
+ EXPECT_EQ( 1, SmallString<10>("aab").compare("aaa"));
+ EXPECT_EQ(-1, SmallString<10>("aab").compare("aabb"));
+ EXPECT_EQ( 1, SmallString<10>("aab").compare("aa"));
+ EXPECT_EQ( 1, SmallString<10>("\xFF").compare("\1"));
+
+ EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aAd"));
+ EXPECT_EQ( 0, SmallString<10>("AaB").compare_lower("aab"));
+ EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("AAA"));
+ EXPECT_EQ(-1, SmallString<10>("AaB").compare_lower("aaBb"));
+ EXPECT_EQ( 1, SmallString<10>("AaB").compare_lower("aA"));
+ EXPECT_EQ( 1, SmallString<10>("\xFF").compare_lower("\1"));
+
+ EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aad"));
+ EXPECT_EQ( 0, SmallString<10>("aab").compare_numeric("aab"));
+ EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aaa"));
+ EXPECT_EQ(-1, SmallString<10>("aab").compare_numeric("aabb"));
+ EXPECT_EQ( 1, SmallString<10>("aab").compare_numeric("aa"));
+ EXPECT_EQ(-1, SmallString<10>("1").compare_numeric("10"));
+ EXPECT_EQ( 0, SmallString<10>("10").compare_numeric("10"));
+ EXPECT_EQ( 0, SmallString<10>("10a").compare_numeric("10a"));
+ EXPECT_EQ( 1, SmallString<10>("2").compare_numeric("1"));
+ EXPECT_EQ( 0, SmallString<10>("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty"));
+ EXPECT_EQ( 1, SmallString<10>("\xFF").compare_numeric("\1"));
+ EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V1_q0"));
+ EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V16"));
+ EXPECT_EQ(-1, SmallString<10>("V8_q0").compare_numeric("V16"));
+ EXPECT_EQ( 1, SmallString<10>("V16").compare_numeric("V8_q0"));
+ EXPECT_EQ(-1, SmallString<10>("V1_q0").compare_numeric("V8_q0"));
+ EXPECT_EQ( 1, SmallString<10>("V8_q0").compare_numeric("V1_q0"));
+}
+
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/SmallVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/SmallVectorTest.cpp
new file mode 100644
index 0000000..9c501bb
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -0,0 +1,998 @@
+//===- llvm/unittest/ADT/SmallVectorTest.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SmallVector unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Compiler.h"
+#include "gtest/gtest.h"
+#include <list>
+#include <stdarg.h>
+
+using namespace llvm;
+
+namespace {
+
+/// A helper class that counts the total number of constructor and
+/// destructor calls.
+class Constructable {
+private:
+ static int numConstructorCalls;
+ static int numMoveConstructorCalls;
+ static int numCopyConstructorCalls;
+ static int numDestructorCalls;
+ static int numAssignmentCalls;
+ static int numMoveAssignmentCalls;
+ static int numCopyAssignmentCalls;
+
+ bool constructed;
+ int value;
+
+public:
+ Constructable() : constructed(true), value(0) {
+ ++numConstructorCalls;
+ }
+
+ Constructable(int val) : constructed(true), value(val) {
+ ++numConstructorCalls;
+ }
+
+ Constructable(const Constructable & src) : constructed(true) {
+ value = src.value;
+ ++numConstructorCalls;
+ ++numCopyConstructorCalls;
+ }
+
+ Constructable(Constructable && src) : constructed(true) {
+ value = src.value;
+ ++numConstructorCalls;
+ ++numMoveConstructorCalls;
+ }
+
+ ~Constructable() {
+ EXPECT_TRUE(constructed);
+ ++numDestructorCalls;
+ constructed = false;
+ }
+
+ Constructable & operator=(const Constructable & src) {
+ EXPECT_TRUE(constructed);
+ value = src.value;
+ ++numAssignmentCalls;
+ ++numCopyAssignmentCalls;
+ return *this;
+ }
+
+ Constructable & operator=(Constructable && src) {
+ EXPECT_TRUE(constructed);
+ value = src.value;
+ ++numAssignmentCalls;
+ ++numMoveAssignmentCalls;
+ return *this;
+ }
+
+ int getValue() const {
+ return abs(value);
+ }
+
+ static void reset() {
+ numConstructorCalls = 0;
+ numMoveConstructorCalls = 0;
+ numCopyConstructorCalls = 0;
+ numDestructorCalls = 0;
+ numAssignmentCalls = 0;
+ numMoveAssignmentCalls = 0;
+ numCopyAssignmentCalls = 0;
+ }
+
+ static int getNumConstructorCalls() {
+ return numConstructorCalls;
+ }
+
+ static int getNumMoveConstructorCalls() {
+ return numMoveConstructorCalls;
+ }
+
+ static int getNumCopyConstructorCalls() {
+ return numCopyConstructorCalls;
+ }
+
+ static int getNumDestructorCalls() {
+ return numDestructorCalls;
+ }
+
+ static int getNumAssignmentCalls() {
+ return numAssignmentCalls;
+ }
+
+ static int getNumMoveAssignmentCalls() {
+ return numMoveAssignmentCalls;
+ }
+
+ static int getNumCopyAssignmentCalls() {
+ return numCopyAssignmentCalls;
+ }
+
+ friend bool operator==(const Constructable & c0, const Constructable & c1) {
+ return c0.getValue() == c1.getValue();
+ }
+
+ friend bool LLVM_ATTRIBUTE_UNUSED
+ operator!=(const Constructable & c0, const Constructable & c1) {
+ return c0.getValue() != c1.getValue();
+ }
+};
+
+int Constructable::numConstructorCalls;
+int Constructable::numCopyConstructorCalls;
+int Constructable::numMoveConstructorCalls;
+int Constructable::numDestructorCalls;
+int Constructable::numAssignmentCalls;
+int Constructable::numCopyAssignmentCalls;
+int Constructable::numMoveAssignmentCalls;
+
+struct NonCopyable {
+ NonCopyable() {}
+ NonCopyable(NonCopyable &&) {}
+ NonCopyable &operator=(NonCopyable &&) { return *this; }
+private:
+ NonCopyable(const NonCopyable &) = delete;
+ NonCopyable &operator=(const NonCopyable &) = delete;
+};
+
+LLVM_ATTRIBUTE_USED void CompileTest() {
+ SmallVector<NonCopyable, 0> V;
+ V.resize(42);
+}
+
+class SmallVectorTestBase : public testing::Test {
+protected:
+ void SetUp() override { Constructable::reset(); }
+
+ template <typename VectorT>
+ void assertEmpty(VectorT & v) {
+ // Size tests
+ EXPECT_EQ(0u, v.size());
+ EXPECT_TRUE(v.empty());
+
+ // Iterator tests
+ EXPECT_TRUE(v.begin() == v.end());
+ }
+
+ // Assert that v contains the specified values, in order.
+ template <typename VectorT>
+ void assertValuesInOrder(VectorT & v, size_t size, ...) {
+ EXPECT_EQ(size, v.size());
+
+ va_list ap;
+ va_start(ap, size);
+ for (size_t i = 0; i < size; ++i) {
+ int value = va_arg(ap, int);
+ EXPECT_EQ(value, v[i].getValue());
+ }
+
+ va_end(ap);
+ }
+
+ // Generate a sequence of values to initialize the vector.
+ template <typename VectorT>
+ void makeSequence(VectorT & v, int start, int end) {
+ for (int i = start; i <= end; ++i) {
+ v.push_back(Constructable(i));
+ }
+ }
+};
+
+// Test fixture class
+template <typename VectorT>
+class SmallVectorTest : public SmallVectorTestBase {
+protected:
+ VectorT theVector;
+ VectorT otherVector;
+};
+
+
+typedef ::testing::Types<SmallVector<Constructable, 0>,
+ SmallVector<Constructable, 1>,
+ SmallVector<Constructable, 2>,
+ SmallVector<Constructable, 4>,
+ SmallVector<Constructable, 5>
+ > SmallVectorTestTypes;
+TYPED_TEST_CASE(SmallVectorTest, SmallVectorTestTypes);
+
+// Constructor test.
+TYPED_TEST(SmallVectorTest, ConstructorNonIterTest) {
+ SCOPED_TRACE("ConstructorTest");
+ this->theVector = SmallVector<Constructable, 2>(2, 2);
+ this->assertValuesInOrder(this->theVector, 2u, 2, 2);
+}
+
+// Constructor test.
+TYPED_TEST(SmallVectorTest, ConstructorIterTest) {
+ SCOPED_TRACE("ConstructorTest");
+ int arr[] = {1, 2, 3};
+ this->theVector =
+ SmallVector<Constructable, 4>(std::begin(arr), std::end(arr));
+ this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
+}
+
+// New vector test.
+TYPED_TEST(SmallVectorTest, EmptyVectorTest) {
+ SCOPED_TRACE("EmptyVectorTest");
+ this->assertEmpty(this->theVector);
+ EXPECT_TRUE(this->theVector.rbegin() == this->theVector.rend());
+ EXPECT_EQ(0, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(0, Constructable::getNumDestructorCalls());
+}
+
+// Simple insertions and deletions.
+TYPED_TEST(SmallVectorTest, PushPopTest) {
+ SCOPED_TRACE("PushPopTest");
+
+ // Track whether the vector will potentially have to grow.
+ bool RequiresGrowth = this->theVector.capacity() < 3;
+
+ // Push an element
+ this->theVector.push_back(Constructable(1));
+
+ // Size tests
+ this->assertValuesInOrder(this->theVector, 1u, 1);
+ EXPECT_FALSE(this->theVector.begin() == this->theVector.end());
+ EXPECT_FALSE(this->theVector.empty());
+
+ // Push another element
+ this->theVector.push_back(Constructable(2));
+ this->assertValuesInOrder(this->theVector, 2u, 1, 2);
+
+ // Insert at beginning
+ this->theVector.insert(this->theVector.begin(), this->theVector[1]);
+ this->assertValuesInOrder(this->theVector, 3u, 2, 1, 2);
+
+ // Pop one element
+ this->theVector.pop_back();
+ this->assertValuesInOrder(this->theVector, 2u, 2, 1);
+
+ // Pop remaining elements
+ this->theVector.pop_back();
+ this->theVector.pop_back();
+ this->assertEmpty(this->theVector);
+
+ // Check number of constructor calls. Should be 2 for each list element,
+ // one for the argument to push_back, one for the argument to insert,
+ // and one for the list element itself.
+ if (!RequiresGrowth) {
+ EXPECT_EQ(5, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(5, Constructable::getNumDestructorCalls());
+ } else {
+ // If we had to grow the vector, these only have a lower bound, but should
+ // always be equal.
+ EXPECT_LE(5, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(Constructable::getNumConstructorCalls(),
+ Constructable::getNumDestructorCalls());
+ }
+}
+
+// Clear test.
+TYPED_TEST(SmallVectorTest, ClearTest) {
+ SCOPED_TRACE("ClearTest");
+
+ this->theVector.reserve(2);
+ this->makeSequence(this->theVector, 1, 2);
+ this->theVector.clear();
+
+ this->assertEmpty(this->theVector);
+ EXPECT_EQ(4, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(4, Constructable::getNumDestructorCalls());
+}
+
+// Resize smaller test.
+TYPED_TEST(SmallVectorTest, ResizeShrinkTest) {
+ SCOPED_TRACE("ResizeShrinkTest");
+
+ this->theVector.reserve(3);
+ this->makeSequence(this->theVector, 1, 3);
+ this->theVector.resize(1);
+
+ this->assertValuesInOrder(this->theVector, 1u, 1);
+ EXPECT_EQ(6, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(5, Constructable::getNumDestructorCalls());
+}
+
+// Resize bigger test.
+TYPED_TEST(SmallVectorTest, ResizeGrowTest) {
+ SCOPED_TRACE("ResizeGrowTest");
+
+ this->theVector.resize(2);
+
+ EXPECT_EQ(2, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(0, Constructable::getNumDestructorCalls());
+ EXPECT_EQ(2u, this->theVector.size());
+}
+
+TYPED_TEST(SmallVectorTest, ResizeWithElementsTest) {
+ this->theVector.resize(2);
+
+ Constructable::reset();
+
+ this->theVector.resize(4);
+
+ size_t Ctors = Constructable::getNumConstructorCalls();
+ EXPECT_TRUE(Ctors == 2 || Ctors == 4);
+ size_t MoveCtors = Constructable::getNumMoveConstructorCalls();
+ EXPECT_TRUE(MoveCtors == 0 || MoveCtors == 2);
+ size_t Dtors = Constructable::getNumDestructorCalls();
+ EXPECT_TRUE(Dtors == 0 || Dtors == 2);
+}
+
+// Resize with fill value.
+TYPED_TEST(SmallVectorTest, ResizeFillTest) {
+ SCOPED_TRACE("ResizeFillTest");
+
+ this->theVector.resize(3, Constructable(77));
+ this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
+}
+
+// Overflow past fixed size.
+TYPED_TEST(SmallVectorTest, OverflowTest) {
+ SCOPED_TRACE("OverflowTest");
+
+ // Push more elements than the fixed size.
+ this->makeSequence(this->theVector, 1, 10);
+
+ // Test size and values.
+ EXPECT_EQ(10u, this->theVector.size());
+ for (int i = 0; i < 10; ++i) {
+ EXPECT_EQ(i+1, this->theVector[i].getValue());
+ }
+
+ // Now resize back to fixed size.
+ this->theVector.resize(1);
+
+ this->assertValuesInOrder(this->theVector, 1u, 1);
+}
+
+// Iteration tests.
+TYPED_TEST(SmallVectorTest, IterationTest) {
+ this->makeSequence(this->theVector, 1, 2);
+
+ // Forward Iteration
+ typename TypeParam::iterator it = this->theVector.begin();
+ EXPECT_TRUE(*it == this->theVector.front());
+ EXPECT_TRUE(*it == this->theVector[0]);
+ EXPECT_EQ(1, it->getValue());
+ ++it;
+ EXPECT_TRUE(*it == this->theVector[1]);
+ EXPECT_TRUE(*it == this->theVector.back());
+ EXPECT_EQ(2, it->getValue());
+ ++it;
+ EXPECT_TRUE(it == this->theVector.end());
+ --it;
+ EXPECT_TRUE(*it == this->theVector[1]);
+ EXPECT_EQ(2, it->getValue());
+ --it;
+ EXPECT_TRUE(*it == this->theVector[0]);
+ EXPECT_EQ(1, it->getValue());
+
+ // Reverse Iteration
+ typename TypeParam::reverse_iterator rit = this->theVector.rbegin();
+ EXPECT_TRUE(*rit == this->theVector[1]);
+ EXPECT_EQ(2, rit->getValue());
+ ++rit;
+ EXPECT_TRUE(*rit == this->theVector[0]);
+ EXPECT_EQ(1, rit->getValue());
+ ++rit;
+ EXPECT_TRUE(rit == this->theVector.rend());
+ --rit;
+ EXPECT_TRUE(*rit == this->theVector[0]);
+ EXPECT_EQ(1, rit->getValue());
+ --rit;
+ EXPECT_TRUE(*rit == this->theVector[1]);
+ EXPECT_EQ(2, rit->getValue());
+}
+
+// Swap test.
+TYPED_TEST(SmallVectorTest, SwapTest) {
+ SCOPED_TRACE("SwapTest");
+
+ this->makeSequence(this->theVector, 1, 2);
+ std::swap(this->theVector, this->otherVector);
+
+ this->assertEmpty(this->theVector);
+ this->assertValuesInOrder(this->otherVector, 2u, 1, 2);
+}
+
+// Append test
+TYPED_TEST(SmallVectorTest, AppendTest) {
+ SCOPED_TRACE("AppendTest");
+
+ this->makeSequence(this->otherVector, 2, 3);
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.append(this->otherVector.begin(), this->otherVector.end());
+
+ this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
+}
+
+// Append repeated test
+TYPED_TEST(SmallVectorTest, AppendRepeatedTest) {
+ SCOPED_TRACE("AppendRepeatedTest");
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.append(2, Constructable(77));
+ this->assertValuesInOrder(this->theVector, 3u, 1, 77, 77);
+}
+
+// Append test
+TYPED_TEST(SmallVectorTest, AppendNonIterTest) {
+ SCOPED_TRACE("AppendRepeatedTest");
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.append(2, 7);
+ this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
+}
+
+struct output_iterator {
+ typedef std::output_iterator_tag iterator_category;
+ typedef int value_type;
+ typedef int difference_type;
+ typedef value_type *pointer;
+ typedef value_type &reference;
+ operator int() { return 2; }
+ operator Constructable() { return 7; }
+};
+
+TYPED_TEST(SmallVectorTest, AppendRepeatedNonForwardIterator) {
+ SCOPED_TRACE("AppendRepeatedTest");
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.append(output_iterator(), output_iterator());
+ this->assertValuesInOrder(this->theVector, 3u, 1, 7, 7);
+}
+
+// Assign test
+TYPED_TEST(SmallVectorTest, AssignTest) {
+ SCOPED_TRACE("AssignTest");
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.assign(2, Constructable(77));
+ this->assertValuesInOrder(this->theVector, 2u, 77, 77);
+}
+
+// Assign test
+TYPED_TEST(SmallVectorTest, AssignRangeTest) {
+ SCOPED_TRACE("AssignTest");
+
+ this->theVector.push_back(Constructable(1));
+ int arr[] = {1, 2, 3};
+ this->theVector.assign(std::begin(arr), std::end(arr));
+ this->assertValuesInOrder(this->theVector, 3u, 1, 2, 3);
+}
+
+// Assign test
+TYPED_TEST(SmallVectorTest, AssignNonIterTest) {
+ SCOPED_TRACE("AssignTest");
+
+ this->theVector.push_back(Constructable(1));
+ this->theVector.assign(2, 7);
+ this->assertValuesInOrder(this->theVector, 2u, 7, 7);
+}
+
+// Move-assign test
+TYPED_TEST(SmallVectorTest, MoveAssignTest) {
+ SCOPED_TRACE("MoveAssignTest");
+
+ // Set up our vector with a single element, but enough capacity for 4.
+ this->theVector.reserve(4);
+ this->theVector.push_back(Constructable(1));
+
+ // Set up the other vector with 2 elements.
+ this->otherVector.push_back(Constructable(2));
+ this->otherVector.push_back(Constructable(3));
+
+ // Move-assign from the other vector.
+ this->theVector = std::move(this->otherVector);
+
+ // Make sure we have the right result.
+ this->assertValuesInOrder(this->theVector, 2u, 2, 3);
+
+ // Make sure the # of constructor/destructor calls line up. There
+ // are two live objects after clearing the other vector.
+ this->otherVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls()-2,
+ Constructable::getNumDestructorCalls());
+
+ // There shouldn't be any live objects any more.
+ this->theVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls(),
+ Constructable::getNumDestructorCalls());
+}
+
+// Erase a single element
+TYPED_TEST(SmallVectorTest, EraseTest) {
+ SCOPED_TRACE("EraseTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+ const auto &theConstVector = this->theVector;
+ this->theVector.erase(theConstVector.begin());
+ this->assertValuesInOrder(this->theVector, 2u, 2, 3);
+}
+
+// Erase a range of elements
+TYPED_TEST(SmallVectorTest, EraseRangeTest) {
+ SCOPED_TRACE("EraseRangeTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+ const auto &theConstVector = this->theVector;
+ this->theVector.erase(theConstVector.begin(), theConstVector.begin() + 2);
+ this->assertValuesInOrder(this->theVector, 1u, 3);
+}
+
+// Insert a single element.
+TYPED_TEST(SmallVectorTest, InsertTest) {
+ SCOPED_TRACE("InsertTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+ typename TypeParam::iterator I =
+ this->theVector.insert(this->theVector.begin() + 1, Constructable(77));
+ EXPECT_EQ(this->theVector.begin() + 1, I);
+ this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
+}
+
+// Insert a copy of a single element.
+TYPED_TEST(SmallVectorTest, InsertCopy) {
+ SCOPED_TRACE("InsertTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+ Constructable C(77);
+ typename TypeParam::iterator I =
+ this->theVector.insert(this->theVector.begin() + 1, C);
+ EXPECT_EQ(this->theVector.begin() + 1, I);
+ this->assertValuesInOrder(this->theVector, 4u, 1, 77, 2, 3);
+}
+
+// Insert repeated elements.
+TYPED_TEST(SmallVectorTest, InsertRepeatedTest) {
+ SCOPED_TRACE("InsertRepeatedTest");
+
+ this->makeSequence(this->theVector, 1, 4);
+ Constructable::reset();
+ auto I =
+ this->theVector.insert(this->theVector.begin() + 1, 2, Constructable(16));
+ // Move construct the top element into newly allocated space, and optionally
+ // reallocate the whole buffer, move constructing into it.
+ // FIXME: This is inefficient, we shouldn't move things into newly allocated
+ // space, then move them up/around, there should only be 2 or 4 move
+ // constructions here.
+ EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
+ Constructable::getNumMoveConstructorCalls() == 6);
+ // Move assign the next two to shift them up and make a gap.
+ EXPECT_EQ(1, Constructable::getNumMoveAssignmentCalls());
+ // Copy construct the two new elements from the parameter.
+ EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
+ // All without any copy construction.
+ EXPECT_EQ(0, Constructable::getNumCopyConstructorCalls());
+ EXPECT_EQ(this->theVector.begin() + 1, I);
+ this->assertValuesInOrder(this->theVector, 6u, 1, 16, 16, 2, 3, 4);
+}
+
+TYPED_TEST(SmallVectorTest, InsertRepeatedNonIterTest) {
+ SCOPED_TRACE("InsertRepeatedTest");
+
+ this->makeSequence(this->theVector, 1, 4);
+ Constructable::reset();
+ auto I = this->theVector.insert(this->theVector.begin() + 1, 2, 7);
+ EXPECT_EQ(this->theVector.begin() + 1, I);
+ this->assertValuesInOrder(this->theVector, 6u, 1, 7, 7, 2, 3, 4);
+}
+
+TYPED_TEST(SmallVectorTest, InsertRepeatedAtEndTest) {
+ SCOPED_TRACE("InsertRepeatedTest");
+
+ this->makeSequence(this->theVector, 1, 4);
+ Constructable::reset();
+ auto I = this->theVector.insert(this->theVector.end(), 2, Constructable(16));
+ // Just copy construct them into newly allocated space
+ EXPECT_EQ(2, Constructable::getNumCopyConstructorCalls());
+ // Move everything across if reallocation is needed.
+ EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
+ Constructable::getNumMoveConstructorCalls() == 4);
+ // Without ever moving or copying anything else.
+ EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
+ EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
+
+ EXPECT_EQ(this->theVector.begin() + 4, I);
+ this->assertValuesInOrder(this->theVector, 6u, 1, 2, 3, 4, 16, 16);
+}
+
+TYPED_TEST(SmallVectorTest, InsertRepeatedEmptyTest) {
+ SCOPED_TRACE("InsertRepeatedTest");
+
+ this->makeSequence(this->theVector, 10, 15);
+
+ // Empty insert.
+ EXPECT_EQ(this->theVector.end(),
+ this->theVector.insert(this->theVector.end(),
+ 0, Constructable(42)));
+ EXPECT_EQ(this->theVector.begin() + 1,
+ this->theVector.insert(this->theVector.begin() + 1,
+ 0, Constructable(42)));
+}
+
+// Insert range.
+TYPED_TEST(SmallVectorTest, InsertRangeTest) {
+ SCOPED_TRACE("InsertRangeTest");
+
+ Constructable Arr[3] =
+ { Constructable(77), Constructable(77), Constructable(77) };
+
+ this->makeSequence(this->theVector, 1, 3);
+ Constructable::reset();
+ auto I = this->theVector.insert(this->theVector.begin() + 1, Arr, Arr + 3);
+ // Move construct the top 3 elements into newly allocated space.
+ // Possibly move the whole sequence into new space first.
+ // FIXME: This is inefficient, we shouldn't move things into newly allocated
+ // space, then move them up/around, there should only be 2 or 3 move
+ // constructions here.
+ EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 2 ||
+ Constructable::getNumMoveConstructorCalls() == 5);
+ // Copy assign the lower 2 new elements into existing space.
+ EXPECT_EQ(2, Constructable::getNumCopyAssignmentCalls());
+ // Copy construct the third element into newly allocated space.
+ EXPECT_EQ(1, Constructable::getNumCopyConstructorCalls());
+ EXPECT_EQ(this->theVector.begin() + 1, I);
+ this->assertValuesInOrder(this->theVector, 6u, 1, 77, 77, 77, 2, 3);
+}
+
+
+TYPED_TEST(SmallVectorTest, InsertRangeAtEndTest) {
+ SCOPED_TRACE("InsertRangeTest");
+
+ Constructable Arr[3] =
+ { Constructable(77), Constructable(77), Constructable(77) };
+
+ this->makeSequence(this->theVector, 1, 3);
+
+ // Insert at end.
+ Constructable::reset();
+ auto I = this->theVector.insert(this->theVector.end(), Arr, Arr+3);
+ // Copy construct the 3 elements into new space at the top.
+ EXPECT_EQ(3, Constructable::getNumCopyConstructorCalls());
+ // Don't copy/move anything else.
+ EXPECT_EQ(0, Constructable::getNumCopyAssignmentCalls());
+ // Reallocation might occur, causing all elements to be moved into the new
+ // buffer.
+ EXPECT_TRUE(Constructable::getNumMoveConstructorCalls() == 0 ||
+ Constructable::getNumMoveConstructorCalls() == 3);
+ EXPECT_EQ(0, Constructable::getNumMoveAssignmentCalls());
+ EXPECT_EQ(this->theVector.begin() + 3, I);
+ this->assertValuesInOrder(this->theVector, 6u,
+ 1, 2, 3, 77, 77, 77);
+}
+
+TYPED_TEST(SmallVectorTest, InsertEmptyRangeTest) {
+ SCOPED_TRACE("InsertRangeTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+
+ // Empty insert.
+ EXPECT_EQ(this->theVector.end(),
+ this->theVector.insert(this->theVector.end(),
+ this->theVector.begin(),
+ this->theVector.begin()));
+ EXPECT_EQ(this->theVector.begin() + 1,
+ this->theVector.insert(this->theVector.begin() + 1,
+ this->theVector.begin(),
+ this->theVector.begin()));
+}
+
+// Comparison tests.
+TYPED_TEST(SmallVectorTest, ComparisonTest) {
+ SCOPED_TRACE("ComparisonTest");
+
+ this->makeSequence(this->theVector, 1, 3);
+ this->makeSequence(this->otherVector, 1, 3);
+
+ EXPECT_TRUE(this->theVector == this->otherVector);
+ EXPECT_FALSE(this->theVector != this->otherVector);
+
+ this->otherVector.clear();
+ this->makeSequence(this->otherVector, 2, 4);
+
+ EXPECT_FALSE(this->theVector == this->otherVector);
+ EXPECT_TRUE(this->theVector != this->otherVector);
+}
+
+// Constant vector tests.
+TYPED_TEST(SmallVectorTest, ConstVectorTest) {
+ const TypeParam constVector;
+
+ EXPECT_EQ(0u, constVector.size());
+ EXPECT_TRUE(constVector.empty());
+ EXPECT_TRUE(constVector.begin() == constVector.end());
+}
+
+// Direct array access.
+TYPED_TEST(SmallVectorTest, DirectVectorTest) {
+ EXPECT_EQ(0u, this->theVector.size());
+ this->theVector.reserve(4);
+ EXPECT_LE(4u, this->theVector.capacity());
+ EXPECT_EQ(0, Constructable::getNumConstructorCalls());
+ this->theVector.push_back(1);
+ this->theVector.push_back(2);
+ this->theVector.push_back(3);
+ this->theVector.push_back(4);
+ EXPECT_EQ(4u, this->theVector.size());
+ EXPECT_EQ(8, Constructable::getNumConstructorCalls());
+ EXPECT_EQ(1, this->theVector[0].getValue());
+ EXPECT_EQ(2, this->theVector[1].getValue());
+ EXPECT_EQ(3, this->theVector[2].getValue());
+ EXPECT_EQ(4, this->theVector[3].getValue());
+}
+
+TYPED_TEST(SmallVectorTest, IteratorTest) {
+ std::list<int> L;
+ this->theVector.insert(this->theVector.end(), L.begin(), L.end());
+}
+
+template <typename InvalidType> class DualSmallVectorsTest;
+
+template <typename VectorT1, typename VectorT2>
+class DualSmallVectorsTest<std::pair<VectorT1, VectorT2>> : public SmallVectorTestBase {
+protected:
+ VectorT1 theVector;
+ VectorT2 otherVector;
+
+ template <typename T, unsigned N>
+ static unsigned NumBuiltinElts(const SmallVector<T, N>&) { return N; }
+};
+
+typedef ::testing::Types<
+ // Small mode -> Small mode.
+ std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 4>>,
+ // Small mode -> Big mode.
+ std::pair<SmallVector<Constructable, 4>, SmallVector<Constructable, 2>>,
+ // Big mode -> Small mode.
+ std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 4>>,
+ // Big mode -> Big mode.
+ std::pair<SmallVector<Constructable, 2>, SmallVector<Constructable, 2>>
+ > DualSmallVectorTestTypes;
+
+TYPED_TEST_CASE(DualSmallVectorsTest, DualSmallVectorTestTypes);
+
+TYPED_TEST(DualSmallVectorsTest, MoveAssignment) {
+ SCOPED_TRACE("MoveAssignTest-DualVectorTypes");
+
+ // Set up our vector with four elements.
+ for (unsigned I = 0; I < 4; ++I)
+ this->otherVector.push_back(Constructable(I));
+
+ const Constructable *OrigDataPtr = this->otherVector.data();
+
+ // Move-assign from the other vector.
+ this->theVector =
+ std::move(static_cast<SmallVectorImpl<Constructable>&>(this->otherVector));
+
+ // Make sure we have the right result.
+ this->assertValuesInOrder(this->theVector, 4u, 0, 1, 2, 3);
+
+ // Make sure the # of constructor/destructor calls line up. There
+ // are two live objects after clearing the other vector.
+ this->otherVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls()-4,
+ Constructable::getNumDestructorCalls());
+
+ // If the source vector (otherVector) was in small-mode, assert that we just
+ // moved the data pointer over.
+ EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 ||
+ this->theVector.data() == OrigDataPtr);
+
+ // There shouldn't be any live objects any more.
+ this->theVector.clear();
+ EXPECT_EQ(Constructable::getNumConstructorCalls(),
+ Constructable::getNumDestructorCalls());
+
+ // We shouldn't have copied anything in this whole process.
+ EXPECT_EQ(Constructable::getNumCopyConstructorCalls(), 0);
+}
+
+struct notassignable {
+ int &x;
+ notassignable(int &x) : x(x) {}
+};
+
+TEST(SmallVectorCustomTest, NoAssignTest) {
+ int x = 0;
+ SmallVector<notassignable, 2> vec;
+ vec.push_back(notassignable(x));
+ x = 42;
+ EXPECT_EQ(42, vec.pop_back_val().x);
+}
+
+struct MovedFrom {
+ bool hasValue;
+ MovedFrom() : hasValue(true) {
+ }
+ MovedFrom(MovedFrom&& m) : hasValue(m.hasValue) {
+ m.hasValue = false;
+ }
+ MovedFrom &operator=(MovedFrom&& m) {
+ hasValue = m.hasValue;
+ m.hasValue = false;
+ return *this;
+ }
+};
+
+TEST(SmallVectorTest, MidInsert) {
+ SmallVector<MovedFrom, 3> v;
+ v.push_back(MovedFrom());
+ v.insert(v.begin(), MovedFrom());
+ for (MovedFrom &m : v)
+ EXPECT_TRUE(m.hasValue);
+}
+
+enum EmplaceableArgState {
+ EAS_Defaulted,
+ EAS_Arg,
+ EAS_LValue,
+ EAS_RValue,
+ EAS_Failure
+};
+template <int I> struct EmplaceableArg {
+ EmplaceableArgState State;
+ EmplaceableArg() : State(EAS_Defaulted) {}
+ EmplaceableArg(EmplaceableArg &&X)
+ : State(X.State == EAS_Arg ? EAS_RValue : EAS_Failure) {}
+ EmplaceableArg(EmplaceableArg &X)
+ : State(X.State == EAS_Arg ? EAS_LValue : EAS_Failure) {}
+
+ explicit EmplaceableArg(bool) : State(EAS_Arg) {}
+
+private:
+ EmplaceableArg &operator=(EmplaceableArg &&) = delete;
+ EmplaceableArg &operator=(const EmplaceableArg &) = delete;
+};
+
+enum EmplaceableState { ES_Emplaced, ES_Moved };
+struct Emplaceable {
+ EmplaceableArg<0> A0;
+ EmplaceableArg<1> A1;
+ EmplaceableArg<2> A2;
+ EmplaceableArg<3> A3;
+ EmplaceableState State;
+
+ Emplaceable() : State(ES_Emplaced) {}
+
+ template <class A0Ty>
+ explicit Emplaceable(A0Ty &&A0)
+ : A0(std::forward<A0Ty>(A0)), State(ES_Emplaced) {}
+
+ template <class A0Ty, class A1Ty>
+ Emplaceable(A0Ty &&A0, A1Ty &&A1)
+ : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
+ State(ES_Emplaced) {}
+
+ template <class A0Ty, class A1Ty, class A2Ty>
+ Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2)
+ : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
+ A2(std::forward<A2Ty>(A2)), State(ES_Emplaced) {}
+
+ template <class A0Ty, class A1Ty, class A2Ty, class A3Ty>
+ Emplaceable(A0Ty &&A0, A1Ty &&A1, A2Ty &&A2, A3Ty &&A3)
+ : A0(std::forward<A0Ty>(A0)), A1(std::forward<A1Ty>(A1)),
+ A2(std::forward<A2Ty>(A2)), A3(std::forward<A3Ty>(A3)),
+ State(ES_Emplaced) {}
+
+ Emplaceable(Emplaceable &&) : State(ES_Moved) {}
+ Emplaceable &operator=(Emplaceable &&) {
+ State = ES_Moved;
+ return *this;
+ }
+
+private:
+ Emplaceable(const Emplaceable &) = delete;
+ Emplaceable &operator=(const Emplaceable &) = delete;
+};
+
+TEST(SmallVectorTest, EmplaceBack) {
+ EmplaceableArg<0> A0(true);
+ EmplaceableArg<1> A1(true);
+ EmplaceableArg<2> A2(true);
+ EmplaceableArg<3> A3(true);
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back();
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
+ }
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back(std::move(A0));
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_RValue);
+ EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
+ }
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back(A0);
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_LValue);
+ EXPECT_TRUE(V.back().A1.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
+ }
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back(A0, A1);
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_LValue);
+ EXPECT_TRUE(V.back().A1.State == EAS_LValue);
+ EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
+ }
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back(std::move(A0), std::move(A1));
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_RValue);
+ EXPECT_TRUE(V.back().A1.State == EAS_RValue);
+ EXPECT_TRUE(V.back().A2.State == EAS_Defaulted);
+ EXPECT_TRUE(V.back().A3.State == EAS_Defaulted);
+ }
+ {
+ SmallVector<Emplaceable, 3> V;
+ V.emplace_back(std::move(A0), A1, std::move(A2), A3);
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_TRUE(V.back().State == ES_Emplaced);
+ EXPECT_TRUE(V.back().A0.State == EAS_RValue);
+ EXPECT_TRUE(V.back().A1.State == EAS_LValue);
+ EXPECT_TRUE(V.back().A2.State == EAS_RValue);
+ EXPECT_TRUE(V.back().A3.State == EAS_LValue);
+ }
+ {
+ SmallVector<int, 1> V;
+ V.emplace_back();
+ V.emplace_back(42);
+ EXPECT_EQ(2U, V.size());
+ EXPECT_EQ(0, V[0]);
+ EXPECT_EQ(42, V[1]);
+ }
+}
+
+TEST(SmallVectorTest, InitializerList) {
+ SmallVector<int, 2> V1 = {};
+ EXPECT_TRUE(V1.empty());
+ V1 = {0, 0};
+ EXPECT_TRUE(makeArrayRef(V1).equals({0, 0}));
+ V1 = {-1, -1};
+ EXPECT_TRUE(makeArrayRef(V1).equals({-1, -1}));
+
+ SmallVector<int, 2> V2 = {1, 2, 3, 4};
+ EXPECT_TRUE(makeArrayRef(V2).equals({1, 2, 3, 4}));
+ V2.assign({4});
+ EXPECT_TRUE(makeArrayRef(V2).equals({4}));
+ V2.append({3, 2});
+ EXPECT_TRUE(makeArrayRef(V2).equals({4, 3, 2}));
+ V2.insert(V2.begin() + 1, 5);
+ EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2}));
+}
+
+} // end namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SparseBitVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/SparseBitVectorTest.cpp
new file mode 100644
index 0000000..7675dda
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SparseBitVectorTest.cpp
@@ -0,0 +1,190 @@
+//===- llvm/unittest/ADT/SparseBitVectorTest.cpp - SparseBitVector tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SparseBitVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(SparseBitVectorTest, TrivialOperation) {
+ SparseBitVector<> Vec;
+ EXPECT_EQ(0U, Vec.count());
+ EXPECT_FALSE(Vec.test(17));
+ Vec.set(5);
+ EXPECT_TRUE(Vec.test(5));
+ EXPECT_FALSE(Vec.test(17));
+ Vec.reset(6);
+ EXPECT_TRUE(Vec.test(5));
+ EXPECT_FALSE(Vec.test(6));
+ Vec.reset(5);
+ EXPECT_FALSE(Vec.test(5));
+ EXPECT_TRUE(Vec.test_and_set(17));
+ EXPECT_FALSE(Vec.test_and_set(17));
+ EXPECT_TRUE(Vec.test(17));
+ Vec.clear();
+ EXPECT_FALSE(Vec.test(17));
+
+ Vec.set(5);
+ const SparseBitVector<> ConstVec = Vec;
+ EXPECT_TRUE(ConstVec.test(5));
+ EXPECT_FALSE(ConstVec.test(17));
+
+ Vec.set(1337);
+ EXPECT_TRUE(Vec.test(1337));
+ Vec = ConstVec;
+ EXPECT_FALSE(Vec.test(1337));
+
+ Vec.set(1337);
+ EXPECT_FALSE(Vec.empty());
+ SparseBitVector<> MovedVec(std::move(Vec));
+ EXPECT_TRUE(Vec.empty());
+ EXPECT_TRUE(MovedVec.test(5));
+ EXPECT_TRUE(MovedVec.test(1337));
+
+ Vec = std::move(MovedVec);
+ EXPECT_TRUE(MovedVec.empty());
+ EXPECT_FALSE(Vec.empty());
+}
+
+TEST(SparseBitVectorTest, IntersectWith) {
+ SparseBitVector<> Vec, Other;
+
+ Vec.set(1);
+ Other.set(1);
+ EXPECT_FALSE(Vec &= Other);
+ EXPECT_TRUE(Vec.test(1));
+
+ Vec.clear();
+ Vec.set(5);
+ Other.clear();
+ Other.set(6);
+ EXPECT_TRUE(Vec &= Other);
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.clear();
+ Vec.set(5);
+ Other.clear();
+ Other.set(225);
+ EXPECT_TRUE(Vec &= Other);
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.clear();
+ Vec.set(225);
+ Other.clear();
+ Other.set(5);
+ EXPECT_TRUE(Vec &= Other);
+ EXPECT_TRUE(Vec.empty());
+}
+
+TEST(SparseBitVectorTest, SelfAssignment) {
+ SparseBitVector<> Vec, Other;
+
+ Vec.set(23);
+ Vec.set(234);
+ Vec = static_cast<SparseBitVector<> &>(Vec);
+ EXPECT_TRUE(Vec.test(23));
+ EXPECT_TRUE(Vec.test(234));
+
+ Vec.clear();
+ Vec.set(17);
+ Vec.set(256);
+ EXPECT_FALSE(Vec |= Vec);
+ EXPECT_TRUE(Vec.test(17));
+ EXPECT_TRUE(Vec.test(256));
+
+ Vec.clear();
+ Vec.set(56);
+ Vec.set(517);
+ EXPECT_FALSE(Vec &= Vec);
+ EXPECT_TRUE(Vec.test(56));
+ EXPECT_TRUE(Vec.test(517));
+
+ Vec.clear();
+ Vec.set(99);
+ Vec.set(333);
+ EXPECT_TRUE(Vec.intersectWithComplement(Vec));
+ EXPECT_TRUE(Vec.empty());
+ EXPECT_FALSE(Vec.intersectWithComplement(Vec));
+
+ Vec.clear();
+ Vec.set(28);
+ Vec.set(43);
+ Vec.intersectWithComplement(Vec, Vec);
+ EXPECT_TRUE(Vec.empty());
+
+ Vec.clear();
+ Vec.set(42);
+ Vec.set(567);
+ Other.set(55);
+ Other.set(567);
+ Vec.intersectWithComplement(Vec, Other);
+ EXPECT_TRUE(Vec.test(42));
+ EXPECT_FALSE(Vec.test(567));
+
+ Vec.clear();
+ Vec.set(19);
+ Vec.set(21);
+ Other.clear();
+ Other.set(19);
+ Other.set(31);
+ Vec.intersectWithComplement(Other, Vec);
+ EXPECT_FALSE(Vec.test(19));
+ EXPECT_TRUE(Vec.test(31));
+
+ Vec.clear();
+ Vec.set(1);
+ Other.clear();
+ Other.set(59);
+ Other.set(75);
+ Vec.intersectWithComplement(Other, Other);
+ EXPECT_TRUE(Vec.empty());
+}
+
+TEST(SparseBitVectorTest, Find) {
+ SparseBitVector<> Vec;
+ Vec.set(1);
+ EXPECT_EQ(1, Vec.find_first());
+ EXPECT_EQ(1, Vec.find_last());
+
+ Vec.set(2);
+ EXPECT_EQ(1, Vec.find_first());
+ EXPECT_EQ(2, Vec.find_last());
+
+ Vec.set(0);
+ Vec.set(3);
+ EXPECT_EQ(0, Vec.find_first());
+ EXPECT_EQ(3, Vec.find_last());
+
+ Vec.reset(1);
+ Vec.reset(0);
+ Vec.reset(3);
+ EXPECT_EQ(2, Vec.find_first());
+ EXPECT_EQ(2, Vec.find_last());
+
+ // Set some large bits to ensure we are pulling bits from more than just a
+ // single bitword.
+ Vec.set(500);
+ Vec.set(2000);
+ Vec.set(3000);
+ Vec.set(4000);
+ Vec.reset(2);
+ EXPECT_EQ(500, Vec.find_first());
+ EXPECT_EQ(4000, Vec.find_last());
+
+ Vec.reset(500);
+ Vec.reset(3000);
+ Vec.reset(4000);
+ EXPECT_EQ(2000, Vec.find_first());
+ EXPECT_EQ(2000, Vec.find_last());
+
+ Vec.clear();
+}
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/SparseMultiSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/SparseMultiSetTest.cpp
new file mode 100644
index 0000000..032990e
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SparseMultiSetTest.cpp
@@ -0,0 +1,235 @@
+//===------ ADT/SparseSetTest.cpp - SparseSet unit tests - -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SparseMultiSet.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+typedef SparseMultiSet<unsigned> USet;
+
+// Empty set tests.
+TEST(SparseMultiSetTest, EmptySet) {
+ USet Set;
+ EXPECT_TRUE(Set.empty());
+ EXPECT_EQ(0u, Set.size());
+
+ Set.setUniverse(10);
+
+ // Lookups on empty set.
+ EXPECT_TRUE(Set.find(0) == Set.end());
+ EXPECT_TRUE(Set.find(9) == Set.end());
+
+ // Same thing on a const reference.
+ const USet &CSet = Set;
+ EXPECT_TRUE(CSet.empty());
+ EXPECT_EQ(0u, CSet.size());
+ EXPECT_TRUE(CSet.find(0) == CSet.end());
+ USet::const_iterator I = CSet.find(5);
+ EXPECT_TRUE(I == CSet.end());
+}
+
+// Single entry set tests.
+TEST(SparseMultiSetTest, SingleEntrySet) {
+ USet Set;
+ Set.setUniverse(10);
+ USet::iterator I = Set.insert(5);
+ EXPECT_TRUE(I != Set.end());
+ EXPECT_TRUE(*I == 5);
+
+ EXPECT_FALSE(Set.empty());
+ EXPECT_EQ(1u, Set.size());
+
+ EXPECT_TRUE(Set.find(0) == Set.end());
+ EXPECT_TRUE(Set.find(9) == Set.end());
+
+ EXPECT_FALSE(Set.contains(0));
+ EXPECT_TRUE(Set.contains(5));
+
+ // Extra insert.
+ I = Set.insert(5);
+ EXPECT_TRUE(I != Set.end());
+ EXPECT_TRUE(I == ++Set.find(5));
+ I--;
+ EXPECT_TRUE(I == Set.find(5));
+
+ // Erase non-existent element.
+ I = Set.find(1);
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_EQ(2u, Set.size());
+ EXPECT_EQ(5u, *Set.find(5));
+
+ // Erase iterator.
+ I = Set.find(5);
+ EXPECT_TRUE(I != Set.end());
+ I = Set.erase(I);
+ EXPECT_TRUE(I != Set.end());
+ I = Set.erase(I);
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_TRUE(Set.empty());
+}
+
+// Multiple entry set tests.
+TEST(SparseMultiSetTest, MultipleEntrySet) {
+ USet Set;
+ Set.setUniverse(10);
+
+ Set.insert(5);
+ Set.insert(5);
+ Set.insert(5);
+ Set.insert(3);
+ Set.insert(2);
+ Set.insert(1);
+ Set.insert(4);
+ EXPECT_EQ(7u, Set.size());
+
+ // Erase last element by key.
+ EXPECT_TRUE(Set.erase(Set.find(4)) == Set.end());
+ EXPECT_EQ(6u, Set.size());
+ EXPECT_FALSE(Set.contains(4));
+ EXPECT_TRUE(Set.find(4) == Set.end());
+
+ // Erase first element by key.
+ EXPECT_EQ(3u, Set.count(5));
+ EXPECT_TRUE(Set.find(5) != Set.end());
+ EXPECT_TRUE(Set.erase(Set.find(5)) != Set.end());
+ EXPECT_EQ(5u, Set.size());
+ EXPECT_EQ(2u, Set.count(5));
+
+ Set.insert(6);
+ Set.insert(7);
+ EXPECT_EQ(7u, Set.size());
+
+ // Erase tail by iterator.
+ EXPECT_TRUE(Set.getTail(6) == Set.getHead(6));
+ USet::iterator I = Set.erase(Set.find(6));
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_EQ(6u, Set.size());
+
+ // Erase tails by iterator.
+ EXPECT_EQ(2u, Set.count(5));
+ I = Set.getTail(5);
+ I = Set.erase(I);
+ EXPECT_TRUE(I == Set.end());
+ --I;
+ EXPECT_EQ(1u, Set.count(5));
+ EXPECT_EQ(5u, *I);
+ I = Set.erase(I);
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_EQ(0u, Set.count(5));
+
+ Set.insert(8);
+ Set.insert(8);
+ Set.insert(8);
+ Set.insert(8);
+ Set.insert(8);
+
+ // Erase all the 8s
+ EXPECT_EQ(5, std::distance(Set.getHead(8), Set.end()));
+ Set.eraseAll(8);
+ EXPECT_EQ(0, std::distance(Set.getHead(8), Set.end()));
+
+ // Clear and resize the universe.
+ Set.clear();
+ EXPECT_EQ(0u, Set.size());
+ EXPECT_FALSE(Set.contains(3));
+ Set.setUniverse(1000);
+
+ // Add more than 256 elements.
+ for (unsigned i = 100; i != 800; ++i)
+ Set.insert(i);
+
+ for (unsigned i = 0; i != 10; ++i)
+ Set.eraseAll(i);
+
+ for (unsigned i = 100; i != 800; ++i)
+ EXPECT_EQ(1u, Set.count(i));
+
+ EXPECT_FALSE(Set.contains(99));
+ EXPECT_FALSE(Set.contains(800));
+ EXPECT_EQ(700u, Set.size());
+}
+
+// Test out iterators
+TEST(SparseMultiSetTest, Iterators) {
+ USet Set;
+ Set.setUniverse(100);
+
+ Set.insert(0);
+ Set.insert(1);
+ Set.insert(2);
+ Set.insert(0);
+ Set.insert(1);
+ Set.insert(0);
+
+ USet::RangePair RangePair = Set.equal_range(0);
+ USet::iterator B = RangePair.first;
+ USet::iterator E = RangePair.second;
+
+ // Move the iterators around, going to end and coming back.
+ EXPECT_EQ(3, std::distance(B, E));
+ EXPECT_EQ(B, --(--(--E)));
+ EXPECT_EQ(++(++(++E)), Set.end());
+ EXPECT_EQ(B, --(--(--E)));
+ EXPECT_EQ(++(++(++E)), Set.end());
+
+ // Insert into the tail, and move around again
+ Set.insert(0);
+ EXPECT_EQ(B, --(--(--(--E))));
+ EXPECT_EQ(++(++(++(++E))), Set.end());
+ EXPECT_EQ(B, --(--(--(--E))));
+ EXPECT_EQ(++(++(++(++E))), Set.end());
+
+ // Erase a tail, and move around again
+ USet::iterator Erased = Set.erase(Set.getTail(0));
+ EXPECT_EQ(Erased, E);
+ EXPECT_EQ(B, --(--(--E)));
+
+ USet Set2;
+ Set2.setUniverse(11);
+ Set2.insert(3);
+ EXPECT_TRUE(!Set2.contains(0));
+ EXPECT_TRUE(!Set.contains(3));
+
+ EXPECT_EQ(Set2.getHead(3), Set2.getTail(3));
+ EXPECT_EQ(Set2.getHead(0), Set2.getTail(0));
+ B = Set2.find(3);
+ EXPECT_EQ(Set2.find(3), --(++B));
+}
+
+struct Alt {
+ unsigned Value;
+ explicit Alt(unsigned x) : Value(x) {}
+ unsigned getSparseSetIndex() const { return Value - 1000; }
+};
+
+TEST(SparseMultiSetTest, AltStructSet) {
+ typedef SparseMultiSet<Alt> ASet;
+ ASet Set;
+ Set.setUniverse(10);
+ Set.insert(Alt(1005));
+
+ ASet::iterator I = Set.find(5);
+ ASSERT_TRUE(I != Set.end());
+ EXPECT_EQ(1005u, I->Value);
+
+ Set.insert(Alt(1006));
+ Set.insert(Alt(1006));
+ I = Set.erase(Set.find(6));
+ ASSERT_TRUE(I != Set.end());
+ EXPECT_EQ(1006u, I->Value);
+ I = Set.erase(Set.find(6));
+ ASSERT_TRUE(I == Set.end());
+
+ EXPECT_TRUE(Set.contains(5));
+ EXPECT_FALSE(Set.contains(6));
+}
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/SparseSetTest.cpp b/src/llvm-project/llvm/unittests/ADT/SparseSetTest.cpp
new file mode 100644
index 0000000..4db7a7d
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/SparseSetTest.cpp
@@ -0,0 +1,206 @@
+//===------ ADT/SparseSetTest.cpp - SparseSet unit tests - -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SparseSet.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+typedef SparseSet<unsigned> USet;
+
+// Empty set tests.
+TEST(SparseSetTest, EmptySet) {
+ USet Set;
+ EXPECT_TRUE(Set.empty());
+ EXPECT_TRUE(Set.begin() == Set.end());
+ EXPECT_EQ(0u, Set.size());
+
+ Set.setUniverse(10);
+
+ // Lookups on empty set.
+ EXPECT_TRUE(Set.find(0) == Set.end());
+ EXPECT_TRUE(Set.find(9) == Set.end());
+
+ // Same thing on a const reference.
+ const USet &CSet = Set;
+ EXPECT_TRUE(CSet.empty());
+ EXPECT_TRUE(CSet.begin() == CSet.end());
+ EXPECT_EQ(0u, CSet.size());
+ EXPECT_TRUE(CSet.find(0) == CSet.end());
+ USet::const_iterator I = CSet.find(5);
+ EXPECT_TRUE(I == CSet.end());
+}
+
+// Single entry set tests.
+TEST(SparseSetTest, SingleEntrySet) {
+ USet Set;
+ Set.setUniverse(10);
+ std::pair<USet::iterator, bool> IP = Set.insert(5);
+ EXPECT_TRUE(IP.second);
+ EXPECT_TRUE(IP.first == Set.begin());
+
+ EXPECT_FALSE(Set.empty());
+ EXPECT_FALSE(Set.begin() == Set.end());
+ EXPECT_TRUE(Set.begin() + 1 == Set.end());
+ EXPECT_EQ(1u, Set.size());
+
+ EXPECT_TRUE(Set.find(0) == Set.end());
+ EXPECT_TRUE(Set.find(9) == Set.end());
+
+ EXPECT_FALSE(Set.count(0));
+ EXPECT_TRUE(Set.count(5));
+
+ // Redundant insert.
+ IP = Set.insert(5);
+ EXPECT_FALSE(IP.second);
+ EXPECT_TRUE(IP.first == Set.begin());
+
+ // Erase non-existent element.
+ EXPECT_FALSE(Set.erase(1));
+ EXPECT_EQ(1u, Set.size());
+ EXPECT_EQ(5u, *Set.begin());
+
+ // Erase iterator.
+ USet::iterator I = Set.find(5);
+ EXPECT_TRUE(I == Set.begin());
+ I = Set.erase(I);
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_TRUE(Set.empty());
+}
+
+// Multiple entry set tests.
+TEST(SparseSetTest, MultipleEntrySet) {
+ USet Set;
+ Set.setUniverse(10);
+
+ Set.insert(5);
+ Set.insert(3);
+ Set.insert(2);
+ Set.insert(1);
+ Set.insert(4);
+ EXPECT_EQ(5u, Set.size());
+
+ // Without deletions, iteration order == insertion order.
+ USet::const_iterator I = Set.begin();
+ EXPECT_EQ(5u, *I);
+ ++I;
+ EXPECT_EQ(3u, *I);
+ ++I;
+ EXPECT_EQ(2u, *I);
+ ++I;
+ EXPECT_EQ(1u, *I);
+ ++I;
+ EXPECT_EQ(4u, *I);
+ ++I;
+ EXPECT_TRUE(I == Set.end());
+
+ // Redundant insert.
+ std::pair<USet::iterator, bool> IP = Set.insert(3);
+ EXPECT_FALSE(IP.second);
+ EXPECT_TRUE(IP.first == Set.begin() + 1);
+
+ // Erase last element by key.
+ EXPECT_TRUE(Set.erase(4));
+ EXPECT_EQ(4u, Set.size());
+ EXPECT_FALSE(Set.count(4));
+ EXPECT_FALSE(Set.erase(4));
+ EXPECT_EQ(4u, Set.size());
+ EXPECT_FALSE(Set.count(4));
+
+ // Erase first element by key.
+ EXPECT_TRUE(Set.count(5));
+ EXPECT_TRUE(Set.find(5) == Set.begin());
+ EXPECT_TRUE(Set.erase(5));
+ EXPECT_EQ(3u, Set.size());
+ EXPECT_FALSE(Set.count(5));
+ EXPECT_FALSE(Set.erase(5));
+ EXPECT_EQ(3u, Set.size());
+ EXPECT_FALSE(Set.count(5));
+
+ Set.insert(6);
+ Set.insert(7);
+ EXPECT_EQ(5u, Set.size());
+
+ // Erase last element by iterator.
+ I = Set.erase(Set.end() - 1);
+ EXPECT_TRUE(I == Set.end());
+ EXPECT_EQ(4u, Set.size());
+
+ // Erase second element by iterator.
+ I = Set.erase(Set.begin() + 1);
+ EXPECT_TRUE(I == Set.begin() + 1);
+
+ // Clear and resize the universe.
+ Set.clear();
+ EXPECT_FALSE(Set.count(5));
+ Set.setUniverse(1000);
+
+ // Add more than 256 elements.
+ for (unsigned i = 100; i != 800; ++i)
+ Set.insert(i);
+
+ for (unsigned i = 0; i != 10; ++i)
+ Set.erase(i);
+
+ for (unsigned i = 100; i != 800; ++i)
+ EXPECT_TRUE(Set.count(i));
+
+ EXPECT_FALSE(Set.count(99));
+ EXPECT_FALSE(Set.count(800));
+ EXPECT_EQ(700u, Set.size());
+}
+
+struct Alt {
+ unsigned Value;
+ explicit Alt(unsigned x) : Value(x) {}
+ unsigned getSparseSetIndex() const { return Value - 1000; }
+};
+
+TEST(SparseSetTest, AltStructSet) {
+ typedef SparseSet<Alt> ASet;
+ ASet Set;
+ Set.setUniverse(10);
+ Set.insert(Alt(1005));
+
+ ASet::iterator I = Set.find(5);
+ ASSERT_TRUE(I == Set.begin());
+ EXPECT_EQ(1005u, I->Value);
+
+ Set.insert(Alt(1006));
+ Set.insert(Alt(1006));
+ I = Set.erase(Set.begin());
+ ASSERT_TRUE(I == Set.begin());
+ EXPECT_EQ(1006u, I->Value);
+
+ EXPECT_FALSE(Set.erase(5));
+ EXPECT_TRUE(Set.erase(6));
+}
+
+TEST(SparseSetTest, PopBack) {
+ USet Set;
+ const unsigned UpperBound = 300;
+ Set.setUniverse(UpperBound);
+ for (unsigned i = 0; i < UpperBound; ++i)
+ Set.insert(i);
+
+ // Make sure pop back returns the values in the reverse order we
+ // inserted them.
+ unsigned Expected = UpperBound;
+ while (!Set.empty())
+ ASSERT_TRUE(--Expected == Set.pop_back_val());
+
+ // Insert again the same elements in the sparse set and make sure
+ // each insertion actually inserts the elements. I.e., check
+ // that the underlying data structure are properly cleared.
+ for (unsigned i = 0; i < UpperBound; ++i)
+ ASSERT_TRUE(Set.insert(i).second);
+}
+} // namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/StatisticTest.cpp b/src/llvm-project/llvm/unittests/ADT/StatisticTest.cpp
new file mode 100644
index 0000000..17a5c7f
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/StatisticTest.cpp
@@ -0,0 +1,160 @@
+//===- llvm/unittest/ADT/StatisticTest.cpp - Statistic unit tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+using OptionalStatistic = Optional<std::pair<StringRef, unsigned>>;
+
+namespace {
+#define DEBUG_TYPE "unittest"
+STATISTIC(Counter, "Counts things");
+STATISTIC(Counter2, "Counts other things");
+
+#if LLVM_ENABLE_STATS
+static void
+extractCounters(const std::vector<std::pair<StringRef, unsigned>> &Range,
+ OptionalStatistic &S1, OptionalStatistic &S2) {
+ for (const auto &S : Range) {
+ if (S.first == "Counter")
+ S1 = S;
+ if (S.first == "Counter2")
+ S2 = S;
+ }
+}
+#endif
+
+TEST(StatisticTest, Count) {
+ EnableStatistics();
+
+ Counter = 0;
+ EXPECT_EQ(Counter, 0u);
+ Counter++;
+ Counter++;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+}
+
+TEST(StatisticTest, Assign) {
+ EnableStatistics();
+
+ Counter = 2;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+}
+
+TEST(StatisticTest, API) {
+ EnableStatistics();
+
+ Counter = 0;
+ EXPECT_EQ(Counter, 0u);
+ Counter++;
+ Counter++;
+#if LLVM_ENABLE_STATS
+ EXPECT_EQ(Counter, 2u);
+#else
+ EXPECT_EQ(Counter, 0u);
+#endif
+
+#if LLVM_ENABLE_STATS
+ {
+ const auto Range1 = GetStatistics();
+ EXPECT_NE(Range1.begin(), Range1.end());
+ EXPECT_EQ(Range1.begin() + 1, Range1.end());
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range1, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), false);
+ }
+
+ // Counter2 will be registered when it's first touched.
+ Counter2++;
+
+ {
+ const auto Range = GetStatistics();
+ EXPECT_NE(Range.begin(), Range.end());
+ EXPECT_EQ(Range.begin() + 2, Range.end());
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), true);
+
+ EXPECT_EQ(S1->first, "Counter");
+ EXPECT_EQ(S1->second, 2u);
+
+ EXPECT_EQ(S2->first, "Counter2");
+ EXPECT_EQ(S2->second, 1u);
+ }
+#else
+ Counter2++;
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin(), Range.end());
+#endif
+
+#if LLVM_ENABLE_STATS
+ // Check that resetting the statistics works correctly.
+ // It should empty the list and zero the counters.
+ ResetStatistics();
+ {
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin(), Range.end());
+ EXPECT_EQ(Counter, 0u);
+ EXPECT_EQ(Counter2, 0u);
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+ EXPECT_EQ(S1.hasValue(), false);
+ EXPECT_EQ(S2.hasValue(), false);
+ }
+
+ // Now check that they successfully re-register and count.
+ Counter++;
+ Counter2++;
+
+ {
+ auto &Range = GetStatistics();
+ EXPECT_EQ(Range.begin() + 2, Range.end());
+ EXPECT_EQ(Counter, 1u);
+ EXPECT_EQ(Counter2, 1u);
+
+ OptionalStatistic S1;
+ OptionalStatistic S2;
+ extractCounters(Range, S1, S2);
+
+ EXPECT_EQ(S1.hasValue(), true);
+ EXPECT_EQ(S2.hasValue(), true);
+
+ EXPECT_EQ(S1->first, "Counter");
+ EXPECT_EQ(S1->second, 1u);
+
+ EXPECT_EQ(S2->first, "Counter2");
+ EXPECT_EQ(S2->second, 1u);
+ }
+#else
+ // No need to test the output ResetStatistics(), there's nothing to reset so
+ // we can't tell if it failed anyway.
+ ResetStatistics();
+#endif
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/StringExtrasTest.cpp b/src/llvm-project/llvm/unittests/ADT/StringExtrasTest.cpp
new file mode 100644
index 0000000..02a45c3
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/StringExtrasTest.cpp
@@ -0,0 +1,121 @@
+//===- StringExtrasTest.cpp - Unit tests for String extras ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(StringExtrasTest, isPrint) {
+ EXPECT_FALSE(isPrint('\0'));
+ EXPECT_FALSE(isPrint('\t'));
+ EXPECT_TRUE(isPrint('0'));
+ EXPECT_TRUE(isPrint('a'));
+ EXPECT_TRUE(isPrint('A'));
+ EXPECT_TRUE(isPrint(' '));
+ EXPECT_TRUE(isPrint('~'));
+ EXPECT_TRUE(isPrint('?'));
+}
+
+TEST(StringExtrasTest, Join) {
+ std::vector<std::string> Items;
+ EXPECT_EQ("", join(Items.begin(), Items.end(), " <sep> "));
+
+ Items = {"foo"};
+ EXPECT_EQ("foo", join(Items.begin(), Items.end(), " <sep> "));
+
+ Items = {"foo", "bar"};
+ EXPECT_EQ("foo <sep> bar", join(Items.begin(), Items.end(), " <sep> "));
+
+ Items = {"foo", "bar", "baz"};
+ EXPECT_EQ("foo <sep> bar <sep> baz",
+ join(Items.begin(), Items.end(), " <sep> "));
+}
+
+TEST(StringExtrasTest, JoinItems) {
+ const char *Foo = "foo";
+ std::string Bar = "bar";
+ llvm::StringRef Baz = "baz";
+ char X = 'x';
+
+ EXPECT_EQ("", join_items(" <sep> "));
+ EXPECT_EQ("", join_items('/'));
+
+ EXPECT_EQ("foo", join_items(" <sep> ", Foo));
+ EXPECT_EQ("foo", join_items('/', Foo));
+
+ EXPECT_EQ("foo <sep> bar", join_items(" <sep> ", Foo, Bar));
+ EXPECT_EQ("foo/bar", join_items('/', Foo, Bar));
+
+ EXPECT_EQ("foo <sep> bar <sep> baz", join_items(" <sep> ", Foo, Bar, Baz));
+ EXPECT_EQ("foo/bar/baz", join_items('/', Foo, Bar, Baz));
+
+ EXPECT_EQ("foo <sep> bar <sep> baz <sep> x",
+ join_items(" <sep> ", Foo, Bar, Baz, X));
+
+ EXPECT_EQ("foo/bar/baz/x", join_items('/', Foo, Bar, Baz, X));
+}
+
+TEST(StringExtrasTest, ToAndFromHex) {
+ std::vector<uint8_t> OddBytes = {0x5, 0xBD, 0x0D, 0x3E, 0xCD};
+ std::string OddStr = "05BD0D3ECD";
+ StringRef OddData(reinterpret_cast<const char *>(OddBytes.data()),
+ OddBytes.size());
+ EXPECT_EQ(OddStr, toHex(OddData));
+ EXPECT_EQ(OddData, fromHex(StringRef(OddStr).drop_front()));
+ EXPECT_EQ(StringRef(OddStr).lower(), toHex(OddData, true));
+
+ std::vector<uint8_t> EvenBytes = {0xA5, 0xBD, 0x0D, 0x3E, 0xCD};
+ std::string EvenStr = "A5BD0D3ECD";
+ StringRef EvenData(reinterpret_cast<const char *>(EvenBytes.data()),
+ EvenBytes.size());
+ EXPECT_EQ(EvenStr, toHex(EvenData));
+ EXPECT_EQ(EvenData, fromHex(EvenStr));
+ EXPECT_EQ(StringRef(EvenStr).lower(), toHex(EvenData, true));
+}
+
+TEST(StringExtrasTest, to_float) {
+ float F;
+ EXPECT_TRUE(to_float("4.7", F));
+ EXPECT_FLOAT_EQ(4.7f, F);
+
+ double D;
+ EXPECT_TRUE(to_float("4.7", D));
+ EXPECT_DOUBLE_EQ(4.7, D);
+
+ long double LD;
+ EXPECT_TRUE(to_float("4.7", LD));
+ EXPECT_DOUBLE_EQ(4.7, LD);
+
+ EXPECT_FALSE(to_float("foo", F));
+ EXPECT_FALSE(to_float("7.4 foo", F));
+ EXPECT_FLOAT_EQ(4.7f, F); // F should be unchanged
+}
+
+TEST(StringExtrasTest, printLowerCase) {
+ std::string str;
+ raw_string_ostream OS(str);
+ printLowerCase("ABCdefg01234.,&!~`'}\"", OS);
+ EXPECT_EQ("abcdefg01234.,&!~`'}\"", OS.str());
+}
+
+TEST(StringExtrasTest, printEscapedString) {
+ std::string str;
+ raw_string_ostream OS(str);
+ printEscapedString("ABCdef123&<>\\\"'\t", OS);
+ EXPECT_EQ("ABCdef123&<>\\5C\\22'\\09", OS.str());
+}
+
+TEST(StringExtrasTest, printHTMLEscaped) {
+ std::string str;
+ raw_string_ostream OS(str);
+ printHTMLEscaped("ABCdef123&<>\"'", OS);
+ EXPECT_EQ("ABCdef123&<>"'", OS.str());
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/StringMapTest.cpp b/src/llvm-project/llvm/unittests/ADT/StringMapTest.cpp
new file mode 100644
index 0000000..a44bbbf
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/StringMapTest.cpp
@@ -0,0 +1,535 @@
+//===- llvm/unittest/ADT/StringMapMap.cpp - StringMap unit tests ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+#include <limits>
+#include <tuple>
+using namespace llvm;
+
+namespace {
+
+// Test fixture
+class StringMapTest : public testing::Test {
+protected:
+ StringMap<uint32_t> testMap;
+
+ static const char testKey[];
+ static const uint32_t testValue;
+ static const char* testKeyFirst;
+ static size_t testKeyLength;
+ static const std::string testKeyStr;
+
+ void assertEmptyMap() {
+ // Size tests
+ EXPECT_EQ(0u, testMap.size());
+ EXPECT_TRUE(testMap.empty());
+
+ // Iterator tests
+ EXPECT_TRUE(testMap.begin() == testMap.end());
+
+ // Lookup tests
+ EXPECT_EQ(0u, testMap.count(testKey));
+ EXPECT_EQ(0u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
+ EXPECT_EQ(0u, testMap.count(testKeyStr));
+ EXPECT_TRUE(testMap.find(testKey) == testMap.end());
+ EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
+ testMap.end());
+ EXPECT_TRUE(testMap.find(testKeyStr) == testMap.end());
+ }
+
+ void assertSingleItemMap() {
+ // Size tests
+ EXPECT_EQ(1u, testMap.size());
+ EXPECT_FALSE(testMap.begin() == testMap.end());
+ EXPECT_FALSE(testMap.empty());
+
+ // Iterator tests
+ StringMap<uint32_t>::iterator it = testMap.begin();
+ EXPECT_STREQ(testKey, it->first().data());
+ EXPECT_EQ(testValue, it->second);
+ ++it;
+ EXPECT_TRUE(it == testMap.end());
+
+ // Lookup tests
+ EXPECT_EQ(1u, testMap.count(testKey));
+ EXPECT_EQ(1u, testMap.count(StringRef(testKeyFirst, testKeyLength)));
+ EXPECT_EQ(1u, testMap.count(testKeyStr));
+ EXPECT_TRUE(testMap.find(testKey) == testMap.begin());
+ EXPECT_TRUE(testMap.find(StringRef(testKeyFirst, testKeyLength)) ==
+ testMap.begin());
+ EXPECT_TRUE(testMap.find(testKeyStr) == testMap.begin());
+ }
+};
+
+const char StringMapTest::testKey[] = "key";
+const uint32_t StringMapTest::testValue = 1u;
+const char* StringMapTest::testKeyFirst = testKey;
+size_t StringMapTest::testKeyLength = sizeof(testKey) - 1;
+const std::string StringMapTest::testKeyStr(testKey);
+
+// Empty map tests.
+TEST_F(StringMapTest, EmptyMapTest) {
+ assertEmptyMap();
+}
+
+// Constant map tests.
+TEST_F(StringMapTest, ConstEmptyMapTest) {
+ const StringMap<uint32_t>& constTestMap = testMap;
+
+ // Size tests
+ EXPECT_EQ(0u, constTestMap.size());
+ EXPECT_TRUE(constTestMap.empty());
+
+ // Iterator tests
+ EXPECT_TRUE(constTestMap.begin() == constTestMap.end());
+
+ // Lookup tests
+ EXPECT_EQ(0u, constTestMap.count(testKey));
+ EXPECT_EQ(0u, constTestMap.count(StringRef(testKeyFirst, testKeyLength)));
+ EXPECT_EQ(0u, constTestMap.count(testKeyStr));
+ EXPECT_TRUE(constTestMap.find(testKey) == constTestMap.end());
+ EXPECT_TRUE(constTestMap.find(StringRef(testKeyFirst, testKeyLength)) ==
+ constTestMap.end());
+ EXPECT_TRUE(constTestMap.find(testKeyStr) == constTestMap.end());
+}
+
+// A map with a single entry.
+TEST_F(StringMapTest, SingleEntryMapTest) {
+ testMap[testKey] = testValue;
+ assertSingleItemMap();
+}
+
+// Test clear() method.
+TEST_F(StringMapTest, ClearTest) {
+ testMap[testKey] = testValue;
+ testMap.clear();
+ assertEmptyMap();
+}
+
+// Test erase(iterator) method.
+TEST_F(StringMapTest, EraseIteratorTest) {
+ testMap[testKey] = testValue;
+ testMap.erase(testMap.begin());
+ assertEmptyMap();
+}
+
+// Test erase(value) method.
+TEST_F(StringMapTest, EraseValueTest) {
+ testMap[testKey] = testValue;
+ testMap.erase(testKey);
+ assertEmptyMap();
+}
+
+// Test inserting two values and erasing one.
+TEST_F(StringMapTest, InsertAndEraseTest) {
+ testMap[testKey] = testValue;
+ testMap["otherKey"] = 2;
+ testMap.erase("otherKey");
+ assertSingleItemMap();
+}
+
+TEST_F(StringMapTest, SmallFullMapTest) {
+ // StringMap has a tricky corner case when the map is small (<8 buckets) and
+ // it fills up through a balanced pattern of inserts and erases. This can
+ // lead to inf-loops in some cases (PR13148) so we test it explicitly here.
+ llvm::StringMap<int> Map(2);
+
+ Map["eins"] = 1;
+ Map["zwei"] = 2;
+ Map["drei"] = 3;
+ Map.erase("drei");
+ Map.erase("eins");
+ Map["veir"] = 4;
+ Map["funf"] = 5;
+
+ EXPECT_EQ(3u, Map.size());
+ EXPECT_EQ(0, Map.lookup("eins"));
+ EXPECT_EQ(2, Map.lookup("zwei"));
+ EXPECT_EQ(0, Map.lookup("drei"));
+ EXPECT_EQ(4, Map.lookup("veir"));
+ EXPECT_EQ(5, Map.lookup("funf"));
+}
+
+TEST_F(StringMapTest, CopyCtorTest) {
+ llvm::StringMap<int> Map;
+
+ Map["eins"] = 1;
+ Map["zwei"] = 2;
+ Map["drei"] = 3;
+ Map.erase("drei");
+ Map.erase("eins");
+ Map["veir"] = 4;
+ Map["funf"] = 5;
+
+ EXPECT_EQ(3u, Map.size());
+ EXPECT_EQ(0, Map.lookup("eins"));
+ EXPECT_EQ(2, Map.lookup("zwei"));
+ EXPECT_EQ(0, Map.lookup("drei"));
+ EXPECT_EQ(4, Map.lookup("veir"));
+ EXPECT_EQ(5, Map.lookup("funf"));
+
+ llvm::StringMap<int> Map2(Map);
+ EXPECT_EQ(3u, Map2.size());
+ EXPECT_EQ(0, Map2.lookup("eins"));
+ EXPECT_EQ(2, Map2.lookup("zwei"));
+ EXPECT_EQ(0, Map2.lookup("drei"));
+ EXPECT_EQ(4, Map2.lookup("veir"));
+ EXPECT_EQ(5, Map2.lookup("funf"));
+}
+
+// A more complex iteration test.
+TEST_F(StringMapTest, IterationTest) {
+ bool visited[100];
+
+ // Insert 100 numbers into the map
+ for (int i = 0; i < 100; ++i) {
+ std::stringstream ss;
+ ss << "key_" << i;
+ testMap[ss.str()] = i;
+ visited[i] = false;
+ }
+
+ // Iterate over all numbers and mark each one found.
+ for (StringMap<uint32_t>::iterator it = testMap.begin();
+ it != testMap.end(); ++it) {
+ std::stringstream ss;
+ ss << "key_" << it->second;
+ ASSERT_STREQ(ss.str().c_str(), it->first().data());
+ visited[it->second] = true;
+ }
+
+ // Ensure every number was visited.
+ for (int i = 0; i < 100; ++i) {
+ ASSERT_TRUE(visited[i]) << "Entry #" << i << " was never visited";
+ }
+}
+
+// Test StringMapEntry::Create() method.
+TEST_F(StringMapTest, StringMapEntryTest) {
+ StringMap<uint32_t>::value_type* entry =
+ StringMap<uint32_t>::value_type::Create(
+ StringRef(testKeyFirst, testKeyLength), 1u);
+ EXPECT_STREQ(testKey, entry->first().data());
+ EXPECT_EQ(1u, entry->second);
+ free(entry);
+}
+
+// Test insert() method.
+TEST_F(StringMapTest, InsertTest) {
+ SCOPED_TRACE("InsertTest");
+ testMap.insert(
+ StringMap<uint32_t>::value_type::Create(
+ StringRef(testKeyFirst, testKeyLength),
+ testMap.getAllocator(), 1u));
+ assertSingleItemMap();
+}
+
+// Test insert(pair<K, V>) method
+TEST_F(StringMapTest, InsertPairTest) {
+ bool Inserted;
+ StringMap<uint32_t>::iterator NewIt;
+ std::tie(NewIt, Inserted) =
+ testMap.insert(std::make_pair(testKeyFirst, testValue));
+ EXPECT_EQ(1u, testMap.size());
+ EXPECT_EQ(testValue, testMap[testKeyFirst]);
+ EXPECT_EQ(testKeyFirst, NewIt->first());
+ EXPECT_EQ(testValue, NewIt->second);
+ EXPECT_TRUE(Inserted);
+
+ StringMap<uint32_t>::iterator ExistingIt;
+ std::tie(ExistingIt, Inserted) =
+ testMap.insert(std::make_pair(testKeyFirst, testValue + 1));
+ EXPECT_EQ(1u, testMap.size());
+ EXPECT_EQ(testValue, testMap[testKeyFirst]);
+ EXPECT_FALSE(Inserted);
+ EXPECT_EQ(NewIt, ExistingIt);
+}
+
+// Test insert(pair<K, V>) method when rehashing occurs
+TEST_F(StringMapTest, InsertRehashingPairTest) {
+ // Check that the correct iterator is returned when the inserted element is
+ // moved to a different bucket during internal rehashing. This depends on
+ // the particular key, and the implementation of StringMap and HashString.
+ // Changes to those might result in this test not actually checking that.
+ StringMap<uint32_t> t(0);
+ EXPECT_EQ(0u, t.getNumBuckets());
+
+ StringMap<uint32_t>::iterator It =
+ t.insert(std::make_pair("abcdef", 42)).first;
+ EXPECT_EQ(16u, t.getNumBuckets());
+ EXPECT_EQ("abcdef", It->first());
+ EXPECT_EQ(42u, It->second);
+}
+
+TEST_F(StringMapTest, IterMapKeys) {
+ StringMap<int> Map;
+ Map["A"] = 1;
+ Map["B"] = 2;
+ Map["C"] = 3;
+ Map["D"] = 3;
+
+ auto Keys = to_vector<4>(Map.keys());
+ llvm::sort(Keys);
+
+ SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
+ EXPECT_EQ(Expected, Keys);
+}
+
+TEST_F(StringMapTest, IterSetKeys) {
+ StringSet<> Set;
+ Set.insert("A");
+ Set.insert("B");
+ Set.insert("C");
+ Set.insert("D");
+
+ auto Keys = to_vector<4>(Set.keys());
+ llvm::sort(Keys);
+
+ SmallVector<StringRef, 4> Expected = {"A", "B", "C", "D"};
+ EXPECT_EQ(Expected, Keys);
+}
+
+// Create a non-default constructable value
+struct StringMapTestStruct {
+ StringMapTestStruct(int i) : i(i) {}
+ StringMapTestStruct() = delete;
+ int i;
+};
+
+TEST_F(StringMapTest, NonDefaultConstructable) {
+ StringMap<StringMapTestStruct> t;
+ t.insert(std::make_pair("Test", StringMapTestStruct(123)));
+ StringMap<StringMapTestStruct>::iterator iter = t.find("Test");
+ ASSERT_NE(iter, t.end());
+ ASSERT_EQ(iter->second.i, 123);
+}
+
+struct Immovable {
+ Immovable() {}
+ Immovable(Immovable&&) = delete; // will disable the other special members
+};
+
+struct MoveOnly {
+ int i;
+ MoveOnly(int i) : i(i) {}
+ MoveOnly(const Immovable&) : i(0) {}
+ MoveOnly(MoveOnly &&RHS) : i(RHS.i) {}
+ MoveOnly &operator=(MoveOnly &&RHS) {
+ i = RHS.i;
+ return *this;
+ }
+
+private:
+ MoveOnly(const MoveOnly &) = delete;
+ MoveOnly &operator=(const MoveOnly &) = delete;
+};
+
+TEST_F(StringMapTest, MoveOnly) {
+ StringMap<MoveOnly> t;
+ t.insert(std::make_pair("Test", MoveOnly(42)));
+ StringRef Key = "Test";
+ StringMapEntry<MoveOnly>::Create(Key, MoveOnly(42))
+ ->Destroy();
+}
+
+TEST_F(StringMapTest, CtorArg) {
+ StringRef Key = "Test";
+ StringMapEntry<MoveOnly>::Create(Key, Immovable())
+ ->Destroy();
+}
+
+TEST_F(StringMapTest, MoveConstruct) {
+ StringMap<int> A;
+ A["x"] = 42;
+ StringMap<int> B = std::move(A);
+ ASSERT_EQ(A.size(), 0u);
+ ASSERT_EQ(B.size(), 1u);
+ ASSERT_EQ(B["x"], 42);
+ ASSERT_EQ(B.count("y"), 0u);
+}
+
+TEST_F(StringMapTest, MoveAssignment) {
+ StringMap<int> A;
+ A["x"] = 42;
+ StringMap<int> B;
+ B["y"] = 117;
+ A = std::move(B);
+ ASSERT_EQ(A.size(), 1u);
+ ASSERT_EQ(B.size(), 0u);
+ ASSERT_EQ(A["y"], 117);
+ ASSERT_EQ(B.count("x"), 0u);
+}
+
+struct Countable {
+ int &InstanceCount;
+ int Number;
+ Countable(int Number, int &InstanceCount)
+ : InstanceCount(InstanceCount), Number(Number) {
+ ++InstanceCount;
+ }
+ Countable(Countable &&C) : InstanceCount(C.InstanceCount), Number(C.Number) {
+ ++InstanceCount;
+ C.Number = -1;
+ }
+ Countable(const Countable &C)
+ : InstanceCount(C.InstanceCount), Number(C.Number) {
+ ++InstanceCount;
+ }
+ Countable &operator=(Countable C) {
+ Number = C.Number;
+ return *this;
+ }
+ ~Countable() { --InstanceCount; }
+};
+
+TEST_F(StringMapTest, MoveDtor) {
+ int InstanceCount = 0;
+ StringMap<Countable> A;
+ A.insert(std::make_pair("x", Countable(42, InstanceCount)));
+ ASSERT_EQ(InstanceCount, 1);
+ auto I = A.find("x");
+ ASSERT_NE(I, A.end());
+ ASSERT_EQ(I->second.Number, 42);
+
+ StringMap<Countable> B;
+ B = std::move(A);
+ ASSERT_EQ(InstanceCount, 1);
+ ASSERT_TRUE(A.empty());
+ I = B.find("x");
+ ASSERT_NE(I, B.end());
+ ASSERT_EQ(I->second.Number, 42);
+
+ B = StringMap<Countable>();
+ ASSERT_EQ(InstanceCount, 0);
+ ASSERT_TRUE(B.empty());
+}
+
+namespace {
+// Simple class that counts how many moves and copy happens when growing a map
+struct CountCtorCopyAndMove {
+ static unsigned Ctor;
+ static unsigned Move;
+ static unsigned Copy;
+ int Data = 0;
+ CountCtorCopyAndMove(int Data) : Data(Data) { Ctor++; }
+ CountCtorCopyAndMove() { Ctor++; }
+
+ CountCtorCopyAndMove(const CountCtorCopyAndMove &) { Copy++; }
+ CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &) {
+ Copy++;
+ return *this;
+ }
+ CountCtorCopyAndMove(CountCtorCopyAndMove &&) { Move++; }
+ CountCtorCopyAndMove &operator=(const CountCtorCopyAndMove &&) {
+ Move++;
+ return *this;
+ }
+};
+unsigned CountCtorCopyAndMove::Copy = 0;
+unsigned CountCtorCopyAndMove::Move = 0;
+unsigned CountCtorCopyAndMove::Ctor = 0;
+
+} // anonymous namespace
+
+// Make sure creating the map with an initial size of N actually gives us enough
+// buckets to insert N items without increasing allocation size.
+TEST(StringMapCustomTest, InitialSizeTest) {
+ // 1 is an "edge value", 32 is an arbitrary power of two, and 67 is an
+ // arbitrary prime, picked without any good reason.
+ for (auto Size : {1, 32, 67}) {
+ StringMap<CountCtorCopyAndMove> Map(Size);
+ auto NumBuckets = Map.getNumBuckets();
+ CountCtorCopyAndMove::Move = 0;
+ CountCtorCopyAndMove::Copy = 0;
+ for (int i = 0; i < Size; ++i)
+ Map.insert(std::pair<std::string, CountCtorCopyAndMove>(
+ std::piecewise_construct, std::forward_as_tuple(Twine(i).str()),
+ std::forward_as_tuple(i)));
+ // After the initial move, the map will move the Elts in the Entry.
+ EXPECT_EQ((unsigned)Size * 2, CountCtorCopyAndMove::Move);
+ // We copy once the pair from the Elts vector
+ EXPECT_EQ(0u, CountCtorCopyAndMove::Copy);
+ // Check that the map didn't grow
+ EXPECT_EQ(Map.getNumBuckets(), NumBuckets);
+ }
+}
+
+TEST(StringMapCustomTest, BracketOperatorCtor) {
+ StringMap<CountCtorCopyAndMove> Map;
+ CountCtorCopyAndMove::Ctor = 0;
+ Map["abcd"];
+ EXPECT_EQ(1u, CountCtorCopyAndMove::Ctor);
+ // Test that operator[] does not create a value when it is already in the map
+ CountCtorCopyAndMove::Ctor = 0;
+ Map["abcd"];
+ EXPECT_EQ(0u, CountCtorCopyAndMove::Ctor);
+}
+
+namespace {
+struct NonMoveableNonCopyableType {
+ int Data = 0;
+ NonMoveableNonCopyableType() = default;
+ NonMoveableNonCopyableType(int Data) : Data(Data) {}
+ NonMoveableNonCopyableType(const NonMoveableNonCopyableType &) = delete;
+ NonMoveableNonCopyableType(NonMoveableNonCopyableType &&) = delete;
+};
+}
+
+// Test that we can "emplace" an element in the map without involving map/move
+TEST(StringMapCustomTest, EmplaceTest) {
+ StringMap<NonMoveableNonCopyableType> Map;
+ Map.try_emplace("abcd", 42);
+ EXPECT_EQ(1u, Map.count("abcd"));
+ EXPECT_EQ(42, Map["abcd"].Data);
+}
+
+// Test that StringMapEntryBase can handle size_t wide sizes.
+TEST(StringMapCustomTest, StringMapEntryBaseSize) {
+ size_t LargeValue;
+
+ // Test that the entry can represent max-unsigned.
+ if (sizeof(size_t) <= sizeof(unsigned))
+ LargeValue = std::numeric_limits<unsigned>::max();
+ else
+ LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
+ StringMapEntryBase LargeBase(LargeValue);
+ EXPECT_EQ(LargeValue, LargeBase.getKeyLength());
+
+ // Test that the entry can hold at least max size_t.
+ LargeValue = std::numeric_limits<size_t>::max();
+ StringMapEntryBase LargerBase(LargeValue);
+ LargeValue = std::numeric_limits<size_t>::max();
+ EXPECT_EQ(LargeValue, LargerBase.getKeyLength());
+}
+
+// Test that StringMapEntry can handle size_t wide sizes.
+TEST(StringMapCustomTest, StringMapEntrySize) {
+ size_t LargeValue;
+
+ // Test that the entry can represent max-unsigned.
+ if (sizeof(size_t) <= sizeof(unsigned))
+ LargeValue = std::numeric_limits<unsigned>::max();
+ else
+ LargeValue = std::numeric_limits<unsigned>::max() + 1ULL;
+ StringMapEntry<int> LargeEntry(LargeValue);
+ StringRef Key = LargeEntry.getKey();
+ EXPECT_EQ(LargeValue, Key.size());
+
+ // Test that the entry can hold at least max size_t.
+ LargeValue = std::numeric_limits<size_t>::max();
+ StringMapEntry<int> LargerEntry(LargeValue);
+ Key = LargerEntry.getKey();
+ EXPECT_EQ(LargeValue, Key.size());
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/StringRefTest.cpp b/src/llvm-project/llvm/unittests/ADT/StringRefTest.cpp
new file mode 100644
index 0000000..4087d6c
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/StringRefTest.cpp
@@ -0,0 +1,1065 @@
+//===- llvm/unittest/ADT/StringRefTest.cpp - StringRef unit tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace llvm {
+
+std::ostream &operator<<(std::ostream &OS, const StringRef &S) {
+ OS << S.str();
+ return OS;
+}
+
+std::ostream &operator<<(std::ostream &OS,
+ const std::pair<StringRef, StringRef> &P) {
+ OS << "(" << P.first << ", " << P.second << ")";
+ return OS;
+}
+
+}
+
+// Check that we can't accidentally assign a temporary std::string to a
+// StringRef. (Unfortunately we can't make use of the same thing with
+// constructors.)
+//
+// Disable this check under MSVC; even MSVC 2015 isn't consistent between
+// std::is_assignable and actually writing such an assignment.
+#if !defined(_MSC_VER)
+static_assert(
+ !std::is_assignable<StringRef&, std::string>::value,
+ "Assigning from prvalue std::string");
+static_assert(
+ !std::is_assignable<StringRef&, std::string &&>::value,
+ "Assigning from xvalue std::string");
+static_assert(
+ std::is_assignable<StringRef&, std::string &>::value,
+ "Assigning from lvalue std::string");
+static_assert(
+ std::is_assignable<StringRef&, const char *>::value,
+ "Assigning from prvalue C string");
+static_assert(
+ std::is_assignable<StringRef&, const char * &&>::value,
+ "Assigning from xvalue C string");
+static_assert(
+ std::is_assignable<StringRef&, const char * &>::value,
+ "Assigning from lvalue C string");
+#endif
+
+
+namespace {
+TEST(StringRefTest, Construction) {
+ EXPECT_EQ("", StringRef());
+ EXPECT_EQ("hello", StringRef("hello"));
+ EXPECT_EQ("hello", StringRef("hello world", 5));
+ EXPECT_EQ("hello", StringRef(std::string("hello")));
+}
+
+TEST(StringRefTest, EmptyInitializerList) {
+ StringRef S = {};
+ EXPECT_TRUE(S.empty());
+
+ S = {};
+ EXPECT_TRUE(S.empty());
+}
+
+TEST(StringRefTest, Iteration) {
+ StringRef S("hello");
+ const char *p = "hello";
+ for (const char *it = S.begin(), *ie = S.end(); it != ie; ++it, ++p)
+ EXPECT_EQ(*it, *p);
+}
+
+TEST(StringRefTest, StringOps) {
+ const char *p = "hello";
+ EXPECT_EQ(p, StringRef(p, 0).data());
+ EXPECT_TRUE(StringRef().empty());
+ EXPECT_EQ((size_t) 5, StringRef("hello").size());
+ EXPECT_EQ(-1, StringRef("aab").compare("aad"));
+ EXPECT_EQ( 0, StringRef("aab").compare("aab"));
+ EXPECT_EQ( 1, StringRef("aab").compare("aaa"));
+ EXPECT_EQ(-1, StringRef("aab").compare("aabb"));
+ EXPECT_EQ( 1, StringRef("aab").compare("aa"));
+ EXPECT_EQ( 1, StringRef("\xFF").compare("\1"));
+
+ EXPECT_EQ(-1, StringRef("AaB").compare_lower("aAd"));
+ EXPECT_EQ( 0, StringRef("AaB").compare_lower("aab"));
+ EXPECT_EQ( 1, StringRef("AaB").compare_lower("AAA"));
+ EXPECT_EQ(-1, StringRef("AaB").compare_lower("aaBb"));
+ EXPECT_EQ(-1, StringRef("AaB").compare_lower("bb"));
+ EXPECT_EQ( 1, StringRef("aaBb").compare_lower("AaB"));
+ EXPECT_EQ( 1, StringRef("bb").compare_lower("AaB"));
+ EXPECT_EQ( 1, StringRef("AaB").compare_lower("aA"));
+ EXPECT_EQ( 1, StringRef("\xFF").compare_lower("\1"));
+
+ EXPECT_EQ(-1, StringRef("aab").compare_numeric("aad"));
+ EXPECT_EQ( 0, StringRef("aab").compare_numeric("aab"));
+ EXPECT_EQ( 1, StringRef("aab").compare_numeric("aaa"));
+ EXPECT_EQ(-1, StringRef("aab").compare_numeric("aabb"));
+ EXPECT_EQ( 1, StringRef("aab").compare_numeric("aa"));
+ EXPECT_EQ(-1, StringRef("1").compare_numeric("10"));
+ EXPECT_EQ( 0, StringRef("10").compare_numeric("10"));
+ EXPECT_EQ( 0, StringRef("10a").compare_numeric("10a"));
+ EXPECT_EQ( 1, StringRef("2").compare_numeric("1"));
+ EXPECT_EQ( 0, StringRef("llvm_v1i64_ty").compare_numeric("llvm_v1i64_ty"));
+ EXPECT_EQ( 1, StringRef("\xFF").compare_numeric("\1"));
+ EXPECT_EQ( 1, StringRef("V16").compare_numeric("V1_q0"));
+ EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V16"));
+ EXPECT_EQ(-1, StringRef("V8_q0").compare_numeric("V16"));
+ EXPECT_EQ( 1, StringRef("V16").compare_numeric("V8_q0"));
+ EXPECT_EQ(-1, StringRef("V1_q0").compare_numeric("V8_q0"));
+ EXPECT_EQ( 1, StringRef("V8_q0").compare_numeric("V1_q0"));
+}
+
+TEST(StringRefTest, Operators) {
+ EXPECT_EQ("", StringRef());
+ EXPECT_TRUE(StringRef("aab") < StringRef("aad"));
+ EXPECT_FALSE(StringRef("aab") < StringRef("aab"));
+ EXPECT_TRUE(StringRef("aab") <= StringRef("aab"));
+ EXPECT_FALSE(StringRef("aab") <= StringRef("aaa"));
+ EXPECT_TRUE(StringRef("aad") > StringRef("aab"));
+ EXPECT_FALSE(StringRef("aab") > StringRef("aab"));
+ EXPECT_TRUE(StringRef("aab") >= StringRef("aab"));
+ EXPECT_FALSE(StringRef("aaa") >= StringRef("aab"));
+ EXPECT_EQ(StringRef("aab"), StringRef("aab"));
+ EXPECT_FALSE(StringRef("aab") == StringRef("aac"));
+ EXPECT_FALSE(StringRef("aab") != StringRef("aab"));
+ EXPECT_TRUE(StringRef("aab") != StringRef("aac"));
+ EXPECT_EQ('a', StringRef("aab")[1]);
+}
+
+TEST(StringRefTest, Substr) {
+ StringRef Str("hello");
+ EXPECT_EQ("lo", Str.substr(3));
+ EXPECT_EQ("", Str.substr(100));
+ EXPECT_EQ("hello", Str.substr(0, 100));
+ EXPECT_EQ("o", Str.substr(4, 10));
+}
+
+TEST(StringRefTest, Slice) {
+ StringRef Str("hello");
+ EXPECT_EQ("l", Str.slice(2, 3));
+ EXPECT_EQ("ell", Str.slice(1, 4));
+ EXPECT_EQ("llo", Str.slice(2, 100));
+ EXPECT_EQ("", Str.slice(2, 1));
+ EXPECT_EQ("", Str.slice(10, 20));
+}
+
+TEST(StringRefTest, Split) {
+ StringRef Str("hello");
+ EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
+ Str.split('X'));
+ EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
+ Str.split('e'));
+ EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
+ Str.split('h'));
+ EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("lo")),
+ Str.split('l'));
+ EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
+ Str.split('o'));
+
+ EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
+ Str.rsplit('X'));
+ EXPECT_EQ(std::make_pair(StringRef("h"), StringRef("llo")),
+ Str.rsplit('e'));
+ EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
+ Str.rsplit('h'));
+ EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")),
+ Str.rsplit('l'));
+ EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
+ Str.rsplit('o'));
+
+ EXPECT_EQ(std::make_pair(StringRef("he"), StringRef("o")),
+ Str.rsplit("ll"));
+ EXPECT_EQ(std::make_pair(StringRef(""), StringRef("ello")),
+ Str.rsplit("h"));
+ EXPECT_EQ(std::make_pair(StringRef("hell"), StringRef("")),
+ Str.rsplit("o"));
+ EXPECT_EQ(std::make_pair(StringRef("hello"), StringRef("")),
+ Str.rsplit("::"));
+ EXPECT_EQ(std::make_pair(StringRef("hel"), StringRef("o")),
+ Str.rsplit("l"));
+}
+
+TEST(StringRefTest, Split2) {
+ SmallVector<StringRef, 5> parts;
+ SmallVector<StringRef, 5> expected;
+
+ expected.push_back("ab"); expected.push_back("c");
+ StringRef(",ab,,c,").split(parts, ",", -1, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back(""); expected.push_back("ab"); expected.push_back("");
+ expected.push_back("c"); expected.push_back("");
+ StringRef(",ab,,c,").split(parts, ",", -1, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("");
+ StringRef("").split(parts, ",", -1, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ StringRef("").split(parts, ",", -1, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ StringRef(",").split(parts, ",", -1, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back(""); expected.push_back("");
+ StringRef(",").split(parts, ",", -1, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back("b");
+ StringRef("a,b").split(parts, ",", -1, true);
+ EXPECT_TRUE(parts == expected);
+
+ // Test MaxSplit
+ expected.clear(); parts.clear();
+ expected.push_back("a,,b,c");
+ StringRef("a,,b,c").split(parts, ",", 0, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a,,b,c");
+ StringRef("a,,b,c").split(parts, ",", 0, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back(",b,c");
+ StringRef("a,,b,c").split(parts, ",", 1, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back(",b,c");
+ StringRef("a,,b,c").split(parts, ",", 1, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back(""); expected.push_back("b,c");
+ StringRef("a,,b,c").split(parts, ",", 2, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back("b,c");
+ StringRef("a,,b,c").split(parts, ",", 2, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back(""); expected.push_back("b");
+ expected.push_back("c");
+ StringRef("a,,b,c").split(parts, ",", 3, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back("b"); expected.push_back("c");
+ StringRef("a,,b,c").split(parts, ",", 3, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a"); expected.push_back("b"); expected.push_back("c");
+ StringRef("a,,b,c").split(parts, ',', 3, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("");
+ StringRef().split(parts, ",", 0, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back(StringRef());
+ StringRef("").split(parts, ",", 0, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ StringRef("").split(parts, ",", 0, false);
+ EXPECT_TRUE(parts == expected);
+ StringRef().split(parts, ",", 0, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a");
+ expected.push_back("");
+ expected.push_back("b");
+ expected.push_back("c,d");
+ StringRef("a,,b,c,d").split(parts, ",", 3, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("");
+ StringRef().split(parts, ',', 0, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back(StringRef());
+ StringRef("").split(parts, ',', 0, true);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ StringRef("").split(parts, ',', 0, false);
+ EXPECT_TRUE(parts == expected);
+ StringRef().split(parts, ',', 0, false);
+ EXPECT_TRUE(parts == expected);
+
+ expected.clear(); parts.clear();
+ expected.push_back("a");
+ expected.push_back("");
+ expected.push_back("b");
+ expected.push_back("c,d");
+ StringRef("a,,b,c,d").split(parts, ',', 3, true);
+ EXPECT_TRUE(parts == expected);
+}
+
+TEST(StringRefTest, Trim) {
+ StringRef Str0("hello");
+ StringRef Str1(" hello ");
+ StringRef Str2(" hello ");
+
+ EXPECT_EQ(StringRef("hello"), Str0.rtrim());
+ EXPECT_EQ(StringRef(" hello"), Str1.rtrim());
+ EXPECT_EQ(StringRef(" hello"), Str2.rtrim());
+ EXPECT_EQ(StringRef("hello"), Str0.ltrim());
+ EXPECT_EQ(StringRef("hello "), Str1.ltrim());
+ EXPECT_EQ(StringRef("hello "), Str2.ltrim());
+ EXPECT_EQ(StringRef("hello"), Str0.trim());
+ EXPECT_EQ(StringRef("hello"), Str1.trim());
+ EXPECT_EQ(StringRef("hello"), Str2.trim());
+
+ EXPECT_EQ(StringRef("ello"), Str0.trim("hhhhhhhhhhh"));
+
+ EXPECT_EQ(StringRef(""), StringRef("").trim());
+ EXPECT_EQ(StringRef(""), StringRef(" ").trim());
+ EXPECT_EQ(StringRef("\0", 1), StringRef(" \0 ", 3).trim());
+ EXPECT_EQ(StringRef("\0\0", 2), StringRef("\0\0", 2).trim());
+ EXPECT_EQ(StringRef("x"), StringRef("\0\0x\0\0", 5).trim('\0'));
+}
+
+TEST(StringRefTest, StartsWith) {
+ StringRef Str("hello");
+ EXPECT_TRUE(Str.startswith(""));
+ EXPECT_TRUE(Str.startswith("he"));
+ EXPECT_FALSE(Str.startswith("helloworld"));
+ EXPECT_FALSE(Str.startswith("hi"));
+}
+
+TEST(StringRefTest, StartsWithLower) {
+ StringRef Str("heLLo");
+ EXPECT_TRUE(Str.startswith_lower(""));
+ EXPECT_TRUE(Str.startswith_lower("he"));
+ EXPECT_TRUE(Str.startswith_lower("hell"));
+ EXPECT_TRUE(Str.startswith_lower("HELlo"));
+ EXPECT_FALSE(Str.startswith_lower("helloworld"));
+ EXPECT_FALSE(Str.startswith_lower("hi"));
+}
+
+TEST(StringRefTest, ConsumeFront) {
+ StringRef Str("hello");
+ EXPECT_TRUE(Str.consume_front(""));
+ EXPECT_EQ("hello", Str);
+ EXPECT_TRUE(Str.consume_front("he"));
+ EXPECT_EQ("llo", Str);
+ EXPECT_FALSE(Str.consume_front("lloworld"));
+ EXPECT_EQ("llo", Str);
+ EXPECT_FALSE(Str.consume_front("lol"));
+ EXPECT_EQ("llo", Str);
+ EXPECT_TRUE(Str.consume_front("llo"));
+ EXPECT_EQ("", Str);
+ EXPECT_FALSE(Str.consume_front("o"));
+ EXPECT_TRUE(Str.consume_front(""));
+}
+
+TEST(StringRefTest, EndsWith) {
+ StringRef Str("hello");
+ EXPECT_TRUE(Str.endswith(""));
+ EXPECT_TRUE(Str.endswith("lo"));
+ EXPECT_FALSE(Str.endswith("helloworld"));
+ EXPECT_FALSE(Str.endswith("worldhello"));
+ EXPECT_FALSE(Str.endswith("so"));
+}
+
+TEST(StringRefTest, EndsWithLower) {
+ StringRef Str("heLLo");
+ EXPECT_TRUE(Str.endswith_lower(""));
+ EXPECT_TRUE(Str.endswith_lower("lo"));
+ EXPECT_TRUE(Str.endswith_lower("LO"));
+ EXPECT_TRUE(Str.endswith_lower("ELlo"));
+ EXPECT_FALSE(Str.endswith_lower("helloworld"));
+ EXPECT_FALSE(Str.endswith_lower("hi"));
+}
+
+TEST(StringRefTest, ConsumeBack) {
+ StringRef Str("hello");
+ EXPECT_TRUE(Str.consume_back(""));
+ EXPECT_EQ("hello", Str);
+ EXPECT_TRUE(Str.consume_back("lo"));
+ EXPECT_EQ("hel", Str);
+ EXPECT_FALSE(Str.consume_back("helhel"));
+ EXPECT_EQ("hel", Str);
+ EXPECT_FALSE(Str.consume_back("hle"));
+ EXPECT_EQ("hel", Str);
+ EXPECT_TRUE(Str.consume_back("hel"));
+ EXPECT_EQ("", Str);
+ EXPECT_FALSE(Str.consume_back("h"));
+ EXPECT_TRUE(Str.consume_back(""));
+}
+
+TEST(StringRefTest, Find) {
+ StringRef Str("helloHELLO");
+ StringRef LongStr("hellx xello hell ello world foo bar hello HELLO");
+
+ struct {
+ StringRef Str;
+ char C;
+ std::size_t From;
+ std::size_t Pos;
+ std::size_t LowerPos;
+ } CharExpectations[] = {
+ {Str, 'h', 0U, 0U, 0U},
+ {Str, 'e', 0U, 1U, 1U},
+ {Str, 'l', 0U, 2U, 2U},
+ {Str, 'l', 3U, 3U, 3U},
+ {Str, 'o', 0U, 4U, 4U},
+ {Str, 'L', 0U, 7U, 2U},
+ {Str, 'z', 0U, StringRef::npos, StringRef::npos},
+ };
+
+ struct {
+ StringRef Str;
+ llvm::StringRef S;
+ std::size_t From;
+ std::size_t Pos;
+ std::size_t LowerPos;
+ } StrExpectations[] = {
+ {Str, "helloword", 0, StringRef::npos, StringRef::npos},
+ {Str, "hello", 0, 0U, 0U},
+ {Str, "ello", 0, 1U, 1U},
+ {Str, "zz", 0, StringRef::npos, StringRef::npos},
+ {Str, "ll", 2U, 2U, 2U},
+ {Str, "ll", 3U, StringRef::npos, 7U},
+ {Str, "LL", 2U, 7U, 2U},
+ {Str, "LL", 3U, 7U, 7U},
+ {Str, "", 0U, 0U, 0U},
+ {LongStr, "hello", 0U, 36U, 36U},
+ {LongStr, "foo", 0U, 28U, 28U},
+ {LongStr, "hell", 2U, 12U, 12U},
+ {LongStr, "HELL", 2U, 42U, 12U},
+ {LongStr, "", 0U, 0U, 0U}};
+
+ for (auto &E : CharExpectations) {
+ EXPECT_EQ(E.Pos, E.Str.find(E.C, E.From));
+ EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.C, E.From));
+ EXPECT_EQ(E.LowerPos, E.Str.find_lower(toupper(E.C), E.From));
+ }
+
+ for (auto &E : StrExpectations) {
+ EXPECT_EQ(E.Pos, E.Str.find(E.S, E.From));
+ EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.S, E.From));
+ EXPECT_EQ(E.LowerPos, E.Str.find_lower(E.S.upper(), E.From));
+ }
+
+ EXPECT_EQ(3U, Str.rfind('l'));
+ EXPECT_EQ(StringRef::npos, Str.rfind('z'));
+ EXPECT_EQ(StringRef::npos, Str.rfind("helloworld"));
+ EXPECT_EQ(0U, Str.rfind("hello"));
+ EXPECT_EQ(1U, Str.rfind("ello"));
+ EXPECT_EQ(StringRef::npos, Str.rfind("zz"));
+
+ EXPECT_EQ(8U, Str.rfind_lower('l'));
+ EXPECT_EQ(8U, Str.rfind_lower('L'));
+ EXPECT_EQ(StringRef::npos, Str.rfind_lower('z'));
+ EXPECT_EQ(StringRef::npos, Str.rfind_lower("HELLOWORLD"));
+ EXPECT_EQ(5U, Str.rfind("HELLO"));
+ EXPECT_EQ(6U, Str.rfind("ELLO"));
+ EXPECT_EQ(StringRef::npos, Str.rfind("ZZ"));
+
+ EXPECT_EQ(2U, Str.find_first_of('l'));
+ EXPECT_EQ(1U, Str.find_first_of("el"));
+ EXPECT_EQ(StringRef::npos, Str.find_first_of("xyz"));
+
+ Str = "hello";
+ EXPECT_EQ(1U, Str.find_first_not_of('h'));
+ EXPECT_EQ(4U, Str.find_first_not_of("hel"));
+ EXPECT_EQ(StringRef::npos, Str.find_first_not_of("hello"));
+
+ EXPECT_EQ(3U, Str.find_last_not_of('o'));
+ EXPECT_EQ(1U, Str.find_last_not_of("lo"));
+ EXPECT_EQ(StringRef::npos, Str.find_last_not_of("helo"));
+}
+
+TEST(StringRefTest, Count) {
+ StringRef Str("hello");
+ EXPECT_EQ(2U, Str.count('l'));
+ EXPECT_EQ(1U, Str.count('o'));
+ EXPECT_EQ(0U, Str.count('z'));
+ EXPECT_EQ(0U, Str.count("helloworld"));
+ EXPECT_EQ(1U, Str.count("hello"));
+ EXPECT_EQ(1U, Str.count("ello"));
+ EXPECT_EQ(0U, Str.count("zz"));
+}
+
+TEST(StringRefTest, EditDistance) {
+ StringRef Hello("hello");
+ EXPECT_EQ(2U, Hello.edit_distance("hill"));
+
+ StringRef Industry("industry");
+ EXPECT_EQ(6U, Industry.edit_distance("interest"));
+
+ StringRef Soylent("soylent green is people");
+ EXPECT_EQ(19U, Soylent.edit_distance("people soiled our green"));
+ EXPECT_EQ(26U, Soylent.edit_distance("people soiled our green",
+ /* allow replacements = */ false));
+ EXPECT_EQ(9U, Soylent.edit_distance("people soiled our green",
+ /* allow replacements = */ true,
+ /* max edit distance = */ 8));
+ EXPECT_EQ(53U, Soylent.edit_distance("people soiled our green "
+ "people soiled our green "
+ "people soiled our green "));
+}
+
+TEST(StringRefTest, Misc) {
+ std::string Storage;
+ raw_string_ostream OS(Storage);
+ OS << StringRef("hello");
+ EXPECT_EQ("hello", OS.str());
+}
+
+TEST(StringRefTest, Hashing) {
+ EXPECT_EQ(hash_value(std::string()), hash_value(StringRef()));
+ EXPECT_EQ(hash_value(std::string()), hash_value(StringRef("")));
+ std::string S = "hello world";
+ hash_code H = hash_value(S);
+ EXPECT_EQ(H, hash_value(StringRef("hello world")));
+ EXPECT_EQ(H, hash_value(StringRef(S)));
+ EXPECT_NE(H, hash_value(StringRef("hello worl")));
+ EXPECT_EQ(hash_value(std::string("hello worl")),
+ hash_value(StringRef("hello worl")));
+ EXPECT_NE(H, hash_value(StringRef("hello world ")));
+ EXPECT_EQ(hash_value(std::string("hello world ")),
+ hash_value(StringRef("hello world ")));
+ EXPECT_EQ(H, hash_value(StringRef("hello world\0")));
+ EXPECT_NE(hash_value(std::string("ello worl")),
+ hash_value(StringRef("hello world").slice(1, -1)));
+}
+
+struct UnsignedPair {
+ const char *Str;
+ uint64_t Expected;
+} Unsigned[] =
+ { {"0", 0}
+ , {"255", 255}
+ , {"256", 256}
+ , {"65535", 65535}
+ , {"65536", 65536}
+ , {"4294967295", 4294967295ULL}
+ , {"4294967296", 4294967296ULL}
+ , {"18446744073709551615", 18446744073709551615ULL}
+ , {"042", 34}
+ , {"0x42", 66}
+ , {"0b101010", 42}
+ };
+
+struct SignedPair {
+ const char *Str;
+ int64_t Expected;
+} Signed[] =
+ { {"0", 0}
+ , {"-0", 0}
+ , {"127", 127}
+ , {"128", 128}
+ , {"-128", -128}
+ , {"-129", -129}
+ , {"32767", 32767}
+ , {"32768", 32768}
+ , {"-32768", -32768}
+ , {"-32769", -32769}
+ , {"2147483647", 2147483647LL}
+ , {"2147483648", 2147483648LL}
+ , {"-2147483648", -2147483648LL}
+ , {"-2147483649", -2147483649LL}
+ , {"-9223372036854775808", -(9223372036854775807LL) - 1}
+ , {"042", 34}
+ , {"0x42", 66}
+ , {"0b101010", 42}
+ , {"-042", -34}
+ , {"-0x42", -66}
+ , {"-0b101010", -42}
+ };
+
+TEST(StringRefTest, getAsInteger) {
+ uint8_t U8;
+ uint16_t U16;
+ uint32_t U32;
+ uint64_t U64;
+
+ for (size_t i = 0; i < array_lengthof(Unsigned); ++i) {
+ bool U8Success = StringRef(Unsigned[i].Str).getAsInteger(0, U8);
+ if (static_cast<uint8_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
+ ASSERT_FALSE(U8Success);
+ EXPECT_EQ(U8, Unsigned[i].Expected);
+ } else {
+ ASSERT_TRUE(U8Success);
+ }
+ bool U16Success = StringRef(Unsigned[i].Str).getAsInteger(0, U16);
+ if (static_cast<uint16_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
+ ASSERT_FALSE(U16Success);
+ EXPECT_EQ(U16, Unsigned[i].Expected);
+ } else {
+ ASSERT_TRUE(U16Success);
+ }
+ bool U32Success = StringRef(Unsigned[i].Str).getAsInteger(0, U32);
+ if (static_cast<uint32_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
+ ASSERT_FALSE(U32Success);
+ EXPECT_EQ(U32, Unsigned[i].Expected);
+ } else {
+ ASSERT_TRUE(U32Success);
+ }
+ bool U64Success = StringRef(Unsigned[i].Str).getAsInteger(0, U64);
+ if (static_cast<uint64_t>(Unsigned[i].Expected) == Unsigned[i].Expected) {
+ ASSERT_FALSE(U64Success);
+ EXPECT_EQ(U64, Unsigned[i].Expected);
+ } else {
+ ASSERT_TRUE(U64Success);
+ }
+ }
+
+ int8_t S8;
+ int16_t S16;
+ int32_t S32;
+ int64_t S64;
+
+ for (size_t i = 0; i < array_lengthof(Signed); ++i) {
+ bool S8Success = StringRef(Signed[i].Str).getAsInteger(0, S8);
+ if (static_cast<int8_t>(Signed[i].Expected) == Signed[i].Expected) {
+ ASSERT_FALSE(S8Success);
+ EXPECT_EQ(S8, Signed[i].Expected);
+ } else {
+ ASSERT_TRUE(S8Success);
+ }
+ bool S16Success = StringRef(Signed[i].Str).getAsInteger(0, S16);
+ if (static_cast<int16_t>(Signed[i].Expected) == Signed[i].Expected) {
+ ASSERT_FALSE(S16Success);
+ EXPECT_EQ(S16, Signed[i].Expected);
+ } else {
+ ASSERT_TRUE(S16Success);
+ }
+ bool S32Success = StringRef(Signed[i].Str).getAsInteger(0, S32);
+ if (static_cast<int32_t>(Signed[i].Expected) == Signed[i].Expected) {
+ ASSERT_FALSE(S32Success);
+ EXPECT_EQ(S32, Signed[i].Expected);
+ } else {
+ ASSERT_TRUE(S32Success);
+ }
+ bool S64Success = StringRef(Signed[i].Str).getAsInteger(0, S64);
+ if (static_cast<int64_t>(Signed[i].Expected) == Signed[i].Expected) {
+ ASSERT_FALSE(S64Success);
+ EXPECT_EQ(S64, Signed[i].Expected);
+ } else {
+ ASSERT_TRUE(S64Success);
+ }
+ }
+}
+
+
+static const char* BadStrings[] = {
+ "" // empty string
+ , "18446744073709551617" // value just over max
+ , "123456789012345678901" // value way too large
+ , "4t23v" // illegal decimal characters
+ , "0x123W56" // illegal hex characters
+ , "0b2" // illegal bin characters
+ , "08" // illegal oct characters
+ , "0o8" // illegal oct characters
+ , "-123" // negative unsigned value
+ , "0x"
+ , "0b"
+};
+
+
+TEST(StringRefTest, getAsUnsignedIntegerBadStrings) {
+ unsigned long long U64;
+ for (size_t i = 0; i < array_lengthof(BadStrings); ++i) {
+ bool IsBadNumber = StringRef(BadStrings[i]).getAsInteger(0, U64);
+ ASSERT_TRUE(IsBadNumber);
+ }
+}
+
+struct ConsumeUnsignedPair {
+ const char *Str;
+ uint64_t Expected;
+ const char *Leftover;
+} ConsumeUnsigned[] = {
+ {"0", 0, ""},
+ {"255", 255, ""},
+ {"256", 256, ""},
+ {"65535", 65535, ""},
+ {"65536", 65536, ""},
+ {"4294967295", 4294967295ULL, ""},
+ {"4294967296", 4294967296ULL, ""},
+ {"255A376", 255, "A376"},
+ {"18446744073709551615", 18446744073709551615ULL, ""},
+ {"18446744073709551615ABC", 18446744073709551615ULL, "ABC"},
+ {"042", 34, ""},
+ {"0x42", 66, ""},
+ {"0x42-0x34", 66, "-0x34"},
+ {"0b101010", 42, ""},
+ {"0429F", 042, "9F"}, // Auto-sensed octal radix, invalid digit
+ {"0x42G12", 0x42, "G12"}, // Auto-sensed hex radix, invalid digit
+ {"0b10101020101", 42, "20101"}}; // Auto-sensed binary radix, invalid digit.
+
+struct ConsumeSignedPair {
+ const char *Str;
+ int64_t Expected;
+ const char *Leftover;
+} ConsumeSigned[] = {
+ {"0", 0, ""},
+ {"-0", 0, ""},
+ {"0-1", 0, "-1"},
+ {"-0-1", 0, "-1"},
+ {"127", 127, ""},
+ {"128", 128, ""},
+ {"127-1", 127, "-1"},
+ {"128-1", 128, "-1"},
+ {"-128", -128, ""},
+ {"-129", -129, ""},
+ {"-128-1", -128, "-1"},
+ {"-129-1", -129, "-1"},
+ {"32767", 32767, ""},
+ {"32768", 32768, ""},
+ {"32767-1", 32767, "-1"},
+ {"32768-1", 32768, "-1"},
+ {"-32768", -32768, ""},
+ {"-32769", -32769, ""},
+ {"-32768-1", -32768, "-1"},
+ {"-32769-1", -32769, "-1"},
+ {"2147483647", 2147483647LL, ""},
+ {"2147483648", 2147483648LL, ""},
+ {"2147483647-1", 2147483647LL, "-1"},
+ {"2147483648-1", 2147483648LL, "-1"},
+ {"-2147483648", -2147483648LL, ""},
+ {"-2147483649", -2147483649LL, ""},
+ {"-2147483648-1", -2147483648LL, "-1"},
+ {"-2147483649-1", -2147483649LL, "-1"},
+ {"-9223372036854775808", -(9223372036854775807LL) - 1, ""},
+ {"-9223372036854775808-1", -(9223372036854775807LL) - 1, "-1"},
+ {"042", 34, ""},
+ {"042-1", 34, "-1"},
+ {"0x42", 66, ""},
+ {"0x42-1", 66, "-1"},
+ {"0b101010", 42, ""},
+ {"0b101010-1", 42, "-1"},
+ {"-042", -34, ""},
+ {"-042-1", -34, "-1"},
+ {"-0x42", -66, ""},
+ {"-0x42-1", -66, "-1"},
+ {"-0b101010", -42, ""},
+ {"-0b101010-1", -42, "-1"}};
+
+TEST(StringRefTest, consumeIntegerUnsigned) {
+ uint8_t U8;
+ uint16_t U16;
+ uint32_t U32;
+ uint64_t U64;
+
+ for (size_t i = 0; i < array_lengthof(ConsumeUnsigned); ++i) {
+ StringRef Str = ConsumeUnsigned[i].Str;
+ bool U8Success = Str.consumeInteger(0, U8);
+ if (static_cast<uint8_t>(ConsumeUnsigned[i].Expected) ==
+ ConsumeUnsigned[i].Expected) {
+ ASSERT_FALSE(U8Success);
+ EXPECT_EQ(U8, ConsumeUnsigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(U8Success);
+ }
+
+ Str = ConsumeUnsigned[i].Str;
+ bool U16Success = Str.consumeInteger(0, U16);
+ if (static_cast<uint16_t>(ConsumeUnsigned[i].Expected) ==
+ ConsumeUnsigned[i].Expected) {
+ ASSERT_FALSE(U16Success);
+ EXPECT_EQ(U16, ConsumeUnsigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(U16Success);
+ }
+
+ Str = ConsumeUnsigned[i].Str;
+ bool U32Success = Str.consumeInteger(0, U32);
+ if (static_cast<uint32_t>(ConsumeUnsigned[i].Expected) ==
+ ConsumeUnsigned[i].Expected) {
+ ASSERT_FALSE(U32Success);
+ EXPECT_EQ(U32, ConsumeUnsigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(U32Success);
+ }
+
+ Str = ConsumeUnsigned[i].Str;
+ bool U64Success = Str.consumeInteger(0, U64);
+ if (static_cast<uint64_t>(ConsumeUnsigned[i].Expected) ==
+ ConsumeUnsigned[i].Expected) {
+ ASSERT_FALSE(U64Success);
+ EXPECT_EQ(U64, ConsumeUnsigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeUnsigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(U64Success);
+ }
+ }
+}
+
+TEST(StringRefTest, consumeIntegerSigned) {
+ int8_t S8;
+ int16_t S16;
+ int32_t S32;
+ int64_t S64;
+
+ for (size_t i = 0; i < array_lengthof(ConsumeSigned); ++i) {
+ StringRef Str = ConsumeSigned[i].Str;
+ bool S8Success = Str.consumeInteger(0, S8);
+ if (static_cast<int8_t>(ConsumeSigned[i].Expected) ==
+ ConsumeSigned[i].Expected) {
+ ASSERT_FALSE(S8Success);
+ EXPECT_EQ(S8, ConsumeSigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(S8Success);
+ }
+
+ Str = ConsumeSigned[i].Str;
+ bool S16Success = Str.consumeInteger(0, S16);
+ if (static_cast<int16_t>(ConsumeSigned[i].Expected) ==
+ ConsumeSigned[i].Expected) {
+ ASSERT_FALSE(S16Success);
+ EXPECT_EQ(S16, ConsumeSigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(S16Success);
+ }
+
+ Str = ConsumeSigned[i].Str;
+ bool S32Success = Str.consumeInteger(0, S32);
+ if (static_cast<int32_t>(ConsumeSigned[i].Expected) ==
+ ConsumeSigned[i].Expected) {
+ ASSERT_FALSE(S32Success);
+ EXPECT_EQ(S32, ConsumeSigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(S32Success);
+ }
+
+ Str = ConsumeSigned[i].Str;
+ bool S64Success = Str.consumeInteger(0, S64);
+ if (static_cast<int64_t>(ConsumeSigned[i].Expected) ==
+ ConsumeSigned[i].Expected) {
+ ASSERT_FALSE(S64Success);
+ EXPECT_EQ(S64, ConsumeSigned[i].Expected);
+ EXPECT_EQ(Str, ConsumeSigned[i].Leftover);
+ } else {
+ ASSERT_TRUE(S64Success);
+ }
+ }
+}
+
+struct GetDoubleStrings {
+ const char *Str;
+ bool AllowInexact;
+ bool ShouldFail;
+ double D;
+} DoubleStrings[] = {{"0", false, false, 0.0},
+ {"0.0", false, false, 0.0},
+ {"-0.0", false, false, -0.0},
+ {"123.45", false, true, 123.45},
+ {"123.45", true, false, 123.45},
+ {"1.8e308", true, false, std::numeric_limits<double>::infinity()},
+ {"1.8e308", false, true, std::numeric_limits<double>::infinity()},
+ {"0x0.0000000000001P-1023", false, true, 0.0},
+ {"0x0.0000000000001P-1023", true, false, 0.0},
+ };
+
+TEST(StringRefTest, getAsDouble) {
+ for (const auto &Entry : DoubleStrings) {
+ double Result;
+ StringRef S(Entry.Str);
+ EXPECT_EQ(Entry.ShouldFail, S.getAsDouble(Result, Entry.AllowInexact));
+ if (!Entry.ShouldFail) {
+ EXPECT_EQ(Result, Entry.D);
+ }
+ }
+}
+
+static const char *join_input[] = { "a", "b", "c" };
+static const char join_result1[] = "a";
+static const char join_result2[] = "a:b:c";
+static const char join_result3[] = "a::b::c";
+
+TEST(StringRefTest, joinStrings) {
+ std::vector<StringRef> v1;
+ std::vector<std::string> v2;
+ for (size_t i = 0; i < array_lengthof(join_input); ++i) {
+ v1.push_back(join_input[i]);
+ v2.push_back(join_input[i]);
+ }
+
+ bool v1_join1 = join(v1.begin(), v1.begin() + 1, ":") == join_result1;
+ EXPECT_TRUE(v1_join1);
+ bool v1_join2 = join(v1.begin(), v1.end(), ":") == join_result2;
+ EXPECT_TRUE(v1_join2);
+ bool v1_join3 = join(v1.begin(), v1.end(), "::") == join_result3;
+ EXPECT_TRUE(v1_join3);
+
+ bool v2_join1 = join(v2.begin(), v2.begin() + 1, ":") == join_result1;
+ EXPECT_TRUE(v2_join1);
+ bool v2_join2 = join(v2.begin(), v2.end(), ":") == join_result2;
+ EXPECT_TRUE(v2_join2);
+ bool v2_join3 = join(v2.begin(), v2.end(), "::") == join_result3;
+ EXPECT_TRUE(v2_join3);
+ v2_join3 = join(v2, "::") == join_result3;
+ EXPECT_TRUE(v2_join3);
+}
+
+
+TEST(StringRefTest, AllocatorCopy) {
+ BumpPtrAllocator Alloc;
+ // First test empty strings. We don't want these to allocate anything on the
+ // allocator.
+ StringRef StrEmpty = "";
+ StringRef StrEmptyc = StrEmpty.copy(Alloc);
+ EXPECT_TRUE(StrEmpty.equals(StrEmptyc));
+ EXPECT_EQ(StrEmptyc.data(), nullptr);
+ EXPECT_EQ(StrEmptyc.size(), 0u);
+ EXPECT_EQ(Alloc.getTotalMemory(), 0u);
+
+ StringRef Str1 = "hello";
+ StringRef Str2 = "bye";
+ StringRef Str1c = Str1.copy(Alloc);
+ StringRef Str2c = Str2.copy(Alloc);
+ EXPECT_TRUE(Str1.equals(Str1c));
+ EXPECT_NE(Str1.data(), Str1c.data());
+ EXPECT_TRUE(Str2.equals(Str2c));
+ EXPECT_NE(Str2.data(), Str2c.data());
+}
+
+TEST(StringRefTest, Drop) {
+ StringRef Test("StringRefTest::Drop");
+
+ StringRef Dropped = Test.drop_front(5);
+ EXPECT_EQ(Dropped, "gRefTest::Drop");
+
+ Dropped = Test.drop_back(5);
+ EXPECT_EQ(Dropped, "StringRefTest:");
+
+ Dropped = Test.drop_front(0);
+ EXPECT_EQ(Dropped, Test);
+
+ Dropped = Test.drop_back(0);
+ EXPECT_EQ(Dropped, Test);
+
+ Dropped = Test.drop_front(Test.size());
+ EXPECT_TRUE(Dropped.empty());
+
+ Dropped = Test.drop_back(Test.size());
+ EXPECT_TRUE(Dropped.empty());
+}
+
+TEST(StringRefTest, Take) {
+ StringRef Test("StringRefTest::Take");
+
+ StringRef Taken = Test.take_front(5);
+ EXPECT_EQ(Taken, "Strin");
+
+ Taken = Test.take_back(5);
+ EXPECT_EQ(Taken, ":Take");
+
+ Taken = Test.take_front(Test.size());
+ EXPECT_EQ(Taken, Test);
+
+ Taken = Test.take_back(Test.size());
+ EXPECT_EQ(Taken, Test);
+
+ Taken = Test.take_front(0);
+ EXPECT_TRUE(Taken.empty());
+
+ Taken = Test.take_back(0);
+ EXPECT_TRUE(Taken.empty());
+}
+
+TEST(StringRefTest, FindIf) {
+ StringRef Punct("Test.String");
+ StringRef NoPunct("ABCDEFG");
+ StringRef Empty;
+
+ auto IsPunct = [](char c) { return ::ispunct(c); };
+ auto IsAlpha = [](char c) { return ::isalpha(c); };
+ EXPECT_EQ(4U, Punct.find_if(IsPunct));
+ EXPECT_EQ(StringRef::npos, NoPunct.find_if(IsPunct));
+ EXPECT_EQ(StringRef::npos, Empty.find_if(IsPunct));
+
+ EXPECT_EQ(4U, Punct.find_if_not(IsAlpha));
+ EXPECT_EQ(StringRef::npos, NoPunct.find_if_not(IsAlpha));
+ EXPECT_EQ(StringRef::npos, Empty.find_if_not(IsAlpha));
+}
+
+TEST(StringRefTest, TakeWhileUntil) {
+ StringRef Test("String With 1 Number");
+
+ StringRef Taken = Test.take_while([](char c) { return ::isdigit(c); });
+ EXPECT_EQ("", Taken);
+
+ Taken = Test.take_until([](char c) { return ::isdigit(c); });
+ EXPECT_EQ("String With ", Taken);
+
+ Taken = Test.take_while([](char c) { return true; });
+ EXPECT_EQ(Test, Taken);
+
+ Taken = Test.take_until([](char c) { return true; });
+ EXPECT_EQ("", Taken);
+
+ Test = "";
+ Taken = Test.take_while([](char c) { return true; });
+ EXPECT_EQ("", Taken);
+}
+
+TEST(StringRefTest, DropWhileUntil) {
+ StringRef Test("String With 1 Number");
+
+ StringRef Taken = Test.drop_while([](char c) { return ::isdigit(c); });
+ EXPECT_EQ(Test, Taken);
+
+ Taken = Test.drop_until([](char c) { return ::isdigit(c); });
+ EXPECT_EQ("1 Number", Taken);
+
+ Taken = Test.drop_while([](char c) { return true; });
+ EXPECT_EQ("", Taken);
+
+ Taken = Test.drop_until([](char c) { return true; });
+ EXPECT_EQ(Test, Taken);
+
+ StringRef EmptyString = "";
+ Taken = EmptyString.drop_while([](char c) { return true; });
+ EXPECT_EQ("", Taken);
+}
+
+TEST(StringRefTest, StringLiteral) {
+ constexpr StringLiteral Strings[] = {"Foo", "Bar"};
+ EXPECT_EQ(StringRef("Foo"), Strings[0]);
+ EXPECT_EQ(StringRef("Bar"), Strings[1]);
+}
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/StringSwitchTest.cpp b/src/llvm-project/llvm/unittests/ADT/StringSwitchTest.cpp
new file mode 100644
index 0000000..62d3a31
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/StringSwitchTest.cpp
@@ -0,0 +1,208 @@
+//===- llvm/unittest/ADT/StringSwitchTest.cpp - StringSwitch unit tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringSwitch.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(StringSwitchTest, Case) {
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<int>(S)
+ .Case("0", 0)
+ .Case("1", 1)
+ .Case("2", 2)
+ .Case("3", 3)
+ .Case("4", 4)
+ .Case("5", 5)
+ .Case("6", 6)
+ .Case("7", 7)
+ .Case("8", 8)
+ .Case("9", 9)
+ .Case("A", 10)
+ .Case("B", 11)
+ .Case("C", 12)
+ .Case("D", 13)
+ .Case("E", 14)
+ .Case("F", 15)
+ .Default(-1);
+ };
+ EXPECT_EQ(1, Translate("1"));
+ EXPECT_EQ(2, Translate("2"));
+ EXPECT_EQ(11, Translate("B"));
+ EXPECT_EQ(-1, Translate("b"));
+ EXPECT_EQ(-1, Translate(""));
+ EXPECT_EQ(-1, Translate("Test"));
+}
+
+TEST(StringSwitchTest, CaseLower) {
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<int>(S)
+ .Case("0", 0)
+ .Case("1", 1)
+ .Case("2", 2)
+ .Case("3", 3)
+ .Case("4", 4)
+ .Case("5", 5)
+ .Case("6", 6)
+ .Case("7", 7)
+ .Case("8", 8)
+ .Case("9", 9)
+ .CaseLower("A", 10)
+ .CaseLower("B", 11)
+ .CaseLower("C", 12)
+ .CaseLower("D", 13)
+ .CaseLower("E", 14)
+ .CaseLower("F", 15)
+ .Default(-1);
+ };
+ EXPECT_EQ(1, Translate("1"));
+ EXPECT_EQ(2, Translate("2"));
+ EXPECT_EQ(11, Translate("B"));
+ EXPECT_EQ(11, Translate("b"));
+
+ EXPECT_EQ(-1, Translate(""));
+ EXPECT_EQ(-1, Translate("Test"));
+}
+
+TEST(StringSwitchTest, StartsWith) {
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<std::function<int(int, int)>>(S)
+ .StartsWith("add", [](int X, int Y) { return X + Y; })
+ .StartsWith("sub", [](int X, int Y) { return X - Y; })
+ .StartsWith("mul", [](int X, int Y) { return X * Y; })
+ .StartsWith("div", [](int X, int Y) { return X / Y; })
+ .Default([](int X, int Y) { return 0; });
+ };
+
+ EXPECT_EQ(15, Translate("adder")(10, 5));
+ EXPECT_EQ(5, Translate("subtracter")(10, 5));
+ EXPECT_EQ(50, Translate("multiplier")(10, 5));
+ EXPECT_EQ(2, Translate("divider")(10, 5));
+
+ EXPECT_EQ(0, Translate("nothing")(10, 5));
+ EXPECT_EQ(0, Translate("ADDER")(10, 5));
+}
+
+TEST(StringSwitchTest, StartsWithLower) {
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<std::function<int(int, int)>>(S)
+ .StartsWithLower("add", [](int X, int Y) { return X + Y; })
+ .StartsWithLower("sub", [](int X, int Y) { return X - Y; })
+ .StartsWithLower("mul", [](int X, int Y) { return X * Y; })
+ .StartsWithLower("div", [](int X, int Y) { return X / Y; })
+ .Default([](int X, int Y) { return 0; });
+ };
+
+ EXPECT_EQ(15, Translate("adder")(10, 5));
+ EXPECT_EQ(5, Translate("subtracter")(10, 5));
+ EXPECT_EQ(50, Translate("multiplier")(10, 5));
+ EXPECT_EQ(2, Translate("divider")(10, 5));
+
+ EXPECT_EQ(15, Translate("AdDeR")(10, 5));
+ EXPECT_EQ(5, Translate("SuBtRaCtEr")(10, 5));
+ EXPECT_EQ(50, Translate("MuLtIpLiEr")(10, 5));
+ EXPECT_EQ(2, Translate("DiViDeR")(10, 5));
+
+ EXPECT_EQ(0, Translate("nothing")(10, 5));
+}
+
+TEST(StringSwitchTest, EndsWith) {
+ enum class Suffix { Possible, PastTense, Process, InProgressAction, Unknown };
+
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<Suffix>(S)
+ .EndsWith("able", Suffix::Possible)
+ .EndsWith("ed", Suffix::PastTense)
+ .EndsWith("ation", Suffix::Process)
+ .EndsWith("ing", Suffix::InProgressAction)
+ .Default(Suffix::Unknown);
+ };
+
+ EXPECT_EQ(Suffix::Possible, Translate("optimizable"));
+ EXPECT_EQ(Suffix::PastTense, Translate("optimized"));
+ EXPECT_EQ(Suffix::Process, Translate("optimization"));
+ EXPECT_EQ(Suffix::InProgressAction, Translate("optimizing"));
+ EXPECT_EQ(Suffix::Unknown, Translate("optimizer"));
+ EXPECT_EQ(Suffix::Unknown, Translate("OPTIMIZABLE"));
+}
+
+TEST(StringSwitchTest, EndsWithLower) {
+ enum class Suffix { Possible, PastTense, Process, InProgressAction, Unknown };
+
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<Suffix>(S)
+ .EndsWithLower("able", Suffix::Possible)
+ .EndsWithLower("ed", Suffix::PastTense)
+ .EndsWithLower("ation", Suffix::Process)
+ .EndsWithLower("ing", Suffix::InProgressAction)
+ .Default(Suffix::Unknown);
+ };
+
+ EXPECT_EQ(Suffix::Possible, Translate("optimizable"));
+ EXPECT_EQ(Suffix::Possible, Translate("OPTIMIZABLE"));
+ EXPECT_EQ(Suffix::PastTense, Translate("optimized"));
+ EXPECT_EQ(Suffix::Process, Translate("optimization"));
+ EXPECT_EQ(Suffix::InProgressAction, Translate("optimizing"));
+ EXPECT_EQ(Suffix::Unknown, Translate("optimizer"));
+}
+
+TEST(StringSwitchTest, Cases) {
+ enum class OSType { Windows, Linux, Unknown };
+
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<OSType>(S)
+ .Cases(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
+ .Cases("linux", "unix", "*nix", "posix", OSType::Linux)
+ .Default(OSType::Unknown);
+ };
+
+ EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7)));
+ EXPECT_EQ(OSType::Windows, Translate("win32"));
+ EXPECT_EQ(OSType::Windows, Translate("winnt"));
+
+ EXPECT_EQ(OSType::Linux, Translate("linux"));
+ EXPECT_EQ(OSType::Linux, Translate("unix"));
+ EXPECT_EQ(OSType::Linux, Translate("*nix"));
+ EXPECT_EQ(OSType::Linux, Translate("posix"));
+
+ // Note that the whole null-terminator embedded string is required for the
+ // case to match.
+ EXPECT_EQ(OSType::Unknown, Translate("wind"));
+ EXPECT_EQ(OSType::Unknown, Translate("Windows"));
+ EXPECT_EQ(OSType::Unknown, Translate(""));
+}
+
+TEST(StringSwitchTest, CasesLower) {
+ enum class OSType { Windows, Linux, Unknown };
+
+ auto Translate = [](StringRef S) {
+ return llvm::StringSwitch<OSType>(S)
+ .CasesLower(StringLiteral::withInnerNUL("wind\0ws"), "win32", "winnt",
+ OSType::Windows)
+ .CasesLower("linux", "unix", "*nix", "posix", OSType::Linux)
+ .Default(OSType::Unknown);
+ };
+
+ EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("WIND\0WS", 7)));
+ EXPECT_EQ(OSType::Windows, Translate("WIN32"));
+ EXPECT_EQ(OSType::Windows, Translate("WINNT"));
+
+ EXPECT_EQ(OSType::Linux, Translate("LINUX"));
+ EXPECT_EQ(OSType::Linux, Translate("UNIX"));
+ EXPECT_EQ(OSType::Linux, Translate("*NIX"));
+ EXPECT_EQ(OSType::Linux, Translate("POSIX"));
+
+ EXPECT_EQ(OSType::Windows, Translate(llvm::StringRef("wind\0ws", 7)));
+ EXPECT_EQ(OSType::Linux, Translate("linux"));
+
+ EXPECT_EQ(OSType::Unknown, Translate("wind"));
+ EXPECT_EQ(OSType::Unknown, Translate(""));
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/TestGraph.h b/src/llvm-project/llvm/unittests/ADT/TestGraph.h
new file mode 100644
index 0000000..4ddd14c
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/TestGraph.h
@@ -0,0 +1,251 @@
+//===- llvm/unittest/ADT/TestGraph.h - Graph for testing ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common graph data structure for testing.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UNITTESTS_ADT_TEST_GRAPH_H
+#define LLVM_UNITTESTS_ADT_TEST_GRAPH_H
+
+#include "llvm/ADT/GraphTraits.h"
+#include <cassert>
+#include <climits>
+#include <utility>
+
+namespace llvm {
+
+/// Graph<N> - A graph with N nodes. Note that N can be at most 8.
+template <unsigned N>
+class Graph {
+private:
+ // Disable copying.
+ Graph(const Graph&);
+ Graph& operator=(const Graph&);
+
+ static void ValidateIndex(unsigned Idx) {
+ assert(Idx < N && "Invalid node index!");
+ }
+public:
+
+ /// NodeSubset - A subset of the graph's nodes.
+ class NodeSubset {
+ typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
+ BitVector Elements;
+ NodeSubset(BitVector e) : Elements(e) {}
+ public:
+ /// NodeSubset - Default constructor, creates an empty subset.
+ NodeSubset() : Elements(0) {
+ assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
+ }
+
+ /// Comparison operators.
+ bool operator==(const NodeSubset &other) const {
+ return other.Elements == this->Elements;
+ }
+ bool operator!=(const NodeSubset &other) const {
+ return !(*this == other);
+ }
+
+ /// AddNode - Add the node with the given index to the subset.
+ void AddNode(unsigned Idx) {
+ ValidateIndex(Idx);
+ Elements |= 1U << Idx;
+ }
+
+ /// DeleteNode - Remove the node with the given index from the subset.
+ void DeleteNode(unsigned Idx) {
+ ValidateIndex(Idx);
+ Elements &= ~(1U << Idx);
+ }
+
+ /// count - Return true if the node with the given index is in the subset.
+ bool count(unsigned Idx) {
+ ValidateIndex(Idx);
+ return (Elements & (1U << Idx)) != 0;
+ }
+
+ /// isEmpty - Return true if this is the empty set.
+ bool isEmpty() const {
+ return Elements == 0;
+ }
+
+ /// isSubsetOf - Return true if this set is a subset of the given one.
+ bool isSubsetOf(const NodeSubset &other) const {
+ return (this->Elements | other.Elements) == other.Elements;
+ }
+
+ /// Complement - Return the complement of this subset.
+ NodeSubset Complement() const {
+ return ~(unsigned)this->Elements & ((1U << N) - 1);
+ }
+
+ /// Join - Return the union of this subset and the given one.
+ NodeSubset Join(const NodeSubset &other) const {
+ return this->Elements | other.Elements;
+ }
+
+ /// Meet - Return the intersection of this subset and the given one.
+ NodeSubset Meet(const NodeSubset &other) const {
+ return this->Elements & other.Elements;
+ }
+ };
+
+ /// NodeType - Node index and set of children of the node.
+ typedef std::pair<unsigned, NodeSubset> NodeType;
+
+private:
+ /// Nodes - The list of nodes for this graph.
+ NodeType Nodes[N];
+public:
+
+ /// Graph - Default constructor. Creates an empty graph.
+ Graph() {
+ // Let each node know which node it is. This allows us to find the start of
+ // the Nodes array given a pointer to any element of it.
+ for (unsigned i = 0; i != N; ++i)
+ Nodes[i].first = i;
+ }
+
+ /// AddEdge - Add an edge from the node with index FromIdx to the node with
+ /// index ToIdx.
+ void AddEdge(unsigned FromIdx, unsigned ToIdx) {
+ ValidateIndex(FromIdx);
+ Nodes[FromIdx].second.AddNode(ToIdx);
+ }
+
+ /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
+ /// the node with index ToIdx.
+ void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
+ ValidateIndex(FromIdx);
+ Nodes[FromIdx].second.DeleteNode(ToIdx);
+ }
+
+ /// AccessNode - Get a pointer to the node with the given index.
+ NodeType *AccessNode(unsigned Idx) const {
+ ValidateIndex(Idx);
+ // The constant cast is needed when working with GraphTraits, which insists
+ // on taking a constant Graph.
+ return const_cast<NodeType *>(&Nodes[Idx]);
+ }
+
+ /// NodesReachableFrom - Return the set of all nodes reachable from the given
+ /// node.
+ NodeSubset NodesReachableFrom(unsigned Idx) const {
+ // This algorithm doesn't scale, but that doesn't matter given the small
+ // size of our graphs.
+ NodeSubset Reachable;
+
+ // The initial node is reachable.
+ Reachable.AddNode(Idx);
+ do {
+ NodeSubset Previous(Reachable);
+
+ // Add in all nodes which are children of a reachable node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Previous.count(i))
+ Reachable = Reachable.Join(Nodes[i].second);
+
+ // If nothing changed then we have found all reachable nodes.
+ if (Reachable == Previous)
+ return Reachable;
+
+ // Rinse and repeat.
+ } while (1);
+ }
+
+ /// ChildIterator - Visit all children of a node.
+ class ChildIterator {
+ friend class Graph;
+
+ /// FirstNode - Pointer to first node in the graph's Nodes array.
+ NodeType *FirstNode;
+ /// Children - Set of nodes which are children of this one and that haven't
+ /// yet been visited.
+ NodeSubset Children;
+
+ ChildIterator(); // Disable default constructor.
+ protected:
+ ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}
+
+ public:
+ /// ChildIterator - Copy constructor.
+ ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode),
+ Children(other.Children) {}
+
+ /// Comparison operators.
+ bool operator==(const ChildIterator &other) const {
+ return other.FirstNode == this->FirstNode &&
+ other.Children == this->Children;
+ }
+ bool operator!=(const ChildIterator &other) const {
+ return !(*this == other);
+ }
+
+ /// Prefix increment operator.
+ ChildIterator& operator++() {
+ // Find the next unvisited child node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Children.count(i)) {
+ // Remove that child - it has been visited. This is the increment!
+ Children.DeleteNode(i);
+ return *this;
+ }
+ assert(false && "Incrementing end iterator!");
+ return *this; // Avoid compiler warnings.
+ }
+
+ /// Postfix increment operator.
+ ChildIterator operator++(int) {
+ ChildIterator Result(*this);
+ ++(*this);
+ return Result;
+ }
+
+ /// Dereference operator.
+ NodeType *operator*() {
+ // Find the next unvisited child node.
+ for (unsigned i = 0; i != N; ++i)
+ if (Children.count(i))
+ // Return a pointer to it.
+ return FirstNode + i;
+ assert(false && "Dereferencing end iterator!");
+ return nullptr; // Avoid compiler warning.
+ }
+ };
+
+ /// child_begin - Return an iterator pointing to the first child of the given
+ /// node.
+ static ChildIterator child_begin(NodeType *Parent) {
+ return ChildIterator(Parent - Parent->first, Parent->second);
+ }
+
+ /// child_end - Return the end iterator for children of the given node.
+ static ChildIterator child_end(NodeType *Parent) {
+ return ChildIterator(Parent - Parent->first, NodeSubset());
+ }
+};
+
+template <unsigned N>
+struct GraphTraits<Graph<N> > {
+ typedef typename Graph<N>::NodeType *NodeRef;
+ typedef typename Graph<N>::ChildIterator ChildIteratorType;
+
+ static NodeRef getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
+ static ChildIteratorType child_begin(NodeRef Node) {
+ return Graph<N>::child_begin(Node);
+ }
+ static ChildIteratorType child_end(NodeRef Node) {
+ return Graph<N>::child_end(Node);
+ }
+};
+
+} // End namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/unittests/ADT/TinyPtrVectorTest.cpp b/src/llvm-project/llvm/unittests/ADT/TinyPtrVectorTest.cpp
new file mode 100644
index 0000000..cc14ccc
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/TinyPtrVectorTest.cpp
@@ -0,0 +1,459 @@
+//===- llvm/unittest/ADT/TinyPtrVectorTest.cpp ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// TinyPtrVector unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/type_traits.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <random>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+template <typename VectorT>
+class TinyPtrVectorTest : public testing::Test {
+protected:
+ typedef typename VectorT::value_type PtrT;
+ typedef typename std::remove_pointer<PtrT>::type ValueT;
+
+ VectorT V;
+ VectorT V2;
+
+ ValueT TestValues[1024];
+ std::vector<PtrT> TestPtrs;
+
+ TinyPtrVectorTest() {
+ for (size_t i = 0, e = array_lengthof(TestValues); i != e; ++i)
+ TestPtrs.push_back(&TestValues[i]);
+
+ std::shuffle(TestPtrs.begin(), TestPtrs.end(), std::mt19937{});
+ }
+
+ ArrayRef<PtrT> testArray(size_t N) {
+ return makeArrayRef(&TestPtrs[0], N);
+ }
+
+ void appendValues(VectorT &V, ArrayRef<PtrT> Values) {
+ for (size_t i = 0, e = Values.size(); i != e; ++i)
+ V.push_back(Values[i]);
+ }
+
+ void setVectors(ArrayRef<PtrT> Values1, ArrayRef<PtrT> Values2) {
+ V.clear();
+ appendValues(V, Values1);
+ V2.clear();
+ appendValues(V2, Values2);
+ }
+
+ void expectValues(const VectorT &V, ArrayRef<PtrT> Values) {
+ EXPECT_EQ(Values.empty(), V.empty());
+ EXPECT_EQ(Values.size(), V.size());
+ for (size_t i = 0, e = Values.size(); i != e; ++i) {
+ EXPECT_EQ(Values[i], V[i]);
+ EXPECT_EQ(Values[i], *std::next(V.begin(), i));
+ }
+ EXPECT_EQ(V.end(), std::next(V.begin(), Values.size()));
+ }
+};
+
+typedef ::testing::Types<TinyPtrVector<int*>,
+ TinyPtrVector<double*>
+ > TinyPtrVectorTestTypes;
+TYPED_TEST_CASE(TinyPtrVectorTest, TinyPtrVectorTestTypes);
+
+TYPED_TEST(TinyPtrVectorTest, EmptyTest) {
+ this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, PushPopBack) {
+ this->V.push_back(this->TestPtrs[0]);
+ this->expectValues(this->V, this->testArray(1));
+ this->V.push_back(this->TestPtrs[1]);
+ this->expectValues(this->V, this->testArray(2));
+ this->V.push_back(this->TestPtrs[2]);
+ this->expectValues(this->V, this->testArray(3));
+ this->V.push_back(this->TestPtrs[3]);
+ this->expectValues(this->V, this->testArray(4));
+ this->V.push_back(this->TestPtrs[4]);
+ this->expectValues(this->V, this->testArray(5));
+
+ // Pop and clobber a few values to keep things interesting.
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(4));
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(3));
+ this->TestPtrs[3] = &this->TestValues[42];
+ this->TestPtrs[4] = &this->TestValues[43];
+ this->V.push_back(this->TestPtrs[3]);
+ this->expectValues(this->V, this->testArray(4));
+ this->V.push_back(this->TestPtrs[4]);
+ this->expectValues(this->V, this->testArray(5));
+
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(4));
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(3));
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(2));
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(1));
+ this->V.pop_back();
+ this->expectValues(this->V, this->testArray(0));
+
+ this->appendValues(this->V, this->testArray(42));
+ this->expectValues(this->V, this->testArray(42));
+}
+
+TYPED_TEST(TinyPtrVectorTest, ClearTest) {
+ this->expectValues(this->V, this->testArray(0));
+ this->V.clear();
+ this->expectValues(this->V, this->testArray(0));
+
+ this->appendValues(this->V, this->testArray(1));
+ this->expectValues(this->V, this->testArray(1));
+ this->V.clear();
+ this->expectValues(this->V, this->testArray(0));
+
+ this->appendValues(this->V, this->testArray(42));
+ this->expectValues(this->V, this->testArray(42));
+ this->V.clear();
+ this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, CopyAndMoveCtorTest) {
+ this->appendValues(this->V, this->testArray(42));
+ TypeParam Copy(this->V);
+ this->expectValues(Copy, this->testArray(42));
+
+ // This is a separate copy, and so it shouldn't destroy the original.
+ Copy.clear();
+ this->expectValues(Copy, this->testArray(0));
+ this->expectValues(this->V, this->testArray(42));
+
+ TypeParam Copy2(this->V2);
+ this->appendValues(Copy2, this->testArray(42));
+ this->expectValues(Copy2, this->testArray(42));
+ this->expectValues(this->V2, this->testArray(0));
+
+ TypeParam Move(std::move(Copy2));
+ this->expectValues(Move, this->testArray(42));
+ this->expectValues(Copy2, this->testArray(0));
+
+ TypeParam MultipleElements(this->testArray(2));
+ TypeParam SingleElement(this->testArray(1));
+ MultipleElements = std::move(SingleElement);
+ this->expectValues(MultipleElements, this->testArray(1));
+ this->expectValues(SingleElement, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, CopyAndMoveTest) {
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(0));
+ this->expectValues(this->V2, this->testArray(0));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(0));
+
+ this->setVectors(this->testArray(1), this->testArray(0));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(0));
+ this->expectValues(this->V2, this->testArray(0));
+ this->setVectors(this->testArray(1), this->testArray(0));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(0));
+
+ this->setVectors(this->testArray(2), this->testArray(0));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(0));
+ this->expectValues(this->V2, this->testArray(0));
+ this->setVectors(this->testArray(2), this->testArray(0));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(0));
+
+ this->setVectors(this->testArray(42), this->testArray(0));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(0));
+ this->expectValues(this->V2, this->testArray(0));
+ this->setVectors(this->testArray(42), this->testArray(0));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(0));
+
+ this->setVectors(this->testArray(0), this->testArray(1));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(1));
+ this->expectValues(this->V2, this->testArray(1));
+ this->setVectors(this->testArray(0), this->testArray(1));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(1));
+
+ this->setVectors(this->testArray(0), this->testArray(2));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(2));
+ this->expectValues(this->V2, this->testArray(2));
+ this->setVectors(this->testArray(0), this->testArray(2));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(2));
+
+ this->setVectors(this->testArray(0), this->testArray(42));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(42));
+ this->expectValues(this->V2, this->testArray(42));
+ this->setVectors(this->testArray(0), this->testArray(42));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(42));
+
+ this->setVectors(this->testArray(1), this->testArray(1));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(1));
+ this->expectValues(this->V2, this->testArray(1));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(1));
+
+ this->setVectors(this->testArray(1), this->testArray(2));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(2));
+ this->expectValues(this->V2, this->testArray(2));
+ this->setVectors(this->testArray(1), this->testArray(2));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(2));
+
+ this->setVectors(this->testArray(1), this->testArray(42));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(42));
+ this->expectValues(this->V2, this->testArray(42));
+ this->setVectors(this->testArray(1), this->testArray(42));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(42));
+
+ this->setVectors(this->testArray(2), this->testArray(1));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(1));
+ this->expectValues(this->V2, this->testArray(1));
+ this->setVectors(this->testArray(2), this->testArray(1));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(1));
+
+ this->setVectors(this->testArray(2), this->testArray(2));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(2));
+ this->expectValues(this->V2, this->testArray(2));
+ this->setVectors(this->testArray(2), this->testArray(2));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(2));
+
+ this->setVectors(this->testArray(2), this->testArray(42));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(42));
+ this->expectValues(this->V2, this->testArray(42));
+ this->setVectors(this->testArray(2), this->testArray(42));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(42));
+
+ this->setVectors(this->testArray(42), this->testArray(1));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(1));
+ this->expectValues(this->V2, this->testArray(1));
+ this->setVectors(this->testArray(42), this->testArray(1));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(1));
+
+ this->setVectors(this->testArray(42), this->testArray(2));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(2));
+ this->expectValues(this->V2, this->testArray(2));
+ this->setVectors(this->testArray(42), this->testArray(2));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(2));
+
+ this->setVectors(this->testArray(42), this->testArray(42));
+ this->V = this->V2;
+ this->expectValues(this->V, this->testArray(42));
+ this->expectValues(this->V2, this->testArray(42));
+ this->setVectors(this->testArray(42), this->testArray(42));
+ this->V = std::move(this->V2);
+ this->expectValues(this->V, this->testArray(42));
+}
+
+TYPED_TEST(TinyPtrVectorTest, EraseTest) {
+ this->appendValues(this->V, this->testArray(1));
+ this->expectValues(this->V, this->testArray(1));
+ this->V.erase(this->V.begin());
+ this->expectValues(this->V, this->testArray(0));
+
+ this->appendValues(this->V, this->testArray(42));
+ this->expectValues(this->V, this->testArray(42));
+ this->V.erase(this->V.begin());
+ this->TestPtrs.erase(this->TestPtrs.begin());
+ this->expectValues(this->V, this->testArray(41));
+ this->V.erase(std::next(this->V.begin(), 1));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1));
+ this->expectValues(this->V, this->testArray(40));
+ this->V.erase(std::next(this->V.begin(), 2));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2));
+ this->expectValues(this->V, this->testArray(39));
+ this->V.erase(std::next(this->V.begin(), 5));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5));
+ this->expectValues(this->V, this->testArray(38));
+ this->V.erase(std::next(this->V.begin(), 13));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13));
+ this->expectValues(this->V, this->testArray(37));
+
+ typename TypeParam::iterator I = this->V.begin();
+ do {
+ I = this->V.erase(I);
+ } while (I != this->V.end());
+ this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, EraseRangeTest) {
+ this->appendValues(this->V, this->testArray(1));
+ this->expectValues(this->V, this->testArray(1));
+ this->V.erase(this->V.begin(), this->V.begin());
+ this->expectValues(this->V, this->testArray(1));
+ this->V.erase(this->V.end(), this->V.end());
+ this->expectValues(this->V, this->testArray(1));
+ this->V.erase(this->V.begin(), this->V.end());
+ this->expectValues(this->V, this->testArray(0));
+
+ this->appendValues(this->V, this->testArray(42));
+ this->expectValues(this->V, this->testArray(42));
+ this->V.erase(this->V.begin(), std::next(this->V.begin(), 1));
+ this->TestPtrs.erase(this->TestPtrs.begin(),
+ std::next(this->TestPtrs.begin(), 1));
+ this->expectValues(this->V, this->testArray(41));
+ this->V.erase(std::next(this->V.begin(), 1), std::next(this->V.begin(), 2));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 1),
+ std::next(this->TestPtrs.begin(), 2));
+ this->expectValues(this->V, this->testArray(40));
+ this->V.erase(std::next(this->V.begin(), 2), std::next(this->V.begin(), 4));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 2),
+ std::next(this->TestPtrs.begin(), 4));
+ this->expectValues(this->V, this->testArray(38));
+ this->V.erase(std::next(this->V.begin(), 5), std::next(this->V.begin(), 10));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 5),
+ std::next(this->TestPtrs.begin(), 10));
+ this->expectValues(this->V, this->testArray(33));
+ this->V.erase(std::next(this->V.begin(), 13), std::next(this->V.begin(), 26));
+ this->TestPtrs.erase(std::next(this->TestPtrs.begin(), 13),
+ std::next(this->TestPtrs.begin(), 26));
+ this->expectValues(this->V, this->testArray(20));
+ this->V.erase(std::next(this->V.begin(), 7), this->V.end());
+ this->expectValues(this->V, this->testArray(7));
+ this->V.erase(this->V.begin(), this->V.end());
+ this->expectValues(this->V, this->testArray(0));
+}
+
+TYPED_TEST(TinyPtrVectorTest, Insert) {
+ this->V.insert(this->V.end(), this->TestPtrs[0]);
+ this->expectValues(this->V, this->testArray(1));
+ this->V.clear();
+ this->appendValues(this->V, this->testArray(4));
+ this->expectValues(this->V, this->testArray(4));
+ this->V.insert(this->V.end(), this->TestPtrs[4]);
+ this->expectValues(this->V, this->testArray(5));
+ this->V.insert(this->V.begin(), this->TestPtrs[42]);
+ this->TestPtrs.insert(this->TestPtrs.begin(), this->TestPtrs[42]);
+ this->expectValues(this->V, this->testArray(6));
+ this->V.insert(std::next(this->V.begin(), 3), this->TestPtrs[43]);
+ this->TestPtrs.insert(std::next(this->TestPtrs.begin(), 3),
+ this->TestPtrs[43]);
+ this->expectValues(this->V, this->testArray(7));
+}
+
+TYPED_TEST(TinyPtrVectorTest, InsertRange) {
+ this->V.insert(this->V.end(), this->TestPtrs.begin(), this->TestPtrs.begin());
+ this->expectValues(this->V, this->testArray(0));
+ this->V.insert(this->V.begin(), this->TestPtrs.begin(),
+ this->TestPtrs.begin());
+ this->expectValues(this->V, this->testArray(0));
+ this->V.insert(this->V.end(), this->TestPtrs.end(), this->TestPtrs.end());
+ this->expectValues(this->V, this->testArray(0));
+ this->V.insert(this->V.end(), this->TestPtrs.begin(),
+ std::next(this->TestPtrs.begin()));
+ this->expectValues(this->V, this->testArray(1));
+ this->V.clear();
+ this->V.insert(this->V.end(), this->TestPtrs.begin(),
+ std::next(this->TestPtrs.begin(), 2));
+ this->expectValues(this->V, this->testArray(2));
+ this->V.clear();
+ this->V.insert(this->V.end(), this->TestPtrs.begin(),
+ std::next(this->TestPtrs.begin(), 42));
+ this->expectValues(this->V, this->testArray(42));
+ this->V.clear();
+ this->V.insert(this->V.end(),
+ std::next(this->TestPtrs.begin(), 5),
+ std::next(this->TestPtrs.begin(), 13));
+ this->V.insert(this->V.begin(),
+ std::next(this->TestPtrs.begin(), 0),
+ std::next(this->TestPtrs.begin(), 3));
+ this->V.insert(std::next(this->V.begin(), 2),
+ std::next(this->TestPtrs.begin(), 2),
+ std::next(this->TestPtrs.begin(), 4));
+ this->V.erase(std::next(this->V.begin(), 4));
+ this->V.insert(std::next(this->V.begin(), 4),
+ std::next(this->TestPtrs.begin(), 4),
+ std::next(this->TestPtrs.begin(), 5));
+ this->expectValues(this->V, this->testArray(13));
+}
+
+}
+
+TEST(TinyPtrVectorTest, SingleEltCtorTest) {
+ int v = 55;
+ TinyPtrVector<int *> V(&v);
+
+ EXPECT_TRUE(V.size() == 1);
+ EXPECT_FALSE(V.empty());
+ EXPECT_TRUE(V.front() == &v);
+}
+
+TEST(TinyPtrVectorTest, ArrayRefCtorTest) {
+ int data_array[128];
+ std::vector<int *> data;
+
+ for (unsigned i = 0, e = 128; i != e; ++i) {
+ data_array[i] = 324 - int(i);
+ data.push_back(&data_array[i]);
+ }
+
+ TinyPtrVector<int *> V(data);
+ EXPECT_TRUE(V.size() == 128);
+ EXPECT_FALSE(V.empty());
+ for (unsigned i = 0, e = 128; i != e; ++i) {
+ EXPECT_TRUE(V[i] == data[i]);
+ }
+}
+
+TEST(TinyPtrVectorTest, MutableArrayRefTest) {
+ int data_array[128];
+ std::vector<int *> data;
+
+ for (unsigned i = 0, e = 128; i != e; ++i) {
+ data_array[i] = 324 - int(i);
+ data.push_back(&data_array[i]);
+ }
+
+ TinyPtrVector<int *> V(data);
+ EXPECT_TRUE(V.size() == 128);
+ EXPECT_FALSE(V.empty());
+
+ MutableArrayRef<int *> mut_array = V;
+ for (unsigned i = 0, e = 128; i != e; ++i) {
+ EXPECT_TRUE(mut_array[i] == data[i]);
+ mut_array[i] = 324 + mut_array[i];
+ EXPECT_TRUE(mut_array[i] == (324 + data[i]));
+ }
+}
diff --git a/src/llvm-project/llvm/unittests/ADT/TripleTest.cpp b/src/llvm-project/llvm/unittests/ADT/TripleTest.cpp
new file mode 100644
index 0000000..bc7f932
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/TripleTest.cpp
@@ -0,0 +1,1452 @@
+//===----------- Triple.cpp - Triple unit tests ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Triple.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(TripleTest, BasicParsing) {
+ Triple T;
+
+ T = Triple("");
+ EXPECT_EQ("", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("-");
+ EXPECT_EQ("", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("--");
+ EXPECT_EQ("", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("---");
+ EXPECT_EQ("", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("----");
+ EXPECT_EQ("", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("-", T.getEnvironmentName().str());
+
+ T = Triple("a");
+ EXPECT_EQ("a", T.getArchName().str());
+ EXPECT_EQ("", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("a-b");
+ EXPECT_EQ("a", T.getArchName().str());
+ EXPECT_EQ("b", T.getVendorName().str());
+ EXPECT_EQ("", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("a-b-c");
+ EXPECT_EQ("a", T.getArchName().str());
+ EXPECT_EQ("b", T.getVendorName().str());
+ EXPECT_EQ("c", T.getOSName().str());
+ EXPECT_EQ("", T.getEnvironmentName().str());
+
+ T = Triple("a-b-c-d");
+ EXPECT_EQ("a", T.getArchName().str());
+ EXPECT_EQ("b", T.getVendorName().str());
+ EXPECT_EQ("c", T.getOSName().str());
+ EXPECT_EQ("d", T.getEnvironmentName().str());
+}
+
+TEST(TripleTest, ParsedIDs) {
+ Triple T;
+
+ T = Triple("i386-apple-darwin");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::Apple, T.getVendor());
+ EXPECT_EQ(Triple::Darwin, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("i386-pc-elfiamcu");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::ELFIAMCU, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("i386-pc-contiki-unknown");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Contiki, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("i386-pc-hurd-gnu");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Hurd, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("x86_64-pc-linux-gnu");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("x86_64-pc-linux-musl");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::Musl, T.getEnvironment());
+
+ T = Triple("powerpc-bgp-linux");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("powerpc-bgp-cnk");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::CNK, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("ppc-bgp-linux");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("ppc32-bgp-linux");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::BGP, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("powerpc64-bgq-linux");
+ EXPECT_EQ(Triple::ppc64, T.getArch());
+ EXPECT_EQ(Triple::BGQ, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("ppc64-bgq-linux");
+ EXPECT_EQ(Triple::ppc64, T.getArch());
+ EXPECT_EQ(Triple::BGQ, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+
+ T = Triple("powerpc-ibm-aix");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::IBM, T.getVendor());
+ EXPECT_EQ(Triple::AIX, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("powerpc64-ibm-aix");
+ EXPECT_EQ(Triple::ppc64, T.getArch());
+ EXPECT_EQ(Triple::IBM, T.getVendor());
+ EXPECT_EQ(Triple::AIX, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("powerpc-dunno-notsure");
+ EXPECT_EQ(Triple::ppc, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("arm-none-none-eabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::EABI, T.getEnvironment());
+
+ T = Triple("arm-none-linux-musleabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::MuslEABI, T.getEnvironment());
+
+ T = Triple("armv6hl-none-linux-gnueabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
+
+ T = Triple("armv7hl-none-linux-gnueabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
+
+ T = Triple("amdil-unknown-unknown");
+ EXPECT_EQ(Triple::amdil, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("amdil64-unknown-unknown");
+ EXPECT_EQ(Triple::amdil64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("hsail-unknown-unknown");
+ EXPECT_EQ(Triple::hsail, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("hsail64-unknown-unknown");
+ EXPECT_EQ(Triple::hsail64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("sparcel-unknown-unknown");
+ EXPECT_EQ(Triple::sparcel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spir-unknown-unknown");
+ EXPECT_EQ(Triple::spir, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("spir64-unknown-unknown");
+ EXPECT_EQ(Triple::spir64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+
+ T = Triple("x86_64-unknown-ananas");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Ananas, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("x86_64-unknown-cloudabi");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::CloudABI, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("x86_64-unknown-fuchsia");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Fuchsia, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("x86_64-unknown-hermit");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::HermitCore, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("wasm32-unknown-unknown");
+ EXPECT_EQ(Triple::wasm32, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("wasm32-unknown-wasi-musl");
+ EXPECT_EQ(Triple::wasm32, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::WASI, T.getOS());
+ EXPECT_EQ(Triple::Musl, T.getEnvironment());
+
+ T = Triple("wasm64-unknown-unknown");
+ EXPECT_EQ(Triple::wasm64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("wasm64-unknown-wasi-musl");
+ EXPECT_EQ(Triple::wasm64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::WASI, T.getOS());
+ EXPECT_EQ(Triple::Musl, T.getEnvironment());
+
+ T = Triple("avr-unknown-unknown");
+ EXPECT_EQ(Triple::avr, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("avr");
+ EXPECT_EQ(Triple::avr, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("lanai-unknown-unknown");
+ EXPECT_EQ(Triple::lanai, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("lanai");
+ EXPECT_EQ(Triple::lanai, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("amdgcn-mesa-mesa3d");
+ EXPECT_EQ(Triple::amdgcn, T.getArch());
+ EXPECT_EQ(Triple::Mesa, T.getVendor());
+ EXPECT_EQ(Triple::Mesa3D, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("amdgcn-amd-amdhsa");
+ EXPECT_EQ(Triple::amdgcn, T.getArch());
+ EXPECT_EQ(Triple::AMD, T.getVendor());
+ EXPECT_EQ(Triple::AMDHSA, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("amdgcn-amd-amdpal");
+ EXPECT_EQ(Triple::amdgcn, T.getArch());
+ EXPECT_EQ(Triple::AMD, T.getVendor());
+ EXPECT_EQ(Triple::AMDPAL, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("riscv32-unknown-unknown");
+ EXPECT_EQ(Triple::riscv32, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("riscv64-unknown-linux");
+ EXPECT_EQ(Triple::riscv64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("riscv64-unknown-freebsd");
+ EXPECT_EQ(Triple::riscv64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::FreeBSD, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("armv7hl-suse-linux-gnueabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::SUSE, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
+
+ T = Triple("i586-pc-haiku");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Haiku, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("x86_64-unknown-haiku");
+ EXPECT_EQ(Triple::x86_64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Haiku, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("mips-mti-linux-gnu");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::MipsTechnologies, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("mipsel-img-linux-gnu");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("mips64-mti-linux-gnu");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::MipsTechnologies, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("mips64el-img-linux-gnu");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+
+ T = Triple("mips64el-img-linux-gnuabin32");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::ImaginationTechnologies, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+
+ T = Triple("mips64el-unknown-linux-gnuabi64");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mips64el");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mips64-unknown-linux-gnuabi64");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mips64");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mipsisa64r6el-unknown-linux-gnuabi64");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mips64r6el");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsisa64r6el");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("mipsisa64r6-unknown-linux-gnuabi64");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mips64r6");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsisa64r6");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABI64, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("mips64el-unknown-linux-gnuabin32");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mipsn32el");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mips64-unknown-linux-gnuabin32");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mipsn32");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mipsisa64r6el-unknown-linux-gnuabin32");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsn32r6el");
+ EXPECT_EQ(Triple::mips64el, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("mipsisa64r6-unknown-linux-gnuabin32");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsn32r6");
+ EXPECT_EQ(Triple::mips64, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNUABIN32, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("mipsel-unknown-linux-gnu");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mipsel");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mips-unknown-linux-gnu");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+ T = Triple("mips");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::NoSubArch, T.getSubArch());
+
+ T = Triple("mipsisa32r6el-unknown-linux-gnu");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsr6el");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsisa32r6el");
+ EXPECT_EQ(Triple::mipsel, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("mipsisa32r6-unknown-linux-gnu");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsr6");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+ T = Triple("mipsisa32r6");
+ EXPECT_EQ(Triple::mips, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::GNU, T.getEnvironment());
+ EXPECT_EQ(Triple::MipsSubArch_r6, T.getSubArch());
+
+ T = Triple("arm-oe-linux-gnueabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ EXPECT_EQ(Triple::OpenEmbedded, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
+
+ T = Triple("aarch64-oe-linux");
+ EXPECT_EQ(Triple::aarch64, T.getArch());
+ EXPECT_EQ(Triple::OpenEmbedded, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T = Triple("huh");
+ EXPECT_EQ(Triple::UnknownArch, T.getArch());
+}
+
+static std::string Join(StringRef A, StringRef B, StringRef C) {
+ std::string Str = A;
+ Str += '-';
+ Str += B;
+ Str += '-';
+ Str += C;
+ return Str;
+}
+
+static std::string Join(StringRef A, StringRef B, StringRef C, StringRef D) {
+ std::string Str = A;
+ Str += '-';
+ Str += B;
+ Str += '-';
+ Str += C;
+ Str += '-';
+ Str += D;
+ return Str;
+}
+
+TEST(TripleTest, Normalization) {
+
+ EXPECT_EQ("unknown", Triple::normalize(""));
+ EXPECT_EQ("unknown-unknown", Triple::normalize("-"));
+ EXPECT_EQ("unknown-unknown-unknown", Triple::normalize("--"));
+ EXPECT_EQ("unknown-unknown-unknown-unknown", Triple::normalize("---"));
+ EXPECT_EQ("unknown-unknown-unknown-unknown-unknown",
+ Triple::normalize("----"));
+
+ EXPECT_EQ("a", Triple::normalize("a"));
+ EXPECT_EQ("a-b", Triple::normalize("a-b"));
+ EXPECT_EQ("a-b-c", Triple::normalize("a-b-c"));
+ EXPECT_EQ("a-b-c-d", Triple::normalize("a-b-c-d"));
+
+ EXPECT_EQ("i386-b-c", Triple::normalize("i386-b-c"));
+ EXPECT_EQ("i386-a-c", Triple::normalize("a-i386-c"));
+ EXPECT_EQ("i386-a-b", Triple::normalize("a-b-i386"));
+ EXPECT_EQ("i386-a-b-c", Triple::normalize("a-b-c-i386"));
+
+ EXPECT_EQ("a-pc-c", Triple::normalize("a-pc-c"));
+ EXPECT_EQ("unknown-pc-b-c", Triple::normalize("pc-b-c"));
+ EXPECT_EQ("a-pc-b", Triple::normalize("a-b-pc"));
+ EXPECT_EQ("a-pc-b-c", Triple::normalize("a-b-c-pc"));
+
+ EXPECT_EQ("a-b-linux", Triple::normalize("a-b-linux"));
+ EXPECT_EQ("unknown-unknown-linux-b-c", Triple::normalize("linux-b-c"));
+ EXPECT_EQ("a-unknown-linux-c", Triple::normalize("a-linux-c"));
+
+ EXPECT_EQ("i386-pc-a", Triple::normalize("a-pc-i386"));
+ EXPECT_EQ("i386-pc-unknown", Triple::normalize("-pc-i386"));
+ EXPECT_EQ("unknown-pc-linux-c", Triple::normalize("linux-pc-c"));
+ EXPECT_EQ("unknown-pc-linux", Triple::normalize("linux-pc-"));
+
+ EXPECT_EQ("i386", Triple::normalize("i386"));
+ EXPECT_EQ("unknown-pc", Triple::normalize("pc"));
+ EXPECT_EQ("unknown-unknown-linux", Triple::normalize("linux"));
+
+ EXPECT_EQ("x86_64-unknown-linux-gnu", Triple::normalize("x86_64-gnu-linux"));
+
+ // Check that normalizing a permutated set of valid components returns a
+ // triple with the unpermuted components.
+ //
+ // We don't check every possible combination. For the set of architectures A,
+ // vendors V, operating systems O, and environments E, that would require |A|
+ // * |V| * |O| * |E| * 4! tests. Instead we check every option for any given
+ // slot and make sure it gets normalized to the correct position from every
+ // permutation. This should cover the core logic while being a tractable
+ // number of tests at (|A| + |V| + |O| + |E|) * 4!.
+ auto FirstArchType = Triple::ArchType(Triple::UnknownArch + 1);
+ auto FirstVendorType = Triple::VendorType(Triple::UnknownVendor + 1);
+ auto FirstOSType = Triple::OSType(Triple::UnknownOS + 1);
+ auto FirstEnvType = Triple::EnvironmentType(Triple::UnknownEnvironment + 1);
+ StringRef InitialC[] = {Triple::getArchTypeName(FirstArchType),
+ Triple::getVendorTypeName(FirstVendorType),
+ Triple::getOSTypeName(FirstOSType),
+ Triple::getEnvironmentTypeName(FirstEnvType)};
+ for (int Arch = FirstArchType; Arch <= Triple::LastArchType; ++Arch) {
+ StringRef C[] = {InitialC[0], InitialC[1], InitialC[2], InitialC[3]};
+ C[0] = Triple::getArchTypeName(Triple::ArchType(Arch));
+ std::string E = Join(C[0], C[1], C[2]);
+ int I[] = {0, 1, 2};
+ do {
+ EXPECT_EQ(E, Triple::normalize(Join(C[I[0]], C[I[1]], C[I[2]])));
+ } while (std::next_permutation(std::begin(I), std::end(I)));
+ std::string F = Join(C[0], C[1], C[2], C[3]);
+ int J[] = {0, 1, 2, 3};
+ do {
+ EXPECT_EQ(F, Triple::normalize(Join(C[J[0]], C[J[1]], C[J[2]], C[J[3]])));
+ } while (std::next_permutation(std::begin(J), std::end(J)));
+ }
+ for (int Vendor = FirstVendorType; Vendor <= Triple::LastVendorType;
+ ++Vendor) {
+ StringRef C[] = {InitialC[0], InitialC[1], InitialC[2], InitialC[3]};
+ C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor));
+ std::string E = Join(C[0], C[1], C[2]);
+ int I[] = {0, 1, 2};
+ do {
+ EXPECT_EQ(E, Triple::normalize(Join(C[I[0]], C[I[1]], C[I[2]])));
+ } while (std::next_permutation(std::begin(I), std::end(I)));
+ std::string F = Join(C[0], C[1], C[2], C[3]);
+ int J[] = {0, 1, 2, 3};
+ do {
+ EXPECT_EQ(F, Triple::normalize(Join(C[J[0]], C[J[1]], C[J[2]], C[J[3]])));
+ } while (std::next_permutation(std::begin(J), std::end(J)));
+ }
+ for (int OS = FirstOSType; OS <= Triple::LastOSType; ++OS) {
+ if (OS == Triple::Win32)
+ continue;
+ StringRef C[] = {InitialC[0], InitialC[1], InitialC[2], InitialC[3]};
+ C[2] = Triple::getOSTypeName(Triple::OSType(OS));
+ std::string E = Join(C[0], C[1], C[2]);
+ int I[] = {0, 1, 2};
+ do {
+ EXPECT_EQ(E, Triple::normalize(Join(C[I[0]], C[I[1]], C[I[2]])));
+ } while (std::next_permutation(std::begin(I), std::end(I)));
+ std::string F = Join(C[0], C[1], C[2], C[3]);
+ int J[] = {0, 1, 2, 3};
+ do {
+ EXPECT_EQ(F, Triple::normalize(Join(C[J[0]], C[J[1]], C[J[2]], C[J[3]])));
+ } while (std::next_permutation(std::begin(J), std::end(J)));
+ }
+ for (int Env = FirstEnvType; Env <= Triple::LastEnvironmentType; ++Env) {
+ StringRef C[] = {InitialC[0], InitialC[1], InitialC[2], InitialC[3]};
+ C[3] = Triple::getEnvironmentTypeName(Triple::EnvironmentType(Env));
+ std::string F = Join(C[0], C[1], C[2], C[3]);
+ int J[] = {0, 1, 2, 3};
+ do {
+ EXPECT_EQ(F, Triple::normalize(Join(C[J[0]], C[J[1]], C[J[2]], C[J[3]])));
+ } while (std::next_permutation(std::begin(J), std::end(J)));
+ }
+
+ // Various real-world funky triples. The value returned by GCC's config.sub
+ // is given in the comment.
+ EXPECT_EQ("i386-unknown-windows-gnu",
+ Triple::normalize("i386-mingw32")); // i386-pc-mingw32
+ EXPECT_EQ("x86_64-unknown-linux-gnu",
+ Triple::normalize("x86_64-linux-gnu")); // x86_64-pc-linux-gnu
+ EXPECT_EQ("i486-unknown-linux-gnu",
+ Triple::normalize("i486-linux-gnu")); // i486-pc-linux-gnu
+ EXPECT_EQ("i386-redhat-linux",
+ Triple::normalize("i386-redhat-linux")); // i386-redhat-linux-gnu
+ EXPECT_EQ("i686-unknown-linux",
+ Triple::normalize("i686-linux")); // i686-pc-linux-gnu
+ EXPECT_EQ("arm-none-unknown-eabi",
+ Triple::normalize("arm-none-eabi")); // arm-none-eabi
+}
+
+TEST(TripleTest, MutateName) {
+ Triple T;
+ EXPECT_EQ(Triple::UnknownArch, T.getArch());
+ EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
+ EXPECT_EQ(Triple::UnknownOS, T.getOS());
+ EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment());
+
+ T.setArchName("i386");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ("i386--", T.getTriple());
+
+ T.setVendorName("pc");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ("i386-pc-", T.getTriple());
+
+ T.setOSName("linux");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ("i386-pc-linux", T.getTriple());
+
+ T.setEnvironmentName("gnu");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Linux, T.getOS());
+ EXPECT_EQ("i386-pc-linux-gnu", T.getTriple());
+
+ T.setOSName("freebsd");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::FreeBSD, T.getOS());
+ EXPECT_EQ("i386-pc-freebsd-gnu", T.getTriple());
+
+ T.setOSAndEnvironmentName("darwin");
+ EXPECT_EQ(Triple::x86, T.getArch());
+ EXPECT_EQ(Triple::PC, T.getVendor());
+ EXPECT_EQ(Triple::Darwin, T.getOS());
+ EXPECT_EQ("i386-pc-darwin", T.getTriple());
+}
+
+TEST(TripleTest, BitWidthPredicates) {
+ Triple T;
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::arm);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::hexagon);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::mips);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::mips64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::msp430);
+ EXPECT_TRUE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::ppc);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::ppc64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::x86);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::x86_64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::amdil);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::amdil64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::hsail);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::hsail64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::spir);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::spir64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::sparc);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::sparcel);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::sparcv9);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::wasm32);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::wasm64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+
+ T.setArch(Triple::avr);
+ EXPECT_TRUE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::lanai);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::riscv32);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+
+ T.setArch(Triple::riscv64);
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+}
+
+TEST(TripleTest, BitWidthArchVariants) {
+ Triple T;
+ EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::UnknownArch);
+ EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::mips);
+ EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::mipsel);
+ EXPECT_EQ(Triple::mipsel, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64el, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::ppc);
+ EXPECT_EQ(Triple::ppc, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::ppc64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::nvptx);
+ EXPECT_EQ(Triple::nvptx, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::nvptx64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::sparc);
+ EXPECT_EQ(Triple::sparc, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::sparcv9, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::x86);
+ EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::mips64);
+ EXPECT_EQ(Triple::mips, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::mips64el);
+ EXPECT_EQ(Triple::mipsel, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64el, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::ppc64);
+ EXPECT_EQ(Triple::ppc, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::ppc64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::nvptx64);
+ EXPECT_EQ(Triple::nvptx, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::nvptx64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::sparcv9);
+ EXPECT_EQ(Triple::sparc, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::sparcv9, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::x86_64);
+ EXPECT_EQ(Triple::x86, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::x86_64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::amdil);
+ EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::amdil64);
+ EXPECT_EQ(Triple::amdil, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::amdil64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::hsail);
+ EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::hsail64);
+ EXPECT_EQ(Triple::hsail, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::hsail64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::spir);
+ EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::spir64);
+ EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::wasm32);
+ EXPECT_EQ(Triple::wasm32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::wasm64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::wasm64);
+ EXPECT_EQ(Triple::wasm32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::wasm64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::riscv32);
+ EXPECT_EQ(Triple::riscv32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::riscv64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::riscv64);
+ EXPECT_EQ(Triple::riscv32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::riscv64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::thumbeb);
+ EXPECT_EQ(Triple::thumbeb, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64_be, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::thumb);
+ EXPECT_EQ(Triple::thumb, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::aarch64);
+ EXPECT_EQ(Triple::arm, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::aarch64_be);
+ EXPECT_EQ(Triple::armeb, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64_be, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::renderscript32);
+ EXPECT_EQ(Triple::renderscript32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::renderscript64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::renderscript64);
+ EXPECT_EQ(Triple::renderscript32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::renderscript64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::le32);
+ EXPECT_EQ(Triple::le32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::le64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::le64);
+ EXPECT_EQ(Triple::le32, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::le64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::armeb);
+ EXPECT_EQ(Triple::armeb, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64_be, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::arm);
+ EXPECT_EQ(Triple::arm, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::systemz);
+ EXPECT_EQ(Triple::UnknownArch, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::systemz, T.get64BitArchVariant().getArch());
+
+ T.setArch(Triple::xcore);
+ EXPECT_EQ(Triple::xcore, T.get32BitArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.get64BitArchVariant().getArch());
+}
+
+TEST(TripleTest, EndianArchVariants) {
+ Triple T;
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::UnknownArch);
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::aarch64_be);
+ EXPECT_EQ(Triple::aarch64_be, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::aarch64);
+ EXPECT_EQ(Triple::aarch64_be, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::aarch64, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::armeb);
+ EXPECT_EQ(Triple::armeb, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::arm);
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::arm, T.getLittleEndianArchVariant().getArch());
+ T = Triple("arm");
+ EXPECT_TRUE(T.isLittleEndian());
+ T = Triple("thumb");
+ EXPECT_TRUE(T.isLittleEndian());
+ T = Triple("armeb");
+ EXPECT_FALSE(T.isLittleEndian());
+ T = Triple("thumbeb");
+ EXPECT_FALSE(T.isLittleEndian());
+
+ T.setArch(Triple::bpfeb);
+ EXPECT_EQ(Triple::bpfeb, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::bpfel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::bpfel);
+ EXPECT_EQ(Triple::bpfeb, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::bpfel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::mips64);
+ EXPECT_EQ(Triple::mips64, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64el, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::mips64el);
+ EXPECT_EQ(Triple::mips64, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::mips64el, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::mips);
+ EXPECT_EQ(Triple::mips, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::mipsel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::mipsel);
+ EXPECT_EQ(Triple::mips, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::mipsel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::ppc);
+ EXPECT_EQ(Triple::ppc, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::ppc64);
+ EXPECT_EQ(Triple::ppc64, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::ppc64le, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::ppc64le);
+ EXPECT_EQ(Triple::ppc64, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::ppc64le, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::sparc);
+ EXPECT_EQ(Triple::sparc, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::sparcel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::sparcel);
+ EXPECT_EQ(Triple::sparc, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::sparcel, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::thumb);
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::thumb, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::thumbeb);
+ EXPECT_EQ(Triple::thumbeb, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::lanai);
+ EXPECT_EQ(Triple::lanai, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::UnknownArch, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::tcele);
+ EXPECT_EQ(Triple::tce, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::tcele, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::tce);
+ EXPECT_EQ(Triple::tce, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::tcele, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::le32);
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::le32, T.getLittleEndianArchVariant().getArch());
+
+ T.setArch(Triple::le64);
+ EXPECT_EQ(Triple::UnknownArch, T.getBigEndianArchVariant().getArch());
+ EXPECT_EQ(Triple::le64, T.getLittleEndianArchVariant().getArch());
+}
+
+TEST(TripleTest, getOSVersion) {
+ Triple T;
+ unsigned Major, Minor, Micro;
+
+ T = Triple("i386-apple-darwin9");
+ EXPECT_TRUE(T.isMacOSX());
+ EXPECT_FALSE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)5, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)5, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+
+ T = Triple("x86_64-apple-darwin9");
+ EXPECT_TRUE(T.isMacOSX());
+ EXPECT_FALSE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)5, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)5, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+
+ T = Triple("x86_64-apple-macosx");
+ EXPECT_TRUE(T.isMacOSX());
+ EXPECT_FALSE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)4, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)5, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+
+ T = Triple("x86_64-apple-macosx10.7");
+ EXPECT_TRUE(T.isMacOSX());
+ EXPECT_FALSE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_FALSE(T.isArch32Bit());
+ EXPECT_TRUE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)7, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)5, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+
+ T = Triple("armv7-apple-ios");
+ EXPECT_FALSE(T.isMacOSX());
+ EXPECT_TRUE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)4, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)5, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+
+ T = Triple("armv7-apple-ios7.0");
+ EXPECT_FALSE(T.isMacOSX());
+ EXPECT_TRUE(T.isiOS());
+ EXPECT_FALSE(T.isArch16Bit());
+ EXPECT_TRUE(T.isArch32Bit());
+ EXPECT_FALSE(T.isArch64Bit());
+ T.getMacOSXVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)4, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)7, Major);
+ EXPECT_EQ((unsigned)0, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ EXPECT_FALSE(T.isSimulatorEnvironment());
+
+ T = Triple("x86_64-apple-ios10.3-simulator");
+ EXPECT_TRUE(T.isiOS());
+ T.getiOSVersion(Major, Minor, Micro);
+ EXPECT_EQ((unsigned)10, Major);
+ EXPECT_EQ((unsigned)3, Minor);
+ EXPECT_EQ((unsigned)0, Micro);
+ EXPECT_TRUE(T.isSimulatorEnvironment());
+}
+
+TEST(TripleTest, FileFormat) {
+ EXPECT_EQ(Triple::ELF, Triple("i686-unknown-linux-gnu").getObjectFormat());
+ EXPECT_EQ(Triple::ELF, Triple("i686-unknown-freebsd").getObjectFormat());
+ EXPECT_EQ(Triple::ELF, Triple("i686-unknown-netbsd").getObjectFormat());
+ EXPECT_EQ(Triple::ELF, Triple("i686--win32-elf").getObjectFormat());
+ EXPECT_EQ(Triple::ELF, Triple("i686---elf").getObjectFormat());
+
+ EXPECT_EQ(Triple::MachO, Triple("i686-apple-macosx").getObjectFormat());
+ EXPECT_EQ(Triple::MachO, Triple("i686-apple-ios").getObjectFormat());
+ EXPECT_EQ(Triple::MachO, Triple("i686---macho").getObjectFormat());
+
+ EXPECT_EQ(Triple::COFF, Triple("i686--win32").getObjectFormat());
+
+ EXPECT_EQ(Triple::ELF, Triple("i686-pc-windows-msvc-elf").getObjectFormat());
+ EXPECT_EQ(Triple::ELF, Triple("i686-pc-cygwin-elf").getObjectFormat());
+
+ EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-unknown").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-unknown").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm, Triple("wasm32-unknown-wasi-musl").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm, Triple("wasm64-unknown-wasi-musl").getObjectFormat());
+
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm32-unknown-unknown-wasm").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm64-unknown-unknown-wasm").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm32-unknown-wasi-musl-wasm").getObjectFormat());
+ EXPECT_EQ(Triple::Wasm,
+ Triple("wasm64-unknown-wasi-musl-wasm").getObjectFormat());
+
+ Triple MSVCNormalized(Triple::normalize("i686-pc-windows-msvc-elf"));
+ EXPECT_EQ(Triple::ELF, MSVCNormalized.getObjectFormat());
+
+ Triple GNUWindowsNormalized(Triple::normalize("i686-pc-windows-gnu-elf"));
+ EXPECT_EQ(Triple::ELF, GNUWindowsNormalized.getObjectFormat());
+
+ Triple CygnusNormalised(Triple::normalize("i686-pc-windows-cygnus-elf"));
+ EXPECT_EQ(Triple::ELF, CygnusNormalised.getObjectFormat());
+
+ Triple CygwinNormalized(Triple::normalize("i686-pc-cygwin-elf"));
+ EXPECT_EQ(Triple::ELF, CygwinNormalized.getObjectFormat());
+
+ Triple T = Triple("");
+ T.setObjectFormat(Triple::ELF);
+ EXPECT_EQ(Triple::ELF, T.getObjectFormat());
+
+ T.setObjectFormat(Triple::MachO);
+ EXPECT_EQ(Triple::MachO, T.getObjectFormat());
+}
+
+TEST(TripleTest, NormalizeWindows) {
+ EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-win32"));
+ EXPECT_EQ("i686-unknown-windows-msvc", Triple::normalize("i686-win32"));
+ EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32"));
+ EXPECT_EQ("i686-unknown-windows-gnu", Triple::normalize("i686-mingw32"));
+ EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32-w64"));
+ EXPECT_EQ("i686-unknown-windows-gnu", Triple::normalize("i686-mingw32-w64"));
+ EXPECT_EQ("i686-pc-windows-cygnus", Triple::normalize("i686-pc-cygwin"));
+ EXPECT_EQ("i686-unknown-windows-cygnus", Triple::normalize("i686-cygwin"));
+
+ EXPECT_EQ("x86_64-pc-windows-msvc", Triple::normalize("x86_64-pc-win32"));
+ EXPECT_EQ("x86_64-unknown-windows-msvc", Triple::normalize("x86_64-win32"));
+ EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32"));
+ EXPECT_EQ("x86_64-unknown-windows-gnu", Triple::normalize("x86_64-mingw32"));
+ EXPECT_EQ("x86_64-pc-windows-gnu",
+ Triple::normalize("x86_64-pc-mingw32-w64"));
+ EXPECT_EQ("x86_64-unknown-windows-gnu",
+ Triple::normalize("x86_64-mingw32-w64"));
+
+ EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-win32-elf"));
+ EXPECT_EQ("i686-unknown-windows-elf", Triple::normalize("i686-win32-elf"));
+ EXPECT_EQ("i686-pc-windows-macho", Triple::normalize("i686-pc-win32-macho"));
+ EXPECT_EQ("i686-unknown-windows-macho",
+ Triple::normalize("i686-win32-macho"));
+
+ EXPECT_EQ("x86_64-pc-windows-elf", Triple::normalize("x86_64-pc-win32-elf"));
+ EXPECT_EQ("x86_64-unknown-windows-elf",
+ Triple::normalize("x86_64-win32-elf"));
+ EXPECT_EQ("x86_64-pc-windows-macho",
+ Triple::normalize("x86_64-pc-win32-macho"));
+ EXPECT_EQ("x86_64-unknown-windows-macho",
+ Triple::normalize("x86_64-win32-macho"));
+
+ EXPECT_EQ("i686-pc-windows-cygnus",
+ Triple::normalize("i686-pc-windows-cygnus"));
+ EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-windows-gnu"));
+ EXPECT_EQ("i686-pc-windows-itanium",
+ Triple::normalize("i686-pc-windows-itanium"));
+ EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-windows-msvc"));
+
+ EXPECT_EQ("i686-pc-windows-elf",
+ Triple::normalize("i686-pc-windows-elf-elf"));
+}
+
+TEST(TripleTest, getARMCPUForArch) {
+ // Platform specific defaults.
+ {
+ llvm::Triple Triple("arm--nacl");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("arm--openbsd");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6-unknown-freebsd");
+ EXPECT_EQ("arm1176jzf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("thumbv6-unknown-freebsd");
+ EXPECT_EQ("arm1176jzf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armebv6-unknown-freebsd");
+ EXPECT_EQ("arm1176jzf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("arm--win32");
+ EXPECT_EQ("cortex-a9", Triple.getARMCPUForArch());
+ }
+ // Some alternative architectures
+ {
+ llvm::Triple Triple("armv7k-apple-ios9");
+ EXPECT_EQ("cortex-a7", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7k-apple-watchos3");
+ EXPECT_EQ("cortex-a7", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7k-apple-tvos9");
+ EXPECT_EQ("cortex-a7", Triple.getARMCPUForArch());
+ }
+ // armeb is permitted, but armebeb is not
+ {
+ llvm::Triple Triple("armeb-none-eabi");
+ EXPECT_EQ("arm7tdmi", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armebeb-none-eabi");
+ EXPECT_EQ("", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armebv6eb-none-eabi");
+ EXPECT_EQ("", Triple.getARMCPUForArch());
+ }
+ // xscaleeb is permitted, but armebxscale is not
+ {
+ llvm::Triple Triple("xscaleeb-none-eabi");
+ EXPECT_EQ("xscale", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armebxscale-none-eabi");
+ EXPECT_EQ("", Triple.getARMCPUForArch());
+ }
+}
+
+TEST(TripleTest, NormalizeARM) {
+ EXPECT_EQ("armv6-unknown-netbsd-eabi",
+ Triple::normalize("armv6-netbsd-eabi"));
+ EXPECT_EQ("armv7-unknown-netbsd-eabi",
+ Triple::normalize("armv7-netbsd-eabi"));
+ EXPECT_EQ("armv6eb-unknown-netbsd-eabi",
+ Triple::normalize("armv6eb-netbsd-eabi"));
+ EXPECT_EQ("armv7eb-unknown-netbsd-eabi",
+ Triple::normalize("armv7eb-netbsd-eabi"));
+ EXPECT_EQ("armv6-unknown-netbsd-eabihf",
+ Triple::normalize("armv6-netbsd-eabihf"));
+ EXPECT_EQ("armv7-unknown-netbsd-eabihf",
+ Triple::normalize("armv7-netbsd-eabihf"));
+ EXPECT_EQ("armv6eb-unknown-netbsd-eabihf",
+ Triple::normalize("armv6eb-netbsd-eabihf"));
+ EXPECT_EQ("armv7eb-unknown-netbsd-eabihf",
+ Triple::normalize("armv7eb-netbsd-eabihf"));
+
+ EXPECT_EQ("armv7-suse-linux-gnueabihf",
+ Triple::normalize("armv7-suse-linux-gnueabi"));
+
+ Triple T;
+ T = Triple("armv6--netbsd-eabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ T = Triple("armv6eb--netbsd-eabi");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ T = Triple("armv7-suse-linux-gnueabihf");
+ EXPECT_EQ(Triple::GNUEABIHF, T.getEnvironment());
+}
+
+TEST(TripleTest, ParseARMArch) {
+ // ARM
+ {
+ Triple T = Triple("arm");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ }
+ {
+ Triple T = Triple("armeb");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ }
+ // THUMB
+ {
+ Triple T = Triple("thumb");
+ EXPECT_EQ(Triple::thumb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbeb");
+ EXPECT_EQ(Triple::thumbeb, T.getArch());
+ }
+ // AARCH64
+ {
+ Triple T = Triple("arm64");
+ EXPECT_EQ(Triple::aarch64, T.getArch());
+ }
+ {
+ Triple T = Triple("aarch64");
+ EXPECT_EQ(Triple::aarch64, T.getArch());
+ }
+ {
+ Triple T = Triple("aarch64_be");
+ EXPECT_EQ(Triple::aarch64_be, T.getArch());
+ }
+}
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/TwineTest.cpp b/src/llvm-project/llvm/unittests/ADT/TwineTest.cpp
new file mode 100644
index 0000000..950eda2
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/TwineTest.cpp
@@ -0,0 +1,123 @@
+//===- TwineTest.cpp - Twine unit tests -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FormatAdapters.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+std::string repr(const Twine &Value) {
+ std::string res;
+ llvm::raw_string_ostream OS(res);
+ Value.printRepr(OS);
+ return OS.str();
+}
+
+TEST(TwineTest, Construction) {
+ EXPECT_EQ("", Twine().str());
+ EXPECT_EQ("hi", Twine("hi").str());
+ EXPECT_EQ("hi", Twine(std::string("hi")).str());
+ EXPECT_EQ("hi", Twine(StringRef("hi")).str());
+ EXPECT_EQ("hi", Twine(StringRef(std::string("hi"))).str());
+ EXPECT_EQ("hi", Twine(StringRef("hithere", 2)).str());
+ EXPECT_EQ("hi", Twine(SmallString<4>("hi")).str());
+ EXPECT_EQ("hi", Twine(formatv("{0}", "hi")).str());
+}
+
+TEST(TwineTest, Numbers) {
+ EXPECT_EQ("123", Twine(123U).str());
+ EXPECT_EQ("123", Twine(123).str());
+ EXPECT_EQ("-123", Twine(-123).str());
+ EXPECT_EQ("123", Twine(123).str());
+ EXPECT_EQ("-123", Twine(-123).str());
+
+ EXPECT_EQ("7b", Twine::utohexstr(123).str());
+}
+
+TEST(TwineTest, Characters) {
+ EXPECT_EQ("x", Twine('x').str());
+ EXPECT_EQ("x", Twine(static_cast<unsigned char>('x')).str());
+ EXPECT_EQ("x", Twine(static_cast<signed char>('x')).str());
+}
+
+TEST(TwineTest, Concat) {
+ // Check verse repr, since we care about the actual representation not just
+ // the result.
+
+ // Concat with null.
+ EXPECT_EQ("(Twine null empty)",
+ repr(Twine("hi").concat(Twine::createNull())));
+ EXPECT_EQ("(Twine null empty)",
+ repr(Twine::createNull().concat(Twine("hi"))));
+
+ // Concat with empty.
+ EXPECT_EQ("(Twine cstring:\"hi\" empty)",
+ repr(Twine("hi").concat(Twine())));
+ EXPECT_EQ("(Twine cstring:\"hi\" empty)",
+ repr(Twine().concat(Twine("hi"))));
+ EXPECT_EQ("(Twine smallstring:\"hi\" empty)",
+ repr(Twine().concat(Twine(SmallString<5>("hi")))));
+ EXPECT_EQ("(Twine formatv:\"howdy\" empty)",
+ repr(Twine(formatv("howdy")).concat(Twine())));
+ EXPECT_EQ("(Twine formatv:\"howdy\" empty)",
+ repr(Twine().concat(Twine(formatv("howdy")))));
+ EXPECT_EQ("(Twine smallstring:\"hey\" cstring:\"there\")",
+ repr(Twine(SmallString<7>("hey")).concat(Twine("there"))));
+
+ // Concatenation of unary ropes.
+ EXPECT_EQ("(Twine cstring:\"a\" cstring:\"b\")",
+ repr(Twine("a").concat(Twine("b"))));
+
+ // Concatenation of other ropes.
+ EXPECT_EQ("(Twine rope:(Twine cstring:\"a\" cstring:\"b\") cstring:\"c\")",
+ repr(Twine("a").concat(Twine("b")).concat(Twine("c"))));
+ EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine cstring:\"b\" cstring:\"c\"))",
+ repr(Twine("a").concat(Twine("b").concat(Twine("c")))));
+ EXPECT_EQ("(Twine cstring:\"a\" rope:(Twine smallstring:\"b\" cstring:\"c\"))",
+ repr(Twine("a").concat(Twine(SmallString<3>("b")).concat(Twine("c")))));
+}
+
+TEST(TwineTest, toNullTerminatedStringRef) {
+ SmallString<8> storage;
+ EXPECT_EQ(0, *Twine("hello").toNullTerminatedStringRef(storage).end());
+ EXPECT_EQ(0,
+ *Twine(StringRef("hello")).toNullTerminatedStringRef(storage).end());
+ EXPECT_EQ(0, *Twine(SmallString<11>("hello"))
+ .toNullTerminatedStringRef(storage)
+ .end());
+ EXPECT_EQ(0, *Twine(formatv("{0}{1}", "how", "dy"))
+ .toNullTerminatedStringRef(storage)
+ .end());
+}
+
+TEST(TwineTest, LazyEvaluation) {
+ struct formatter : FormatAdapter<int> {
+ explicit formatter(int &Count) : FormatAdapter(0), Count(Count) {}
+ int &Count;
+
+ void format(raw_ostream &OS, StringRef Style) { ++Count; }
+ };
+
+ int Count = 0;
+ formatter Formatter(Count);
+ (void)Twine(formatv("{0}", Formatter));
+ EXPECT_EQ(0, Count);
+ (void)Twine(formatv("{0}", Formatter)).str();
+ EXPECT_EQ(1, Count);
+}
+
+ // I suppose linking in the entire code generator to add a unit test to check
+ // the code size of the concat operation is overkill... :)
+
+} // end anonymous namespace
diff --git a/src/llvm-project/llvm/unittests/ADT/VariadicFunctionTest.cpp b/src/llvm-project/llvm/unittests/ADT/VariadicFunctionTest.cpp
new file mode 100644
index 0000000..43db648
--- /dev/null
+++ b/src/llvm-project/llvm/unittests/ADT/VariadicFunctionTest.cpp
@@ -0,0 +1,110 @@
+//===----------- VariadicFunctionTest.cpp - VariadicFunction unit tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/VariadicFunction.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+namespace {
+
+// Defines a variadic function StringCat() to join strings.
+// StringCat()'s arguments and return value have class types.
+std::string StringCatImpl(ArrayRef<const std::string *> Args) {
+ std::string S;
+ for (unsigned i = 0, e = Args.size(); i < e; ++i)
+ S += *Args[i];
+ return S;
+}
+const VariadicFunction<std::string, std::string, StringCatImpl> StringCat = {};
+
+TEST(VariadicFunctionTest, WorksForClassTypes) {
+ EXPECT_EQ("", StringCat());
+ EXPECT_EQ("a", StringCat("a"));
+ EXPECT_EQ("abc", StringCat("a", "bc"));
+ EXPECT_EQ("0123456789abcdefghijklmnopqrstuv",
+ StringCat("0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
+ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j",
+ "k", "l", "m", "n", "o", "p", "q", "r", "s", "t",
+ "u", "v"));
+}
+
+// Defines a variadic function Sum(), whose arguments and return value
+// have primitive types.
+// The return type of SumImp() is deliberately different from its
+// argument type, as we want to test that this works.
+long SumImpl(ArrayRef<const int *> Args) {
+ long Result = 0;
+ for (unsigned i = 0, e = Args.size(); i < e; ++i)
+ Result += *Args[i];
+ return Result;
+}
+const VariadicFunction<long, int, SumImpl> Sum = {};
+
+TEST(VariadicFunctionTest, WorksForPrimitiveTypes) {
+ EXPECT_EQ(0, Sum());
+ EXPECT_EQ(1, Sum(1));
+ EXPECT_EQ(12, Sum(10, 2));
+ EXPECT_EQ(1234567, Sum(1000000, 200000, 30000, 4000, 500, 60, 7));
+}
+
+// Appends an array of strings to dest and returns the number of
+// characters appended.
+int StringAppendImpl(std::string *Dest, ArrayRef<const std::string *> Args) {
+ int Chars = 0;
+ for (unsigned i = 0, e = Args.size(); i < e; ++i) {
+ Chars += Args[i]->size();
+ *Dest += *Args[i];
+ }
+ return Chars;
+}
+const VariadicFunction1<int, std::string *, std::string,
+ StringAppendImpl> StringAppend = {};
+
+TEST(VariadicFunction1Test, Works) {
+ std::string S0("hi");
+ EXPECT_EQ(0, StringAppend(&S0));
+ EXPECT_EQ("hi", S0);
+
+ std::string S1("bin");
+ EXPECT_EQ(2, StringAppend(&S1, "go"));
+ EXPECT_EQ("bingo", S1);
+
+ std::string S4("Fab4");
+ EXPECT_EQ(4 + 4 + 6 + 5,
+ StringAppend(&S4, "John", "Paul", "George", "Ringo"));
+ EXPECT_EQ("Fab4JohnPaulGeorgeRingo", S4);
+}
+
+// Counts how many optional arguments fall in the given range.
+// Returns the result in *num_in_range. We make the return type void
+// as we want to test that VariadicFunction* can handle it.
+void CountInRangeImpl(int *NumInRange, int Low, int High,
+ ArrayRef<const int *> Args) {
+ *NumInRange = 0;
+ for (unsigned i = 0, e = Args.size(); i < e; ++i)
+ if (Low <= *Args[i] && *Args[i] <= High)
+ ++(*NumInRange);
+}
+const VariadicFunction3<void, int *, int, int, int,
+ CountInRangeImpl> CountInRange = {};
+
+TEST(VariadicFunction3Test, Works) {
+ int N = -1;
+ CountInRange(&N, -100, 100);
+ EXPECT_EQ(0, N);
+
+ CountInRange(&N, -100, 100, 42);
+ EXPECT_EQ(1, N);
+
+ CountInRange(&N, -100, 100, 1, 999, -200, 42);
+ EXPECT_EQ(2, N);
+}
+
+} // namespace