summaryrefslogtreecommitdiff
path: root/gnu/llvm/unittests
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/unittests')
-rw-r--r--gnu/llvm/unittests/ADT/APFloatTest.cpp2894
-rw-r--r--gnu/llvm/unittests/ADT/APIntTest.cpp1025
-rw-r--r--gnu/llvm/unittests/ADT/APSIntTest.cpp163
-rw-r--r--gnu/llvm/unittests/ADT/ArrayRefTest.cpp143
-rw-r--r--gnu/llvm/unittests/ADT/BitVectorTest.cpp403
-rw-r--r--gnu/llvm/unittests/ADT/CMakeLists.txt53
-rw-r--r--gnu/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp105
-rw-r--r--gnu/llvm/unittests/ADT/DeltaAlgorithmTest.cpp100
-rw-r--r--gnu/llvm/unittests/ADT/DenseMapTest.cpp441
-rw-r--r--gnu/llvm/unittests/ADT/DenseSetTest.cpp68
-rw-r--r--gnu/llvm/unittests/ADT/FoldingSet.cpp39
-rw-r--r--gnu/llvm/unittests/ADT/FunctionRefTest.cpp28
-rw-r--r--gnu/llvm/unittests/ADT/HashingTest.cpp448
-rw-r--r--gnu/llvm/unittests/ADT/ImmutableMapTest.cpp50
-rw-r--r--gnu/llvm/unittests/ADT/ImmutableSetTest.cpp201
-rw-r--r--gnu/llvm/unittests/ADT/IntEqClassesTest.cpp107
-rw-r--r--gnu/llvm/unittests/ADT/IntervalMapTest.cpp716
-rw-r--r--gnu/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp66
-rw-r--r--gnu/llvm/unittests/ADT/MakeUniqueTest.cpp76
-rw-r--r--gnu/llvm/unittests/ADT/Makefile23
-rw-r--r--gnu/llvm/unittests/ADT/MapVectorTest.cpp367
-rw-r--r--gnu/llvm/unittests/ADT/OptionalTest.cpp394
-rw-r--r--gnu/llvm/unittests/ADT/PackedVectorTest.cpp103
-rw-r--r--gnu/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp46
-rw-r--r--gnu/llvm/unittests/ADT/PointerIntPairTest.cpp102
-rw-r--r--gnu/llvm/unittests/ADT/PointerSumTypeTest.cpp113
-rw-r--r--gnu/llvm/unittests/ADT/PointerUnionTest.cpp72
-rw-r--r--gnu/llvm/unittests/ADT/PostOrderIteratorTest.cpp37
-rw-r--r--gnu/llvm/unittests/ADT/RangeAdapterTest.cpp83
-rw-r--r--gnu/llvm/unittests/ADT/SCCIteratorTest.cpp344
-rw-r--r--gnu/llvm/unittests/ADT/SmallPtrSetTest.cpp212
-rw-r--r--gnu/llvm/unittests/ADT/SmallStringTest.cpp207
-rw-r--r--gnu/llvm/unittests/ADT/SmallVectorTest.cpp925
-rw-r--r--gnu/llvm/unittests/ADT/SparseBitVectorTest.cpp130
-rw-r--r--gnu/llvm/unittests/ADT/SparseMultiSetTest.cpp235
-rw-r--r--gnu/llvm/unittests/ADT/SparseSetTest.cpp186
-rw-r--r--gnu/llvm/unittests/ADT/StringMapTest.cpp359
-rw-r--r--gnu/llvm/unittests/ADT/StringRefTest.cpp603
-rw-r--r--gnu/llvm/unittests/ADT/TinyPtrVectorTest.cpp461
-rw-r--r--gnu/llvm/unittests/ADT/TripleTest.cpp1111
-rw-r--r--gnu/llvm/unittests/ADT/TwineTest.cpp97
-rw-r--r--gnu/llvm/unittests/ADT/VariadicFunctionTest.cpp110
-rw-r--r--gnu/llvm/unittests/ADT/ilistTest.cpp99
-rw-r--r--gnu/llvm/unittests/Analysis/AliasAnalysisTest.cpp256
-rw-r--r--gnu/llvm/unittests/Analysis/CFGTest.cpp387
-rw-r--r--gnu/llvm/unittests/Analysis/CMakeLists.txt16
-rw-r--r--gnu/llvm/unittests/Analysis/CallGraphTest.cpp59
-rw-r--r--gnu/llvm/unittests/Analysis/LazyCallGraphTest.cpp720
-rw-r--r--gnu/llvm/unittests/Analysis/Makefile15
-rw-r--r--gnu/llvm/unittests/Analysis/MixedTBAATest.cpp78
-rw-r--r--gnu/llvm/unittests/Analysis/ScalarEvolutionTest.cpp241
-rw-r--r--gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp189
-rw-r--r--gnu/llvm/unittests/AsmParser/AsmParserTest.cpp155
-rw-r--r--gnu/llvm/unittests/AsmParser/CMakeLists.txt9
-rw-r--r--gnu/llvm/unittests/AsmParser/Makefile15
-rw-r--r--gnu/llvm/unittests/Bitcode/BitReaderTest.cpp275
-rw-r--r--gnu/llvm/unittests/Bitcode/BitstreamReaderTest.cpp56
-rw-r--r--gnu/llvm/unittests/Bitcode/CMakeLists.txt12
-rw-r--r--gnu/llvm/unittests/Bitcode/Makefile15
-rw-r--r--gnu/llvm/unittests/CMakeLists.txt28
-rw-r--r--gnu/llvm/unittests/CodeGen/CMakeLists.txt12
-rw-r--r--gnu/llvm/unittests/CodeGen/DIEHashTest.cpp699
-rw-r--r--gnu/llvm/unittests/CodeGen/Makefile16
-rw-r--r--gnu/llvm/unittests/DebugInfo/CMakeLists.txt3
-rw-r--r--gnu/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt11
-rw-r--r--gnu/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp124
-rw-r--r--gnu/llvm/unittests/DebugInfo/DWARF/Makefile16
-rw-r--r--gnu/llvm/unittests/DebugInfo/Makefile15
-rw-r--r--gnu/llvm/unittests/DebugInfo/PDB/CMakeLists.txt11
-rw-r--r--gnu/llvm/unittests/DebugInfo/PDB/Makefile16
-rw-r--r--gnu/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp397
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/CMakeLists.txt22
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp170
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt33
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp510
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp170
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp423
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp229
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp284
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h103
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h347
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTests.def1
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/MCJIT/Makefile18
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Makefile22
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt22
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp75
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp55
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp48
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp32
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/Makefile16
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp176
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp275
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp160
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp25
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h179
-rw-r--r--gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp147
-rw-r--r--gnu/llvm/unittests/IR/AsmWriterTest.cpp37
-rw-r--r--gnu/llvm/unittests/IR/AttributesTest.cpp47
-rw-r--r--gnu/llvm/unittests/IR/CMakeLists.txt41
-rw-r--r--gnu/llvm/unittests/IR/ConstantRangeTest.cpp623
-rw-r--r--gnu/llvm/unittests/IR/ConstantsTest.cpp455
-rw-r--r--gnu/llvm/unittests/IR/DebugInfoTest.cpp81
-rw-r--r--gnu/llvm/unittests/IR/DominatorTreeTest.cpp259
-rw-r--r--gnu/llvm/unittests/IR/IRBuilderTest.cpp421
-rw-r--r--gnu/llvm/unittests/IR/InstructionsTest.cpp524
-rw-r--r--gnu/llvm/unittests/IR/LegacyPassManagerTest.cpp548
-rw-r--r--gnu/llvm/unittests/IR/MDBuilderTest.cpp108
-rw-r--r--gnu/llvm/unittests/IR/Makefile15
-rw-r--r--gnu/llvm/unittests/IR/MetadataTest.cpp2304
-rw-r--r--gnu/llvm/unittests/IR/PassManagerTest.cpp349
-rw-r--r--gnu/llvm/unittests/IR/PatternMatch.cpp298
-rw-r--r--gnu/llvm/unittests/IR/TypeBuilderTest.cpp253
-rw-r--r--gnu/llvm/unittests/IR/TypesTest.cpp38
-rw-r--r--gnu/llvm/unittests/IR/UseTest.cpp112
-rw-r--r--gnu/llvm/unittests/IR/UserTest.cpp120
-rw-r--r--gnu/llvm/unittests/IR/ValueHandleTest.cpp413
-rw-r--r--gnu/llvm/unittests/IR/ValueMapTest.cpp295
-rw-r--r--gnu/llvm/unittests/IR/ValueTest.cpp238
-rw-r--r--gnu/llvm/unittests/IR/VerifierTest.cpp111
-rw-r--r--gnu/llvm/unittests/IR/WaymarkTest.cpp58
-rw-r--r--gnu/llvm/unittests/LineEditor/CMakeLists.txt8
-rw-r--r--gnu/llvm/unittests/LineEditor/LineEditor.cpp83
-rw-r--r--gnu/llvm/unittests/LineEditor/Makefile15
-rw-r--r--gnu/llvm/unittests/Linker/CMakeLists.txt13
-rw-r--r--gnu/llvm/unittests/Linker/LinkModulesTest.cpp333
-rw-r--r--gnu/llvm/unittests/Linker/Makefile15
-rw-r--r--gnu/llvm/unittests/MC/CMakeLists.txt12
-rw-r--r--gnu/llvm/unittests/MC/Disassembler.cpp64
-rw-r--r--gnu/llvm/unittests/MC/Makefile15
-rw-r--r--gnu/llvm/unittests/MC/StringTableBuilderTest.cpp71
-rw-r--r--gnu/llvm/unittests/MC/YAMLTest.cpp38
-rw-r--r--gnu/llvm/unittests/Makefile20
-rw-r--r--gnu/llvm/unittests/Makefile.unittest69
-rw-r--r--gnu/llvm/unittests/Option/CMakeLists.txt13
-rw-r--r--gnu/llvm/unittests/Option/Makefile23
-rw-r--r--gnu/llvm/unittests/Option/OptionParsingTest.cpp216
-rw-r--r--gnu/llvm/unittests/Option/Opts.td28
-rw-r--r--gnu/llvm/unittests/ProfileData/CMakeLists.txt11
-rw-r--r--gnu/llvm/unittests/ProfileData/CoverageMappingTest.cpp295
-rw-r--r--gnu/llvm/unittests/ProfileData/InstrProfTest.cpp734
-rw-r--r--gnu/llvm/unittests/ProfileData/Makefile15
-rw-r--r--gnu/llvm/unittests/ProfileData/SampleProfTest.cpp132
-rw-r--r--gnu/llvm/unittests/Support/AlignOfTest.cpp357
-rw-r--r--gnu/llvm/unittests/Support/AllocatorTest.cpp188
-rw-r--r--gnu/llvm/unittests/Support/ArrayRecyclerTest.cpp109
-rw-r--r--gnu/llvm/unittests/Support/BlockFrequencyTest.cpp128
-rw-r--r--gnu/llvm/unittests/Support/BranchProbabilityTest.cpp358
-rw-r--r--gnu/llvm/unittests/Support/CMakeLists.txt59
-rw-r--r--gnu/llvm/unittests/Support/Casting.cpp330
-rw-r--r--gnu/llvm/unittests/Support/CommandLineTest.cpp268
-rw-r--r--gnu/llvm/unittests/Support/CompressionTest.cpp70
-rw-r--r--gnu/llvm/unittests/Support/ConvertUTFTest.cpp1678
-rw-r--r--gnu/llvm/unittests/Support/DataExtractorTest.cpp120
-rw-r--r--gnu/llvm/unittests/Support/DwarfTest.cpp141
-rw-r--r--gnu/llvm/unittests/Support/EndianStreamTest.cpp157
-rw-r--r--gnu/llvm/unittests/Support/EndianTest.cpp204
-rw-r--r--gnu/llvm/unittests/Support/ErrorOrTest.cpp100
-rw-r--r--gnu/llvm/unittests/Support/FileOutputBufferTest.cpp121
-rw-r--r--gnu/llvm/unittests/Support/IteratorTest.cpp101
-rw-r--r--gnu/llvm/unittests/Support/LEB128Test.cpp348
-rw-r--r--gnu/llvm/unittests/Support/LineIteratorTest.cpp193
-rw-r--r--gnu/llvm/unittests/Support/LockFileManagerTest.cpp127
-rw-r--r--gnu/llvm/unittests/Support/MD5Test.cpp60
-rw-r--r--gnu/llvm/unittests/Support/Makefile15
-rw-r--r--gnu/llvm/unittests/Support/ManagedStatic.cpp60
-rw-r--r--gnu/llvm/unittests/Support/MathExtrasTest.cpp361
-rw-r--r--gnu/llvm/unittests/Support/MemoryBufferTest.cpp225
-rw-r--r--gnu/llvm/unittests/Support/MemoryTest.cpp365
-rw-r--r--gnu/llvm/unittests/Support/Path.cpp950
-rw-r--r--gnu/llvm/unittests/Support/ProcessTest.cpp57
-rw-r--r--gnu/llvm/unittests/Support/ProgramTest.cpp355
-rw-r--r--gnu/llvm/unittests/Support/RegexTest.cpp156
-rw-r--r--gnu/llvm/unittests/Support/ReplaceFileTest.cpp113
-rw-r--r--gnu/llvm/unittests/Support/ScaledNumberTest.cpp564
-rw-r--r--gnu/llvm/unittests/Support/SourceMgrTest.cpp175
-rw-r--r--gnu/llvm/unittests/Support/SpecialCaseListTest.cpp135
-rw-r--r--gnu/llvm/unittests/Support/StreamingMemoryObject.cpp39
-rw-r--r--gnu/llvm/unittests/Support/StringPool.cpp31
-rw-r--r--gnu/llvm/unittests/Support/SwapByteOrderTest.cpp201
-rw-r--r--gnu/llvm/unittests/Support/TargetRegistry.cpp42
-rw-r--r--gnu/llvm/unittests/Support/ThreadLocalTest.cpp57
-rw-r--r--gnu/llvm/unittests/Support/ThreadPool.cpp168
-rw-r--r--gnu/llvm/unittests/Support/TimeValueTest.cpp40
-rw-r--r--gnu/llvm/unittests/Support/TimerTest.cpp65
-rw-r--r--gnu/llvm/unittests/Support/TrailingObjectsTest.cpp195
-rw-r--r--gnu/llvm/unittests/Support/UnicodeTest.cpp93
-rw-r--r--gnu/llvm/unittests/Support/YAMLIOTest.cpp2196
-rw-r--r--gnu/llvm/unittests/Support/YAMLParserTest.cpp335
-rw-r--r--gnu/llvm/unittests/Support/formatted_raw_ostream_test.cpp33
-rw-r--r--gnu/llvm/unittests/Support/raw_ostream_test.cpp185
-rw-r--r--gnu/llvm/unittests/Support/raw_pwrite_stream_test.cpp64
-rw-r--r--gnu/llvm/unittests/Transforms/CMakeLists.txt2
-rw-r--r--gnu/llvm/unittests/Transforms/IPO/CMakeLists.txt9
-rw-r--r--gnu/llvm/unittests/Transforms/IPO/LowerBitSets.cpp155
-rw-r--r--gnu/llvm/unittests/Transforms/IPO/Makefile15
-rw-r--r--gnu/llvm/unittests/Transforms/Makefile17
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp102
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/CMakeLists.txt13
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/Cloning.cpp450
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/IntegerDivision.cpp264
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/Local.cpp97
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/Makefile15
-rw-r--r--gnu/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp58
203 files changed, 44593 insertions, 0 deletions
diff --git a/gnu/llvm/unittests/ADT/APFloatTest.cpp b/gnu/llvm/unittests/ADT/APFloatTest.cpp
new file mode 100644
index 00000000000..55c3f48f00d
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/APFloatTest.cpp
@@ -0,0 +1,2894 @@
+//===- 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/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <cmath>
+#include <ostream>
+#include <string>
+
+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) {
+ llvm::SmallVector<char, 100> Buffer;
+ llvm::APFloat F(d);
+ F.toString(Buffer, Prec, Pad);
+ 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.isZero() && !test.isNegative());
+ 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.isZero() && test.isNegative());
+ 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, minnum(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\02", 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, 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));
+}
+
+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 nanbits(const fltSemantics &Sem,
+ bool SNaN, bool Negative, uint64_t fill) {
+ APInt apfill(64, fill);
+ if (SNaN)
+ return APFloat::getSNaN(Sem, Negative, &apfill).bitcastToAPInt();
+ else
+ return APFloat::getQNaN(Sem, Negative, &apfill).bitcastToAPInt();
+}
+
+TEST(APFloatTest, makeNaN) {
+ ASSERT_EQ(0x7fc00000, nanbits(APFloat::IEEEsingle, false, false, 0));
+ ASSERT_EQ(0xffc00000, nanbits(APFloat::IEEEsingle, false, true, 0));
+ ASSERT_EQ(0x7fc0ae72, nanbits(APFloat::IEEEsingle, false, false, 0xae72));
+ ASSERT_EQ(0x7fffae72, nanbits(APFloat::IEEEsingle, false, false, 0xffffae72));
+ ASSERT_EQ(0x7fa00000, nanbits(APFloat::IEEEsingle, true, false, 0));
+ ASSERT_EQ(0xffa00000, nanbits(APFloat::IEEEsingle, true, true, 0));
+ ASSERT_EQ(0x7f80ae72, nanbits(APFloat::IEEEsingle, true, false, 0xae72));
+ ASSERT_EQ(0x7fbfae72, nanbits(APFloat::IEEEsingle, true, false, 0xffffae72));
+
+ ASSERT_EQ(0x7ff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, false, 0));
+ ASSERT_EQ(0xfff8000000000000ULL, nanbits(APFloat::IEEEdouble, false, true, 0));
+ ASSERT_EQ(0x7ff800000000ae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xae72));
+ ASSERT_EQ(0x7fffffffffffae72ULL, nanbits(APFloat::IEEEdouble, false, false, 0xffffffffffffae72ULL));
+ ASSERT_EQ(0x7ff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, false, 0));
+ ASSERT_EQ(0xfff4000000000000ULL, nanbits(APFloat::IEEEdouble, true, true, 0));
+ ASSERT_EQ(0x7ff000000000ae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xae72));
+ ASSERT_EQ(0x7ff7ffffffffae72ULL, nanbits(APFloat::IEEEdouble, true, false, 0xffffffffffffae72ULL));
+}
+
+#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\02", 3)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("1\02e1", 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\02", 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\02", 5)), "Invalid character in significand");
+ EXPECT_DEATH(APFloat(APFloat::IEEEdouble, StringRef("0x1\02p1", 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\02", 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(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]);
+
+ test.divide(APFloat(APFloat::PPCDoubleDouble, "3.0"), APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(0x3fd5555555555555ull, test.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x3c75555555555556ull, 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]);
+
+ test = APFloat(APFloat::PPCDoubleDouble, "1.0");
+ test.add(APFloat(APFloat::PPCDoubleDouble, "0x1p-105"), APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
+ EXPECT_EQ(0x3960000000000000ull, test.bitcastToAPInt().getRawData()[1]);
+
+ test = APFloat(APFloat::PPCDoubleDouble, "1.0");
+ test.add(APFloat(APFloat::PPCDoubleDouble, "0x1p-106"), APFloat::rmNearestTiesToEven);
+ EXPECT_EQ(0x3ff0000000000000ull, test.bitcastToAPInt().getRawData()[0]);
+#if 0 // XFAIL
+ // This is what we would expect with a true double-double implementation
+ EXPECT_EQ(0x3950000000000000ull, test.bitcastToAPInt().getRawData()[1]);
+#else
+ // This is what we get with our 106-bit mantissa approximation
+ EXPECT_EQ(0x0000000000000000ull, test.bitcastToAPInt().getRawData()[1]);
+#endif
+}
+
+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, ilogb) {
+ 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(-126, ilogb(APFloat::getSmallest(APFloat::IEEEsingle, false)));
+ EXPECT_EQ(-126, 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) {
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle, "0x1p+0")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 0)));
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle, "0x1p+42")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 42)));
+ EXPECT_TRUE(
+ APFloat(APFloat::IEEEsingle, "0x1p-42")
+ .bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -42)));
+
+ 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)));
+ EXPECT_TRUE(MInf.bitwiseIsEqual(scalbn(MInf, 0)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(scalbn(PZero, 0)));
+ EXPECT_TRUE(MZero.bitwiseIsEqual(scalbn(MZero, 0)));
+ EXPECT_TRUE(QPNaN.bitwiseIsEqual(scalbn(QPNaN, 0)));
+ EXPECT_TRUE(QMNaN.bitwiseIsEqual(scalbn(QMNaN, 0)));
+ EXPECT_TRUE(SNaN.bitwiseIsEqual(scalbn(SNaN, 0)));
+
+ EXPECT_TRUE(
+ PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), 128)));
+ EXPECT_TRUE(MInf.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), 128)));
+ EXPECT_TRUE(
+ PInf.bitwiseIsEqual(scalbn(APFloat(APFloat::IEEEsingle, "0x1p+127"), 1)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle, "0x1p+0"), -127)));
+ EXPECT_TRUE(MZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle, "-0x1p+0"), -127)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1)));
+ EXPECT_TRUE(PZero.bitwiseIsEqual(
+ scalbn(APFloat(APFloat::IEEEsingle, "0x1p-126"), -1)));
+}
+}
diff --git a/gnu/llvm/unittests/ADT/APIntTest.cpp b/gnu/llvm/unittests/ADT/APIntTest.cpp
new file mode 100644
index 00000000000..0002dad8555
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/APIntTest.cpp
@@ -0,0 +1,1025 @@
+//===- 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/SmallString.h"
+#include "gtest/gtest.h"
+#include <array>
+#include <ostream>
+
+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, 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());
+}
+
+// XFAIL this test on FreeBSD where the system gcc-4.2.1 seems to miscompile it.
+#if defined(__llvm__) || !defined(__FreeBSD__)
+
+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());
+}
+
+#endif
+
+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());
+}
+
+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);
+
+ // 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(zero, 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));
+}
+
+
+// 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});
+}
+
+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, 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(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));
+
+ APInt Big(256, "00004000800000000000000000003fff8000000000000000", 16);
+ APInt Rot(256, "3fff80000000000000000000000000000000000040008000", 16);
+ EXPECT_EQ(Rot, Big.rotr(144));
+}
+
+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.
+ {
+ integerPart singleWord = ~integerPart(0) << (integerPartWidth - 1);
+ integerPart carry = APInt::tcDecrement(&singleWord, 1);
+ EXPECT_EQ(carry, integerPart(0));
+ EXPECT_EQ(singleWord, ~integerPart(0) >> 1);
+ }
+
+ // With out borrow.
+ {
+ integerPart singleWord = 0;
+ integerPart carry = APInt::tcDecrement(&singleWord, 1);
+ EXPECT_EQ(carry, integerPart(1));
+ EXPECT_EQ(singleWord, ~integerPart(0));
+ }
+
+ // Test multiword decrement.
+
+ // No across word borrow, no out borrow.
+ {
+ integerPart test[4] = {0x1, 0x1, 0x1, 0x1};
+ integerPart 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.
+ {
+ integerPart test[4] = {0x0, 0xF, 0x1, 0x1};
+ integerPart expected[4] = {~integerPart(0), 0xE, 0x1, 0x1};
+ integerPart carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, integerPart(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 2 across word borrow, no out borrow.
+ {
+ integerPart test[4] = {0x0, 0x0, 0xC, 0x1};
+ integerPart expected[4] = {~integerPart(0), ~integerPart(0), 0xB, 0x1};
+ integerPart carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, integerPart(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 3 across word borrow, no out borrow.
+ {
+ integerPart test[4] = {0x0, 0x0, 0x0, 0x1};
+ integerPart expected[4] = {~integerPart(0), ~integerPart(0), ~integerPart(0), 0x0};
+ integerPart carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, integerPart(0));
+ EXPECT_EQ(APInt::tcCompare(test, expected, 4), 0);
+ }
+
+ // 3 across word borrow, with out borrow.
+ {
+ integerPart test[4] = {0x0, 0x0, 0x0, 0x0};
+ integerPart expected[4] = {~integerPart(0), ~integerPart(0), ~integerPart(0), ~integerPart(0)};
+ integerPart carry = APInt::tcDecrement(test, 4);
+ EXPECT_EQ(carry, integerPart(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.
+ integerPart E2[4] = {
+ 0xEB6EB136591CBA21ULL,
+ 0x7B9358BD6A33F10AULL,
+ 0x7E7FFA5EADD8846ULL,
+ 0x305F341CA00B613DULL
+ };
+ APInt A2(integerPartWidth*4, E2);
+ for (unsigned i = 0; i < 4; ++i) {
+ for (unsigned j = 0; j < integerPartWidth; ++j) {
+ EXPECT_EQ(bool(E2[i] & (1ULL << j)),
+ A2[i*integerPartWidth + 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.
+ integerPart I4[4] = {0x0, 0xF, 0x18, 0x0};
+ APInt A4(integerPartWidth*4, I4);
+ EXPECT_EQ(A4.nearestLogBase2(), A4.ceilLogBase2());
+
+ // Test round down.
+ integerPart I5[4] = {0x0, 0xF, 0x10, 0x0};
+ APInt A5(integerPartWidth*4, I5);
+ EXPECT_EQ(A5.nearestLogBase2(), A5.logBase2());
+
+ // Test ties round up.
+ uint64_t I6[4] = {0x0, 0x0, 0x0, 0x18};
+ APInt A6(integerPartWidth*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));
+}
+
+#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
+}
diff --git a/gnu/llvm/unittests/ADT/APSIntTest.cpp b/gnu/llvm/unittests/ADT/APSIntTest.cpp
new file mode 100644
index 00000000000..a9b3071d138
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/ArrayRefTest.cpp b/gnu/llvm/unittests/ADT/ArrayRefTest.cpp
new file mode 100644
index 00000000000..6cbadd6bc22
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/ArrayRefTest.cpp
@@ -0,0 +1,143 @@
+//===- 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 <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");
+
+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, 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, 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) {
+ ArrayRef<int> A = { 0, 1, 2, 3, 4 };
+ 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 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/gnu/llvm/unittests/ADT/BitVectorTest.cpp b/gnu/llvm/unittests/ADT/BitVectorTest.cpp
new file mode 100644
index 00000000000..95ff93fa9c4
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/BitVectorTest.cpp
@@ -0,0 +1,403 @@
+//===- 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, 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_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());
+}
+
+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));
+}
+
+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());
+}
+}
+#endif
diff --git a/gnu/llvm/unittests/ADT/CMakeLists.txt b/gnu/llvm/unittests/ADT/CMakeLists.txt
new file mode 100644
index 00000000000..bce1bf93a33
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/CMakeLists.txt
@@ -0,0 +1,53 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+set(ADTSources
+ APFloatTest.cpp
+ APIntTest.cpp
+ APSIntTest.cpp
+ ArrayRefTest.cpp
+ BitVectorTest.cpp
+ DAGDeltaAlgorithmTest.cpp
+ DeltaAlgorithmTest.cpp
+ DenseMapTest.cpp
+ DenseSetTest.cpp
+ FoldingSet.cpp
+ FunctionRefTest.cpp
+ HashingTest.cpp
+ ilistTest.cpp
+ ImmutableMapTest.cpp
+ ImmutableSetTest.cpp
+ IntEqClassesTest.cpp
+ IntervalMapTest.cpp
+ IntrusiveRefCntPtrTest.cpp
+ MakeUniqueTest.cpp
+ MapVectorTest.cpp
+ OptionalTest.cpp
+ PackedVectorTest.cpp
+ PointerEmbeddedIntTest.cpp
+ PointerIntPairTest.cpp
+ PointerSumTypeTest.cpp
+ PointerUnionTest.cpp
+ PostOrderIteratorTest.cpp
+ RangeAdapterTest.cpp
+ SCCIteratorTest.cpp
+ SmallPtrSetTest.cpp
+ SmallStringTest.cpp
+ SmallVectorTest.cpp
+ SparseBitVectorTest.cpp
+ SparseMultiSetTest.cpp
+ SparseSetTest.cpp
+ StringMapTest.cpp
+ StringRefTest.cpp
+ TinyPtrVectorTest.cpp
+ TripleTest.cpp
+ TwineTest.cpp
+ VariadicFunctionTest.cpp
+ )
+
+add_llvm_unittest(ADTTests
+ ${ADTSources}
+ )
+
+add_dependencies(ADTTests intrinsics_gen)
diff --git a/gnu/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp b/gnu/llvm/unittests/ADT/DAGDeltaAlgorithmTest.cpp
new file mode 100644
index 00000000000..190df7f5747
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/DAGDeltaAlgorithm.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/gnu/llvm/unittests/ADT/DeltaAlgorithmTest.cpp b/gnu/llvm/unittests/ADT/DeltaAlgorithmTest.cpp
new file mode 100644
index 00000000000..bed57b1a172
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/DeltaAlgorithm.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/gnu/llvm/unittests/ADT/DenseMapTest.cpp b/gnu/llvm/unittests/ADT/DenseMapTest.cpp
new file mode 100644
index 00000000000..f3dcf95e92f
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/DenseMapTest.cpp
@@ -0,0 +1,441 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/DenseMap.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];
+}
+
+/// \brief 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 = 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 = 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);
+}
+
+// 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());
+}
+
+}
diff --git a/gnu/llvm/unittests/ADT/DenseSetTest.cpp b/gnu/llvm/unittests/ADT/DenseSetTest.cpp
new file mode 100644
index 00000000000..5952353034f
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/DenseSetTest.cpp
@@ -0,0 +1,68 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/DenseSet.h"
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture
+class DenseSetTest : public testing::Test {
+};
+
+// Test hashing with a set of only two entries.
+TEST_F(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(DenseSetCustomTest, FindAsTest) {
+ DenseSet<unsigned, TestDenseSetInfo> set;
+ set.insert(0);
+ set.insert(1);
+ set.insert(2);
+
+ // 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());
+}
+
+}
diff --git a/gnu/llvm/unittests/ADT/FoldingSet.cpp b/gnu/llvm/unittests/ADT/FoldingSet.cpp
new file mode 100644
index 00000000000..5addf27e136
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/FoldingSet.cpp
@@ -0,0 +1,39 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/FoldingSet.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());
+}
+
+}
+
diff --git a/gnu/llvm/unittests/ADT/FunctionRefTest.cpp b/gnu/llvm/unittests/ADT/FunctionRefTest.cpp
new file mode 100644
index 00000000000..075d9a070df
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/FunctionRefTest.cpp
@@ -0,0 +1,28 @@
+//===- 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 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/gnu/llvm/unittests/ADT/HashingTest.cpp b/gnu/llvm/unittests/ADT/HashingTest.cpp
new file mode 100644
index 00000000000..b28561bd011
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/HashingTest.cpp
@@ -0,0 +1,448 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/DataTypes.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
+ { "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 }
+#elif SIZE_MAX == UINT32_MAX
+ { "a", 0x000000004605f745ULL },
+ { "ab", 0x00000000d5f06301ULL },
+ { "abc", 0x00000000559fe1eeULL },
+ { "abcde", 0x00000000424028d7ULL },
+ { "abcdefgh", 0x000000007bb119f8ULL },
+ { "abcdefghijklm", 0x00000000edbca513ULL },
+ { "abcdefghijklmnopqrstu", 0x000000007c15712eULL },
+ { "abcdefghijklmnopqrstuvwxyzabcdef", 0x000000000b3aad66ULL },
+ { "abcdefghijklmnopqrstuvwxyzabcdef"
+ "abcdefghijklmnopqrstuvwxyzghijkl"
+ "abcdefghijklmnopqrstuvwxyzmnopqr"
+ "abcdefghijklmnopqrstuvwxyzstuvwx"
+ "abcdefghijklmnopqrstuvwxyzyzabcd", 0x000000008c758c8bULL },
+ { "a", 0x000000004605f745ULL },
+ { "aa", 0x00000000dc0a52daULL },
+ { "aaa", 0x00000000b309274fULL },
+ { "aaaaa", 0x00000000203b5ef6ULL },
+ { "aaaaaaaa", 0x00000000a429e18fULL },
+ { "aaaaaaaaaaaaa", 0x000000008662070bULL },
+ { "aaaaaaaaaaaaaaaaaaaaa", 0x000000003f11151cULL },
+ { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000008600fe20ULL },
+ { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x000000004e0e0804ULL },
+ { "z", 0x00000000c5e405e9ULL },
+ { "zz", 0x00000000a8d8a2c6ULL },
+ { "zzz", 0x00000000fc2af672ULL },
+ { "zzzzz", 0x0000000047d9efe6ULL },
+ { "zzzzzzzz", 0x0000000080d77794ULL },
+ { "zzzzzzzzzzzzz", 0x00000000405f93adULL },
+ { "zzzzzzzzzzzzzzzzzzzzz", 0x00000000fc72838dULL },
+ { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x000000007ce160f1ULL },
+ { "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+ "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", 0x00000000aed9ed1bULL },
+ { "a", 0x000000004605f745ULL },
+ { "ab", 0x00000000d5f06301ULL },
+ { "aba", 0x00000000a85cd91bULL },
+ { "ababa", 0x000000009e3bb52eULL },
+ { "abababab", 0x000000002709b3b9ULL },
+ { "ababababababa", 0x000000003a234174ULL },
+ { "ababababababababababa", 0x000000005c63e5ceULL },
+ { "abababababababababababababababab", 0x0000000013f74334ULL },
+ { "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab"
+ "abababababababababababababababab", 0x00000000c1a6f135ULL },
+#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/gnu/llvm/unittests/ADT/ImmutableMapTest.cpp b/gnu/llvm/unittests/ADT/ImmutableMapTest.cpp
new file mode 100644
index 00000000000..6a99884bfbb
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/ImmutableMap.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/gnu/llvm/unittests/ADT/ImmutableSetTest.cpp b/gnu/llvm/unittests/ADT/ImmutableSetTest.cpp
new file mode 100644
index 00000000000..febd441db16
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/ImmutableSetTest.cpp
@@ -0,0 +1,201 @@
+//===----------- 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 "gtest/gtest.h"
+#include "llvm/ADT/ImmutableSet.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);
+ }
+ ASSERT_EQ(0, i);
+
+ i = 0;
+ for (ImmutableSet<long>::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+ ASSERT_EQ(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);
+ }
+ ASSERT_EQ(6, i);
+}
+
+}
diff --git a/gnu/llvm/unittests/ADT/IntEqClassesTest.cpp b/gnu/llvm/unittests/ADT/IntEqClassesTest.cpp
new file mode 100644
index 00000000000..fc908c1e8bf
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/IntervalMapTest.cpp b/gnu/llvm/unittests/ADT/IntervalMapTest.cpp
new file mode 100644
index 00000000000..b5556d265ae
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/IntervalMapTest.cpp
@@ -0,0 +1,716 @@
+//===---- 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;
+
+// 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());
+
+ I.setStop(160);
+ ASSERT_TRUE(I.valid());
+ EXPECT_EQ(150u, 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()));
+}
+
+// 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(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/gnu/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp b/gnu/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
new file mode 100644
index 00000000000..c67ec130912
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
@@ -0,0 +1,66 @@
+//===- 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 {
+struct VirtualRefCounted : public llvm::RefCountedBaseVPTR {
+ virtual void f() {}
+};
+}
+
+namespace llvm {
+
+// Run this test with valgrind to detect memory leaks.
+TEST(IntrusiveRefCntPtr, RefCountedBaseVPTRCopyDoesNotLeak) {
+ VirtualRefCounted *V1 = new VirtualRefCounted;
+ IntrusiveRefCntPtr<VirtualRefCounted> R1 = V1;
+ VirtualRefCounted *V2 = new VirtualRefCounted(*V1);
+ IntrusiveRefCntPtr<VirtualRefCounted> R2 = V2;
+}
+
+struct SimpleRefCounted : public RefCountedBase<SimpleRefCounted> {};
+
+// Run this test with valgrind to detect memory leaks.
+TEST(IntrusiveRefCntPtr, RefCountedBaseCopyDoesNotLeak) {
+ SimpleRefCounted *S1 = new SimpleRefCounted;
+ IntrusiveRefCntPtr<SimpleRefCounted> R1 = S1;
+ SimpleRefCounted *S2 = new SimpleRefCounted(*S1);
+ IntrusiveRefCntPtr<SimpleRefCounted> R2 = S2;
+}
+
+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/gnu/llvm/unittests/ADT/MakeUniqueTest.cpp b/gnu/llvm/unittests/ADT/MakeUniqueTest.cpp
new file mode 100644
index 00000000000..3b4938a2ef3
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/Makefile b/gnu/llvm/unittests/ADT/Makefile
new file mode 100644
index 00000000000..c255a0b44d0
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/Makefile
@@ -0,0 +1,23 @@
+##===- unittests/ADT/Makefile ------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = ADT
+LINK_COMPONENTS := support
+
+include $(LEVEL)/Makefile.config
+
+# Xfail BitVectorTest for now on PPC Darwin. 7598360.
+ifeq ($(ARCH),PowerPC)
+ifeq ($(TARGET_OS),Darwin)
+CPP.Flags += -DXFAIL
+endif
+endif
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/ADT/MapVectorTest.cpp b/gnu/llvm/unittests/ADT/MapVectorTest.cpp
new file mode 100644
index 00000000000..ff8464293c7
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/MapVectorTest.cpp
@@ -0,0 +1,367 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/iterator_range.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(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(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/gnu/llvm/unittests/ADT/OptionalTest.cpp b/gnu/llvm/unittests/ADT/OptionalTest.cpp
new file mode 100644
index 00000000000..18b59e31581
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/OptionalTest.cpp
@@ -0,0 +1,394 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/Optional.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_FALSE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, 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_FALSE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(1u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(0u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, 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_FALSE((bool)A);
+ EXPECT_TRUE((bool)B);
+ EXPECT_EQ(3, B->val);
+ EXPECT_EQ(0u, MoveOnly::MoveConstructions);
+ EXPECT_EQ(1u, MoveOnly::MoveAssignments);
+ EXPECT_EQ(1u, 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
+
+TEST_F(OptionalTest, NoneComparison) {
+ Optional<int> o;
+ EXPECT_EQ(o, None);
+ EXPECT_EQ(None, o);
+ EXPECT_FALSE(o != None);
+ EXPECT_FALSE(None != o);
+ o = 3;
+ EXPECT_FALSE(o == None);
+ EXPECT_FALSE(None == o);
+ EXPECT_TRUE(o != None);
+ EXPECT_TRUE(None != o);
+}
+
+} // end anonymous namespace
+
diff --git a/gnu/llvm/unittests/ADT/PackedVectorTest.cpp b/gnu/llvm/unittests/ADT/PackedVectorTest.cpp
new file mode 100644
index 00000000000..199a6704309
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp b/gnu/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp
new file mode 100644
index 00000000000..b10365a2f61
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/PointerEmbeddedIntTest.cpp
@@ -0,0 +1,46 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/PointerEmbeddedInt.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);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ADT/PointerIntPairTest.cpp b/gnu/llvm/unittests/ADT/PointerIntPairTest.cpp
new file mode 100644
index 00000000000..13680c78b9b
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/PointerIntPair.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/gnu/llvm/unittests/ADT/PointerSumTypeTest.cpp b/gnu/llvm/unittests/ADT/PointerSumTypeTest.cpp
new file mode 100644
index 00000000000..75c88f7fee9
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/PointerSumType.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/gnu/llvm/unittests/ADT/PointerUnionTest.cpp b/gnu/llvm/unittests/ADT/PointerUnionTest.cpp
new file mode 100644
index 00000000000..a592784ae09
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/PointerUnion.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/gnu/llvm/unittests/ADT/PostOrderIteratorTest.cpp b/gnu/llvm/unittests/ADT/PostOrderIteratorTest.cpp
new file mode 100644
index 00000000000..1da1078c749
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/PostOrderIterator.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CFG.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(Null, Null);
+ ExtSetTy Ext;
+ po_iterator_storage<ExtSetTy, true> PISExt(Ext);
+ PIS.insertEdge(Null, Null);
+
+ // Test above, but going through po_iterator (which inherits from template
+ // base)
+ BasicBlock *NullBB = nullptr;
+ auto PI = po_end(NullBB);
+ PI.insertEdge(NullBB, NullBB);
+ auto PIExt = po_ext_end(NullBB, Ext);
+ PIExt.insertEdge(NullBB, NullBB);
+}
+}
diff --git a/gnu/llvm/unittests/ADT/RangeAdapterTest.cpp b/gnu/llvm/unittests/ADT/RangeAdapterTest.cpp
new file mode 100644
index 00000000000..634f5bb990d
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/RangeAdapterTest.cpp
@@ -0,0 +1,83 @@
+//===- 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/iterator_range.h"
+#include "llvm/ADT/STLExtras.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;
+ reverse_iterator rbegin() { return Vec.rbegin(); }
+ reverse_iterator rend() { 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 {
+ std::vector<int> Vec;
+
+public:
+ BidirectionalVector(std::initializer_list<int> list) : Vec(list) {}
+
+ typedef std::vector<int>::iterator iterator;
+ iterator begin();
+ iterator end();
+
+ typedef std::vector<int>::reverse_iterator reverse_iterator;
+ reverse_iterator rbegin() { return Vec.rbegin(); }
+ reverse_iterator rend() { return Vec.rend(); }
+};
+
+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>, ReverseOnlyVector,
+ BidirectionalVector> RangeAdapterRValueTestTypes;
+TYPED_TEST_CASE(RangeAdapterRValueTest, RangeAdapterRValueTestTypes);
+
+TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) {
+ TestRev(reverse(TypeParam({0, 1, 2, 3})));
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/ADT/SCCIteratorTest.cpp b/gnu/llvm/unittests/ADT/SCCIteratorTest.cpp
new file mode 100644
index 00000000000..da8c04483f9
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/SCCIteratorTest.cpp
@@ -0,0 +1,344 @@
+//===----- 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 "llvm/ADT/GraphTraits.h"
+#include "gtest/gtest.h"
+#include <limits.h>
+
+using namespace llvm;
+
+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 NodeType;
+ typedef typename Graph<N>::ChildIterator ChildIteratorType;
+
+ static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
+ static inline ChildIteratorType child_begin(NodeType *Node) {
+ return Graph<N>::child_begin(Node);
+ }
+ static inline ChildIteratorType child_end(NodeType *Node) {
+ return Graph<N>::child_end(Node);
+ }
+};
+
+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/gnu/llvm/unittests/ADT/SmallPtrSetTest.cpp b/gnu/llvm/unittests/ADT/SmallPtrSetTest.cpp
new file mode 100644
index 00000000000..fdd1cbb6004
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/SmallPtrSetTest.cpp
@@ -0,0 +1,212 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+using namespace llvm;
+
+TEST(SmallPtrSetTest, Assignment) {
+ 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]);
+
+ SmallPtrSet<int *, 4> s2;
+ (s2 = s1).insert(&buf[2]);
+
+ // Self assign as well.
+ (s2 = 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]));
+}
+
+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]);
+
+ std::swap(a, b);
+
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(2U, b.size());
+ EXPECT_TRUE(a.count(&buf[2]));
+ EXPECT_TRUE(b.count(&buf[0]));
+ EXPECT_TRUE(b.count(&buf[1]));
+
+ 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_TRUE(a.count(&buf[3]));
+ EXPECT_TRUE(b.count(&buf[2]));
+
+ std::swap(a, b);
+
+ EXPECT_EQ(1U, a.size());
+ EXPECT_EQ(3U, b.size());
+ EXPECT_TRUE(a.count(&buf[2]));
+ EXPECT_TRUE(b.count(&buf[0]));
+ EXPECT_TRUE(b.count(&buf[1]));
+ 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]));
+}
diff --git a/gnu/llvm/unittests/ADT/SmallStringTest.cpp b/gnu/llvm/unittests/ADT/SmallStringTest.cpp
new file mode 100644
index 00000000000..995ef8e8127
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/SmallVectorTest.cpp b/gnu/llvm/unittests/ADT/SmallVectorTest.cpp
new file mode 100644
index 00000000000..46f7021ac16
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/SmallVectorTest.cpp
@@ -0,0 +1,925 @@
+//===- 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/ArrayRef.h"
+#include "llvm/ADT/SmallVector.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);
+
+// 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);
+}
+
+// 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);
+}
+
+// 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);
+ this->theVector.erase(this->theVector.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);
+ this->theVector.erase(this->theVector.begin(), this->theVector.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, 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/gnu/llvm/unittests/ADT/SparseBitVectorTest.cpp b/gnu/llvm/unittests/ADT/SparseBitVectorTest.cpp
new file mode 100644
index 00000000000..9127225860b
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/SparseBitVectorTest.cpp
@@ -0,0 +1,130 @@
+//===- 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));
+}
+
+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 = 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());
+}
+
+}
diff --git a/gnu/llvm/unittests/ADT/SparseMultiSetTest.cpp b/gnu/llvm/unittests/ADT/SparseMultiSetTest.cpp
new file mode 100644
index 00000000000..032990e4bcd
--- /dev/null
+++ b/gnu/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/gnu/llvm/unittests/ADT/SparseSetTest.cpp b/gnu/llvm/unittests/ADT/SparseSetTest.cpp
new file mode 100644
index 00000000000..eb0e0db283b
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/SparseSetTest.cpp
@@ -0,0 +1,186 @@
+//===------ 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));
+}
+} // namespace
diff --git a/gnu/llvm/unittests/ADT/StringMapTest.cpp b/gnu/llvm/unittests/ADT/StringMapTest.cpp
new file mode 100644
index 00000000000..4ed0b76f0f4
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/StringMapTest.cpp
@@ -0,0 +1,359 @@
+//===- 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 "gtest/gtest.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/DataTypes.h"
+#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"));
+}
+
+// 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(1);
+ EXPECT_EQ(1u, t.getNumBuckets());
+
+ StringMap<uint32_t>::iterator It =
+ t.insert(std::make_pair("abcdef", 42)).first;
+ EXPECT_EQ(2u, t.getNumBuckets());
+ EXPECT_EQ("abcdef", It->first());
+ EXPECT_EQ(42u, It->second);
+}
+
+// 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());
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ADT/StringRefTest.cpp b/gnu/llvm/unittests/ADT/StringRefTest.cpp
new file mode 100644
index 00000000000..6cf2e6a0454
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/StringRefTest.cpp
@@ -0,0 +1,603 @@
+//===- 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;
+}
+
+}
+
+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, 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'));
+}
+
+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(StringRef("\0", 1)));
+}
+
+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, 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, Find) {
+ StringRef Str("hello");
+ EXPECT_EQ(2U, Str.find('l'));
+ EXPECT_EQ(StringRef::npos, Str.find('z'));
+ EXPECT_EQ(StringRef::npos, Str.find("helloworld"));
+ EXPECT_EQ(0U, Str.find("hello"));
+ EXPECT_EQ(1U, Str.find("ello"));
+ EXPECT_EQ(StringRef::npos, Str.find("zz"));
+ EXPECT_EQ(2U, Str.find("ll", 2));
+ EXPECT_EQ(StringRef::npos, Str.find("ll", 3));
+ EXPECT_EQ(0U, Str.find(""));
+ StringRef LongStr("hellx xello hell ello world foo bar hello");
+ EXPECT_EQ(36U, LongStr.find("hello"));
+ EXPECT_EQ(28U, LongStr.find("foo"));
+ EXPECT_EQ(12U, LongStr.find("hell", 2));
+ EXPECT_EQ(0U, LongStr.find(""));
+
+ 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(2U, Str.find_first_of('l'));
+ EXPECT_EQ(1U, Str.find_first_of("el"));
+ EXPECT_EQ(StringRef::npos, Str.find_first_of("xyz"));
+
+ 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 Str("hello");
+ EXPECT_EQ(2U, Str.edit_distance("hill"));
+}
+
+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[] = {
+ "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
+};
+
+
+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);
+ }
+}
+
+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);
+}
+
+
+TEST(StringRefTest, AllocatorCopy) {
+ BumpPtrAllocator Alloc;
+ 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());
+}
+
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ADT/TinyPtrVectorTest.cpp b/gnu/llvm/unittests/ADT/TinyPtrVectorTest.cpp
new file mode 100644
index 00000000000..294dfac0c63
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/TinyPtrVectorTest.cpp
@@ -0,0 +1,461 @@
+//===- 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/ADT/SmallVector.h"
+#include "llvm/Support/type_traits.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+#include <list>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+// The world's worst RNG, but it is deterministic and makes it easy to get
+// *some* shuffling of elements.
+static ptrdiff_t test_shuffle_rng(ptrdiff_t i) {
+ return (i + i * 33) % i;
+}
+static ptrdiff_t (*test_shuffle_rng_p)(ptrdiff_t) = &test_shuffle_rng;
+
+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::random_shuffle(TestPtrs.begin(), TestPtrs.end(), test_shuffle_rng_p);
+ }
+
+ 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));
+}
+
+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/gnu/llvm/unittests/ADT/TripleTest.cpp b/gnu/llvm/unittests/ADT/TripleTest.cpp
new file mode 100644
index 00000000000..ac4fa2274e9
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/TripleTest.cpp
@@ -0,0 +1,1111 @@
+//===----------- 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 "gtest/gtest.h"
+#include "llvm/ADT/Triple.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("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("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("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("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("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-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("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("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("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("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("", Triple::normalize(""));
+ EXPECT_EQ("-", Triple::normalize("-"));
+ EXPECT_EQ("--", Triple::normalize("--"));
+ EXPECT_EQ("---", Triple::normalize("---"));
+ EXPECT_EQ("----", 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("-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("--linux-b-c", Triple::normalize("linux-b-c"));
+ EXPECT_EQ("a--linux-c", Triple::normalize("a-linux-c"));
+
+ EXPECT_EQ("i386-pc-a", Triple::normalize("a-pc-i386"));
+ EXPECT_EQ("i386-pc-", Triple::normalize("-pc-i386"));
+ EXPECT_EQ("-pc-linux-c", Triple::normalize("linux-pc-c"));
+ EXPECT_EQ("-pc-linux", Triple::normalize("linux-pc-"));
+
+ EXPECT_EQ("i386", Triple::normalize("i386"));
+ EXPECT_EQ("-pc", Triple::normalize("pc"));
+ EXPECT_EQ("--linux", Triple::normalize("linux"));
+
+ EXPECT_EQ("x86_64--linux-gnu", Triple::normalize("x86_64-gnu-linux"));
+
+ // Check that normalizing a permutated set of valid components returns a
+ // triple with the unpermuted components.
+ StringRef C[4];
+ for (int Arch = 1+Triple::UnknownArch; Arch <= Triple::LastArchType; ++Arch) {
+ C[0] = Triple::getArchTypeName(Triple::ArchType(Arch));
+ for (int Vendor = 1+Triple::UnknownVendor; Vendor <= Triple::LastVendorType;
+ ++Vendor) {
+ C[1] = Triple::getVendorTypeName(Triple::VendorType(Vendor));
+ for (int OS = 1+Triple::UnknownOS; OS <= Triple::LastOSType; ++OS) {
+ if (OS == Triple::Win32)
+ continue;
+
+ C[2] = Triple::getOSTypeName(Triple::OSType(OS));
+
+ std::string E = Join(C[0], C[1], C[2]);
+ EXPECT_EQ(E, Triple::normalize(Join(C[0], C[1], C[2])));
+
+ EXPECT_EQ(E, Triple::normalize(Join(C[0], C[2], C[1])));
+ EXPECT_EQ(E, Triple::normalize(Join(C[1], C[2], C[0])));
+ EXPECT_EQ(E, Triple::normalize(Join(C[1], C[0], C[2])));
+ EXPECT_EQ(E, Triple::normalize(Join(C[2], C[0], C[1])));
+ EXPECT_EQ(E, Triple::normalize(Join(C[2], C[1], C[0])));
+
+ for (int Env = 1 + Triple::UnknownEnvironment; Env <= Triple::LastEnvironmentType;
+ ++Env) {
+ C[3] = Triple::getEnvironmentTypeName(Triple::EnvironmentType(Env));
+
+ std::string F = Join(C[0], C[1], C[2], C[3]);
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[1], C[2], C[3])));
+
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[1], C[3], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[2], C[3], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[2], C[1], C[3])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[3], C[1], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[0], C[3], C[2], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[2], C[3], C[0])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[2], C[0], C[3])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[3], C[0], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[3], C[2], C[0])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[0], C[2], C[3])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[1], C[0], C[3], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[3], C[0], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[3], C[1], C[0])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[0], C[1], C[3])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[0], C[3], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[1], C[3], C[0])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[2], C[1], C[0], C[3])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[0], C[1], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[0], C[2], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[1], C[2], C[0])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[1], C[0], C[2])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[2], C[0], C[1])));
+ EXPECT_EQ(F, Triple::normalize(Join(C[3], C[2], C[1], C[0])));
+ }
+ }
+ }
+ }
+
+ // Various real-world funky triples. The value returned by GCC's config.sub
+ // is given in the comment.
+ EXPECT_EQ("i386--windows-gnu", Triple::normalize("i386-mingw32")); // i386-pc-mingw32
+ EXPECT_EQ("x86_64--linux-gnu", Triple::normalize("x86_64-linux-gnu")); // x86_64-pc-linux-gnu
+ EXPECT_EQ("i486--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--linux", Triple::normalize("i686-linux")); // i686-pc-linux-gnu
+ EXPECT_EQ("arm-none--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());
+
+ T.setEnvironmentName("amdopencl");
+ EXPECT_EQ(Triple::AMDOpenCL, T.getEnvironment());
+}
+
+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());
+}
+
+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());
+}
+
+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.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());
+}
+
+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);
+}
+
+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());
+
+ 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());
+}
+
+TEST(TripleTest, NormalizeWindows) {
+ EXPECT_EQ("i686-pc-windows-msvc", Triple::normalize("i686-pc-win32"));
+ EXPECT_EQ("i686--windows-msvc", Triple::normalize("i686-win32"));
+ EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32"));
+ EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32"));
+ EXPECT_EQ("i686-pc-windows-gnu", Triple::normalize("i686-pc-mingw32-w64"));
+ EXPECT_EQ("i686--windows-gnu", Triple::normalize("i686-mingw32-w64"));
+ EXPECT_EQ("i686-pc-windows-cygnus", Triple::normalize("i686-pc-cygwin"));
+ EXPECT_EQ("i686--windows-cygnus", Triple::normalize("i686-cygwin"));
+
+ EXPECT_EQ("x86_64-pc-windows-msvc", Triple::normalize("x86_64-pc-win32"));
+ EXPECT_EQ("x86_64--windows-msvc", Triple::normalize("x86_64-win32"));
+ EXPECT_EQ("x86_64-pc-windows-gnu", Triple::normalize("x86_64-pc-mingw32"));
+ EXPECT_EQ("x86_64--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--windows-gnu", Triple::normalize("x86_64-mingw32-w64"));
+
+ EXPECT_EQ("i686-pc-windows-elf", Triple::normalize("i686-pc-win32-elf"));
+ EXPECT_EQ("i686--windows-elf", Triple::normalize("i686-win32-elf"));
+ EXPECT_EQ("i686-pc-windows-macho", Triple::normalize("i686-pc-win32-macho"));
+ EXPECT_EQ("i686--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--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--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) {
+ // Standard ARM Architectures.
+ {
+ llvm::Triple Triple("armv4-unknown-eabi");
+ EXPECT_EQ("strongarm", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv4t-unknown-eabi");
+ EXPECT_EQ("arm7tdmi", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv5-unknown-eabi");
+ EXPECT_EQ("arm10tdmi", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv5t-unknown-eabi");
+ EXPECT_EQ("arm10tdmi", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv5e-unknown-eabi");
+ EXPECT_EQ("arm1022e", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv5tej-unknown-eabi");
+ EXPECT_EQ("arm926ej-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6-unknown-eabi");
+ EXPECT_EQ("arm1136jf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6j-unknown-eabi");
+ EXPECT_EQ("arm1136jf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6k-unknown-eabi");
+ EXPECT_EQ("arm1176j-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6kz-unknown-eabi");
+ EXPECT_EQ("arm1176jzf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6zk-unknown-eabi");
+ EXPECT_EQ("arm1176jzf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6t2-unknown-eabi");
+ EXPECT_EQ("arm1156t2-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6m-unknown-eabi");
+ EXPECT_EQ("cortex-m0", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7-unknown-eabi");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7a-unknown-eabi");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7m-unknown-eabi");
+ EXPECT_EQ("cortex-m3", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7r-unknown-eabi");
+ EXPECT_EQ("cortex-r4", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7r-unknown-eabi");
+ EXPECT_EQ("cortex-r4", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7r-unknown-eabi");
+ EXPECT_EQ("cortex-r4", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7r-unknown-eabi");
+ EXPECT_EQ("cortex-r4", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv8a-unknown-eabi");
+ EXPECT_EQ("cortex-a53", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv8.1a-unknown-eabi");
+ EXPECT_EQ("generic", Triple.getARMCPUForArch());
+ }
+ // Non-synonym names, using -march style, not default arch.
+ {
+ llvm::Triple Triple("arm");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch("armv7-a"));
+ }
+ {
+ llvm::Triple Triple("arm");
+ EXPECT_EQ("cortex-m3", Triple.getARMCPUForArch("armv7-m"));
+ }
+ {
+ llvm::Triple Triple("arm");
+ EXPECT_EQ("cortex-a53", Triple.getARMCPUForArch("armv8"));
+ }
+ {
+ llvm::Triple Triple("arm");
+ EXPECT_EQ("cortex-a53", Triple.getARMCPUForArch("armv8-a"));
+ }
+ // Platform specific defaults.
+ {
+ llvm::Triple Triple("arm--nacl");
+ 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("xscale-unknown-eabi");
+ EXPECT_EQ("xscale", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("iwmmxt-unknown-eabi");
+ EXPECT_EQ("iwmmxt", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7s-apple-ios7");
+ EXPECT_EQ("swift", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7em-apple-ios7");
+ EXPECT_EQ("cortex-m4", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv7l-linux-gnueabihf");
+ EXPECT_EQ("cortex-a8", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6sm-apple-ios7");
+ EXPECT_EQ("cortex-m0", 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());
+ }
+ // armebv6 and armv6eb are permitted, but armebv6eb is not
+ {
+ llvm::Triple Triple("armebv6-non-eabi");
+ EXPECT_EQ("arm1136jf-s", Triple.getARMCPUForArch());
+ }
+ {
+ llvm::Triple Triple("armv6eb-none-eabi");
+ EXPECT_EQ("arm1136jf-s", 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--netbsd-eabi", Triple::normalize("armv6-netbsd-eabi"));
+ EXPECT_EQ("armv7--netbsd-eabi", Triple::normalize("armv7-netbsd-eabi"));
+ EXPECT_EQ("armv6eb--netbsd-eabi", Triple::normalize("armv6eb-netbsd-eabi"));
+ EXPECT_EQ("armv7eb--netbsd-eabi", Triple::normalize("armv7eb-netbsd-eabi"));
+ EXPECT_EQ("armv6--netbsd-eabihf", Triple::normalize("armv6-netbsd-eabihf"));
+ EXPECT_EQ("armv7--netbsd-eabihf", Triple::normalize("armv7-netbsd-eabihf"));
+ EXPECT_EQ("armv6eb--netbsd-eabihf", Triple::normalize("armv6eb-netbsd-eabihf"));
+ EXPECT_EQ("armv7eb--netbsd-eabihf", Triple::normalize("armv7eb-netbsd-eabihf"));
+
+ Triple T;
+ T = Triple("armv6--netbsd-eabi");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ T = Triple("armv6eb--netbsd-eabi");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+}
+
+TEST(TripleTest, ParseARMArch) {
+ // ARM
+ {
+ Triple T = Triple("arm");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ }
+ {
+ Triple T = Triple("armv6t2");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ }
+ {
+ Triple T = Triple("armv8");
+ EXPECT_EQ(Triple::arm, T.getArch());
+ }
+ {
+ Triple T = Triple("armeb");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ }
+ {
+ Triple T = Triple("armv5eb");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ }
+ {
+ Triple T = Triple("armebv7m");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ }
+ {
+ Triple T = Triple("armv7eb");
+ EXPECT_EQ(Triple::armeb, T.getArch());
+ }
+ // THUMB
+ {
+ Triple T = Triple("thumb");
+ EXPECT_EQ(Triple::thumb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbv7a");
+ EXPECT_EQ(Triple::thumb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbeb");
+ EXPECT_EQ(Triple::thumbeb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbv4teb");
+ EXPECT_EQ(Triple::thumbeb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbebv7");
+ EXPECT_EQ(Triple::thumbeb, T.getArch());
+ }
+ {
+ Triple T = Triple("armv6m");
+ EXPECT_EQ(Triple::thumb, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbv2");
+ EXPECT_EQ(Triple::UnknownArch, T.getArch());
+ }
+ {
+ Triple T = Triple("thumbebv6eb");
+ EXPECT_EQ(Triple::UnknownArch, 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());
+ }
+ {
+ Triple T = Triple("aarch64be");
+ EXPECT_EQ(Triple::UnknownArch, T.getArch());
+ }
+ {
+ Triple T = Triple("arm64be");
+ EXPECT_EQ(Triple::UnknownArch, T.getArch());
+ }
+}
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ADT/TwineTest.cpp b/gnu/llvm/unittests/ADT/TwineTest.cpp
new file mode 100644
index 00000000000..9683e97511b
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/TwineTest.cpp
@@ -0,0 +1,97 @@
+//===- 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/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());
+}
+
+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 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());
+}
+
+ // 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/gnu/llvm/unittests/ADT/VariadicFunctionTest.cpp b/gnu/llvm/unittests/ADT/VariadicFunctionTest.cpp
new file mode 100644
index 00000000000..cde31205966
--- /dev/null
+++ b/gnu/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 "gtest/gtest.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/VariadicFunction.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
diff --git a/gnu/llvm/unittests/ADT/ilistTest.cpp b/gnu/llvm/unittests/ADT/ilistTest.cpp
new file mode 100644
index 00000000000..377dcc044dd
--- /dev/null
+++ b/gnu/llvm/unittests/ADT/ilistTest.cpp
@@ -0,0 +1,99 @@
+//===- 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/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(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(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, SpliceOne) {
+ ilist<Node> List;
+ List.push_back(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(2);
+ List.push_back(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, 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(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(5);
+ List.push_back(6);
+ ASSERT_EQ(2u, List.size());
+ EXPECT_EQ(5, List.front().Value);
+ EXPECT_EQ(6, List.back().Value);
+}
+
+}
diff --git a/gnu/llvm/unittests/Analysis/AliasAnalysisTest.cpp b/gnu/llvm/unittests/Analysis/AliasAnalysisTest.cpp
new file mode 100644
index 00000000000..ee116992fe7
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/AliasAnalysisTest.cpp
@@ -0,0 +1,256 @@
+//===--- AliasAnalysisTest.cpp - Mixed TBAA 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/Analysis/AliasAnalysis.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+// Set up some test passes.
+namespace llvm {
+void initializeAATestPassPass(PassRegistry&);
+void initializeTestCustomAAWrapperPassPass(PassRegistry&);
+}
+
+namespace {
+struct AATestPass : FunctionPass {
+ static char ID;
+ AATestPass() : FunctionPass(ID) {
+ initializeAATestPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<AAResultsWrapperPass>();
+ AU.setPreservesAll();
+ }
+
+ bool runOnFunction(Function &F) override {
+ AliasAnalysis &AA = getAnalysis<AAResultsWrapperPass>().getAAResults();
+
+ SetVector<Value *> Pointers;
+ for (Argument &A : F.args())
+ if (A.getType()->isPointerTy())
+ Pointers.insert(&A);
+ for (Instruction &I : instructions(F))
+ if (I.getType()->isPointerTy())
+ Pointers.insert(&I);
+
+ for (Value *P1 : Pointers)
+ for (Value *P2 : Pointers)
+ (void)AA.alias(P1, MemoryLocation::UnknownSize, P2,
+ MemoryLocation::UnknownSize);
+
+ return false;
+ }
+};
+}
+
+char AATestPass::ID = 0;
+INITIALIZE_PASS_BEGIN(AATestPass, "aa-test-pas", "Alias Analysis Test Pass",
+ false, true)
+INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
+INITIALIZE_PASS_END(AATestPass, "aa-test-pass", "Alias Analysis Test Pass",
+ false, true)
+
+namespace {
+/// A test customizable AA result. It merely accepts a callback to run whenever
+/// it receives an alias query. Useful for testing that a particular AA result
+/// is reached.
+struct TestCustomAAResult : AAResultBase<TestCustomAAResult> {
+ friend AAResultBase<TestCustomAAResult>;
+
+ std::function<void()> CB;
+
+ explicit TestCustomAAResult(const TargetLibraryInfo &TLI,
+ std::function<void()> CB)
+ : AAResultBase(TLI), CB(std::move(CB)) {}
+ TestCustomAAResult(TestCustomAAResult &&Arg)
+ : AAResultBase(std::move(Arg)), CB(std::move(Arg.CB)) {}
+
+ bool invalidate(Function &, const PreservedAnalyses &) { return false; }
+
+ AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
+ CB();
+ return MayAlias;
+ }
+};
+}
+
+namespace {
+/// A wrapper pass for the legacy pass manager to use with the above custom AA
+/// result.
+class TestCustomAAWrapperPass : public ImmutablePass {
+ std::function<void()> CB;
+ std::unique_ptr<TestCustomAAResult> Result;
+
+public:
+ static char ID;
+
+ explicit TestCustomAAWrapperPass(
+ std::function<void()> CB = std::function<void()>())
+ : ImmutablePass(ID), CB(std::move(CB)) {
+ initializeTestCustomAAWrapperPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
+ }
+
+ bool doInitialization(Module &M) override {
+ Result.reset(new TestCustomAAResult(
+ getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(), std::move(CB)));
+ return true;
+ }
+
+ bool doFinalization(Module &M) override {
+ Result.reset();
+ return true;
+ }
+
+ TestCustomAAResult &getResult() { return *Result; }
+ const TestCustomAAResult &getResult() const { return *Result; }
+};
+}
+
+char TestCustomAAWrapperPass::ID = 0;
+INITIALIZE_PASS_BEGIN(TestCustomAAWrapperPass, "test-custom-aa",
+ "Test Custom AA Wrapper Pass", false, true)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(TestCustomAAWrapperPass, "test-custom-aa",
+ "Test Custom AA Wrapper Pass", false, true)
+
+namespace {
+
+class AliasAnalysisTest : public testing::Test {
+protected:
+ LLVMContext C;
+ Module M;
+ TargetLibraryInfoImpl TLII;
+ TargetLibraryInfo TLI;
+ std::unique_ptr<AssumptionCache> AC;
+ std::unique_ptr<BasicAAResult> BAR;
+ std::unique_ptr<AAResults> AAR;
+
+ AliasAnalysisTest() : M("AliasAnalysisTest", C), TLI(TLII) {}
+
+ AAResults &getAAResults(Function &F) {
+ // Reset the Function AA results first to clear out any references.
+ AAR.reset(new AAResults());
+
+ // Build the various AA results and register them.
+ AC.reset(new AssumptionCache(F));
+ BAR.reset(new BasicAAResult(M.getDataLayout(), TLI, *AC));
+ AAR->addAAResult(*BAR);
+
+ return *AAR;
+ }
+};
+
+TEST_F(AliasAnalysisTest, getModRefInfo) {
+ // Setup function.
+ FunctionType *FTy =
+ FunctionType::get(Type::getVoidTy(C), std::vector<Type *>(), false);
+ auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ auto *BB = BasicBlock::Create(C, "entry", F);
+ auto IntType = Type::getInt32Ty(C);
+ auto PtrType = Type::getInt32PtrTy(C);
+ auto *Value = ConstantInt::get(IntType, 42);
+ auto *Addr = ConstantPointerNull::get(PtrType);
+
+ auto *Store1 = new StoreInst(Value, Addr, BB);
+ auto *Load1 = new LoadInst(Addr, "load", BB);
+ auto *Add1 = BinaryOperator::CreateAdd(Value, Value, "add", BB);
+ auto *VAArg1 = new VAArgInst(Addr, PtrType, "vaarg", BB);
+ auto *CmpXChg1 = new AtomicCmpXchgInst(Addr, ConstantInt::get(IntType, 0),
+ ConstantInt::get(IntType, 1),
+ Monotonic, Monotonic, CrossThread, BB);
+ auto *AtomicRMW =
+ new AtomicRMWInst(AtomicRMWInst::Xchg, Addr, ConstantInt::get(IntType, 1),
+ Monotonic, CrossThread, BB);
+
+ ReturnInst::Create(C, nullptr, BB);
+
+ auto &AA = getAAResults(*F);
+
+ // Check basic results
+ EXPECT_EQ(AA.getModRefInfo(Store1, MemoryLocation()), MRI_Mod);
+ EXPECT_EQ(AA.getModRefInfo(Store1), MRI_Mod);
+ EXPECT_EQ(AA.getModRefInfo(Load1, MemoryLocation()), MRI_Ref);
+ EXPECT_EQ(AA.getModRefInfo(Load1), MRI_Ref);
+ EXPECT_EQ(AA.getModRefInfo(Add1, MemoryLocation()), MRI_NoModRef);
+ EXPECT_EQ(AA.getModRefInfo(Add1), MRI_NoModRef);
+ EXPECT_EQ(AA.getModRefInfo(VAArg1, MemoryLocation()), MRI_ModRef);
+ EXPECT_EQ(AA.getModRefInfo(VAArg1), MRI_ModRef);
+ EXPECT_EQ(AA.getModRefInfo(CmpXChg1, MemoryLocation()), MRI_ModRef);
+ EXPECT_EQ(AA.getModRefInfo(CmpXChg1), MRI_ModRef);
+ EXPECT_EQ(AA.getModRefInfo(AtomicRMW, MemoryLocation()), MRI_ModRef);
+ EXPECT_EQ(AA.getModRefInfo(AtomicRMW), MRI_ModRef);
+}
+
+class AAPassInfraTest : public testing::Test {
+protected:
+ LLVMContext &C;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M;
+
+public:
+ AAPassInfraTest()
+ : C(getGlobalContext()),
+ M(parseAssemblyString("define i32 @f(i32* %x, i32* %y) {\n"
+ "entry:\n"
+ " %lx = load i32, i32* %x\n"
+ " %ly = load i32, i32* %y\n"
+ " %sum = add i32 %lx, %ly\n"
+ " ret i32 %sum\n"
+ "}\n",
+ Err, C)) {
+ assert(M && "Failed to build the module!");
+ }
+};
+
+TEST_F(AAPassInfraTest, injectExternalAA) {
+ legacy::PassManager PM;
+
+ // Register our custom AA's wrapper pass manually.
+ bool IsCustomAAQueried = false;
+ PM.add(new TestCustomAAWrapperPass([&] { IsCustomAAQueried = true; }));
+
+ // Now add the external AA wrapper with a lambda which queries for the
+ // wrapper around our custom AA and adds it to the results.
+ PM.add(createExternalAAWrapperPass([](Pass &P, Function &, AAResults &AAR) {
+ if (auto *WrapperPass = P.getAnalysisIfAvailable<TestCustomAAWrapperPass>())
+ AAR.addAAResult(WrapperPass->getResult());
+ }));
+
+ // And run a pass that will make some alias queries. This will automatically
+ // trigger the rest of the alias analysis stack to be run. It is analagous to
+ // building a full pass pipeline with any of the existing pass manager
+ // builders.
+ PM.add(new AATestPass());
+ PM.run(*M);
+
+ // Finally, ensure that our custom AA was indeed queried.
+ EXPECT_TRUE(IsCustomAAQueried);
+}
+
+} // end anonymous namspace
diff --git a/gnu/llvm/unittests/Analysis/CFGTest.cpp b/gnu/llvm/unittests/Analysis/CFGTest.cpp
new file mode 100644
index 00000000000..44f0fe681df
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/CFGTest.cpp
@@ -0,0 +1,387 @@
+//===- CFGTest.cpp - CFG tests --------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CFG.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// This fixture assists in running the isPotentiallyReachable utility four ways
+// and ensuring it produces the correct answer each time.
+class IsPotentiallyReachableTest : public testing::Test {
+protected:
+ void ParseAssembly(const char *Assembly) {
+ SMDiagnostic Error;
+ M = parseAssemblyString(Assembly, Error, getGlobalContext());
+
+ std::string errMsg;
+ raw_string_ostream os(errMsg);
+ Error.print("", os);
+
+ // A failure here means that the test itself is buggy.
+ if (!M)
+ report_fatal_error(os.str().c_str());
+
+ Function *F = M->getFunction("test");
+ if (F == nullptr)
+ report_fatal_error("Test must have a function named @test");
+
+ A = B = nullptr;
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if (I->hasName()) {
+ if (I->getName() == "A")
+ A = &*I;
+ else if (I->getName() == "B")
+ B = &*I;
+ }
+ }
+ if (A == nullptr)
+ report_fatal_error("@test must have an instruction %A");
+ if (B == nullptr)
+ report_fatal_error("@test must have an instruction %B");
+ }
+
+ void ExpectPath(bool ExpectedResult) {
+ static char ID;
+ class IsPotentiallyReachableTestPass : public FunctionPass {
+ public:
+ IsPotentiallyReachableTestPass(bool ExpectedResult,
+ Instruction *A, Instruction *B)
+ : FunctionPass(ID), ExpectedResult(ExpectedResult), A(A), B(B) {}
+
+ static int initialize() {
+ PassInfo *PI = new PassInfo("isPotentiallyReachable testing pass",
+ "", &ID, nullptr, true, true);
+ PassRegistry::getPassRegistry()->registerPass(*PI, false);
+ initializeLoopInfoWrapperPassPass(*PassRegistry::getPassRegistry());
+ initializeDominatorTreeWrapperPassPass(
+ *PassRegistry::getPassRegistry());
+ return 0;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ AU.addRequired<LoopInfoWrapperPass>();
+ AU.addRequired<DominatorTreeWrapperPass>();
+ }
+
+ bool runOnFunction(Function &F) override {
+ if (!F.hasName() || F.getName() != "test")
+ return false;
+
+ LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
+ DominatorTree *DT =
+ &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+ EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, nullptr),
+ ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, DT, nullptr), ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, nullptr, LI), ExpectedResult);
+ EXPECT_EQ(isPotentiallyReachable(A, B, DT, LI), ExpectedResult);
+ return false;
+ }
+ bool ExpectedResult;
+ Instruction *A, *B;
+ };
+
+ static int initialize = IsPotentiallyReachableTestPass::initialize();
+ (void)initialize;
+
+ IsPotentiallyReachableTestPass *P =
+ new IsPotentiallyReachableTestPass(ExpectedResult, A, B);
+ legacy::PassManager PM;
+ PM.add(P);
+ PM.run(*M);
+ }
+
+ std::unique_ptr<Module> M;
+ Instruction *A, *B;
+};
+
+}
+
+TEST_F(IsPotentiallyReachableTest, SameBlockNoPath) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " bitcast i8 undef to i8\n"
+ " %B = bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " %A = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}\n");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, SameBlockPath) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}\n");
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, SameBlockNoLoop) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %middle\n"
+ "middle:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " bitcast i8 undef to i8\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br label %nextblock\n"
+ "nextblock:\n"
+ " ret void\n"
+ "}\n");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, StraightNoPath) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " br label %exit\n"
+ "exit:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, StraightPath) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br label %exit\n"
+ "exit:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, DestUnreachable) {
+ ParseAssembly(
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %midblock\n"
+ "midblock:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "unreachable:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " br label %midblock\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, BranchToReturn) {
+ ParseAssembly(
+ "define void @test(i1 %x) {\n"
+ "entry:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br i1 %x, label %block1, label %block2\n"
+ "block1:\n"
+ " ret void\n"
+ "block2:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, SimpleLoop1) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %loop\n"
+ "loop:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " %A = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %loop, label %exit\n"
+ "exit:\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, SimpleLoop2) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " br label %loop\n"
+ "loop:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %loop, label %exit\n"
+ "exit:\n"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, SimpleLoop3) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %loop\n"
+ "loop:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %loop, label %exit\n"
+ "exit:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+
+TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther1) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %loop1\n"
+ "loop1:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %loop1, label %loop1exit\n"
+ "loop1exit:\n"
+ " br label %loop2\n"
+ "loop2:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " %y = call i1 @switch()\n"
+ " br i1 %x, label %loop2, label %loop2exit\n"
+ "loop2exit:"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOther2) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %loop1\n"
+ "loop1:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %loop1, label %loop1exit\n"
+ "loop1exit:\n"
+ " br label %loop2\n"
+ "loop2:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " %y = call i1 @switch()\n"
+ " br i1 %x, label %loop2, label %loop2exit\n"
+ "loop2exit:"
+ " ret void\n"
+ "}");
+ ExpectPath(false);
+}
+
+TEST_F(IsPotentiallyReachableTest, OneLoopAfterTheOtherInsideAThirdLoop) {
+ ParseAssembly(
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %outerloop3\n"
+ "outerloop3:\n"
+ " br label %innerloop1\n"
+ "innerloop1:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %innerloop1, label %innerloop1exit\n"
+ "innerloop1exit:\n"
+ " br label %innerloop2\n"
+ "innerloop2:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " %y = call i1 @switch()\n"
+ " br i1 %x, label %innerloop2, label %innerloop2exit\n"
+ "innerloop2exit:"
+ " ;; In outer loop3 now.\n"
+ " %z = call i1 @switch()\n"
+ " br i1 %z, label %outerloop3, label %exit\n"
+ "exit:\n"
+ " ret void\n"
+ "}");
+ ExpectPath(true);
+}
+
+static const char *BranchInsideLoopIR =
+ "declare i1 @switch()\n"
+ "\n"
+ "define void @test() {\n"
+ "entry:\n"
+ " br label %loop\n"
+ "loop:\n"
+ " %x = call i1 @switch()\n"
+ " br i1 %x, label %nextloopblock, label %exit\n"
+ "nextloopblock:\n"
+ " %y = call i1 @switch()\n"
+ " br i1 %y, label %left, label %right\n"
+ "left:\n"
+ " %A = bitcast i8 undef to i8\n"
+ " br label %loop\n"
+ "right:\n"
+ " %B = bitcast i8 undef to i8\n"
+ " br label %loop\n"
+ "exit:\n"
+ " ret void\n"
+ "}";
+
+TEST_F(IsPotentiallyReachableTest, BranchInsideLoop) {
+ ParseAssembly(BranchInsideLoopIR);
+ ExpectPath(true);
+}
+
+TEST_F(IsPotentiallyReachableTest, ModifyTest) {
+ ParseAssembly(BranchInsideLoopIR);
+
+ succ_iterator S = succ_begin(&*++M->getFunction("test")->begin());
+ BasicBlock *OldBB = S[0];
+ S[0] = S[1];
+ ExpectPath(false);
+ S[0] = OldBB;
+ ExpectPath(true);
+}
diff --git a/gnu/llvm/unittests/Analysis/CMakeLists.txt b/gnu/llvm/unittests/Analysis/CMakeLists.txt
new file mode 100644
index 00000000000..06560cf14d4
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ AsmParser
+ Core
+ Support
+ )
+
+add_llvm_unittest(AnalysisTests
+ AliasAnalysisTest.cpp
+ CallGraphTest.cpp
+ CFGTest.cpp
+ LazyCallGraphTest.cpp
+ ScalarEvolutionTest.cpp
+ MixedTBAATest.cpp
+ ValueTrackingTest.cpp
+ )
diff --git a/gnu/llvm/unittests/Analysis/CallGraphTest.cpp b/gnu/llvm/unittests/Analysis/CallGraphTest.cpp
new file mode 100644
index 00000000000..777907a55b1
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/CallGraphTest.cpp
@@ -0,0 +1,59 @@
+//=======- CallGraphTest.cpp - Unit tests for the CG analysis -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+template <typename Ty> void canSpecializeGraphTraitsIterators(Ty *G) {
+ typedef typename GraphTraits<Ty *>::NodeType NodeTy;
+
+ auto I = GraphTraits<Ty *>::nodes_begin(G);
+ auto E = GraphTraits<Ty *>::nodes_end(G);
+ auto X = ++I;
+
+ // Should be able to iterate over all nodes of the graph.
+ static_assert(std::is_same<decltype(*I), NodeTy &>::value,
+ "Node type does not match");
+ static_assert(std::is_same<decltype(*X), NodeTy &>::value,
+ "Node type does not match");
+ static_assert(std::is_same<decltype(*E), NodeTy &>::value,
+ "Node type does not match");
+
+ NodeTy *N = GraphTraits<Ty *>::getEntryNode(G);
+
+ auto S = GraphTraits<NodeTy *>::child_begin(N);
+ auto F = GraphTraits<NodeTy *>::child_end(N);
+
+ // Should be able to iterate over immediate successors of a node.
+ static_assert(std::is_same<decltype(*S), NodeTy *>::value,
+ "Node type does not match");
+ static_assert(std::is_same<decltype(*F), NodeTy *>::value,
+ "Node type does not match");
+}
+
+TEST(CallGraphTest, GraphTraitsSpecialization) {
+ Module M("", getGlobalContext());
+ CallGraph CG(M);
+
+ canSpecializeGraphTraitsIterators(&CG);
+}
+
+TEST(CallGraphTest, GraphTraitsConstSpecialization) {
+ Module M("", getGlobalContext());
+ CallGraph CG(M);
+
+ canSpecializeGraphTraitsIterators(const_cast<const CallGraph *>(&CG));
+}
+}
diff --git a/gnu/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/gnu/llvm/unittests/Analysis/LazyCallGraphTest.cpp
new file mode 100644
index 00000000000..6caccb89239
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/LazyCallGraphTest.cpp
@@ -0,0 +1,720 @@
+//===- LazyCallGraphTest.cpp - Unit tests for the lazy CG analysis --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/LazyCallGraph.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+std::unique_ptr<Module> parseAssembly(const char *Assembly) {
+ SMDiagnostic Error;
+ std::unique_ptr<Module> M =
+ parseAssemblyString(Assembly, Error, getGlobalContext());
+
+ std::string ErrMsg;
+ raw_string_ostream OS(ErrMsg);
+ Error.print("", OS);
+
+ // A failure here means that the test itself is buggy.
+ if (!M)
+ report_fatal_error(OS.str().c_str());
+
+ return M;
+}
+
+/*
+ IR forming a call graph with a diamond of triangle-shaped SCCs:
+
+ d1
+ / \
+ d3--d2
+ / \
+ b1 c1
+ / \ / \
+ b3--b2 c3--c2
+ \ /
+ a1
+ / \
+ a3--a2
+
+ All call edges go up between SCCs, and clockwise around the SCC.
+ */
+static const char DiamondOfTriangles[] =
+ "define void @a1() {\n"
+ "entry:\n"
+ " call void @a2()\n"
+ " call void @b2()\n"
+ " call void @c3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @a2() {\n"
+ "entry:\n"
+ " call void @a3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @a3() {\n"
+ "entry:\n"
+ " call void @a1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b1() {\n"
+ "entry:\n"
+ " call void @b2()\n"
+ " call void @d3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b2() {\n"
+ "entry:\n"
+ " call void @b3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b3() {\n"
+ "entry:\n"
+ " call void @b1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c1() {\n"
+ "entry:\n"
+ " call void @c2()\n"
+ " call void @d2()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c2() {\n"
+ "entry:\n"
+ " call void @c3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c3() {\n"
+ "entry:\n"
+ " call void @c1()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d1() {\n"
+ "entry:\n"
+ " call void @d2()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d2() {\n"
+ "entry:\n"
+ " call void @d3()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d3() {\n"
+ "entry:\n"
+ " call void @d1()\n"
+ " ret void\n"
+ "}\n";
+
+TEST(LazyCallGraphTest, BasicGraphFormation) {
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // The order of the entry nodes should be stable w.r.t. the source order of
+ // the IR, and everything in our module is an entry node, so just directly
+ // build variables for each node.
+ auto I = CG.begin();
+ LazyCallGraph::Node &A1 = *I++;
+ EXPECT_EQ("a1", A1.getFunction().getName());
+ LazyCallGraph::Node &A2 = *I++;
+ EXPECT_EQ("a2", A2.getFunction().getName());
+ LazyCallGraph::Node &A3 = *I++;
+ EXPECT_EQ("a3", A3.getFunction().getName());
+ LazyCallGraph::Node &B1 = *I++;
+ EXPECT_EQ("b1", B1.getFunction().getName());
+ LazyCallGraph::Node &B2 = *I++;
+ EXPECT_EQ("b2", B2.getFunction().getName());
+ LazyCallGraph::Node &B3 = *I++;
+ EXPECT_EQ("b3", B3.getFunction().getName());
+ LazyCallGraph::Node &C1 = *I++;
+ EXPECT_EQ("c1", C1.getFunction().getName());
+ LazyCallGraph::Node &C2 = *I++;
+ EXPECT_EQ("c2", C2.getFunction().getName());
+ LazyCallGraph::Node &C3 = *I++;
+ EXPECT_EQ("c3", C3.getFunction().getName());
+ LazyCallGraph::Node &D1 = *I++;
+ EXPECT_EQ("d1", D1.getFunction().getName());
+ LazyCallGraph::Node &D2 = *I++;
+ EXPECT_EQ("d2", D2.getFunction().getName());
+ LazyCallGraph::Node &D3 = *I++;
+ EXPECT_EQ("d3", D3.getFunction().getName());
+ EXPECT_EQ(CG.end(), I);
+
+ // Build vectors and sort them for the rest of the assertions to make them
+ // independent of order.
+ std::vector<std::string> Nodes;
+
+ for (LazyCallGraph::Node &N : A1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("a2", Nodes[0]);
+ EXPECT_EQ("b2", Nodes[1]);
+ EXPECT_EQ("c3", Nodes[2]);
+ Nodes.clear();
+
+ EXPECT_EQ(A2.end(), std::next(A2.begin()));
+ EXPECT_EQ("a3", A2.begin()->getFunction().getName());
+ EXPECT_EQ(A3.end(), std::next(A3.begin()));
+ EXPECT_EQ("a1", A3.begin()->getFunction().getName());
+
+ for (LazyCallGraph::Node &N : B1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("b2", Nodes[0]);
+ EXPECT_EQ("d3", Nodes[1]);
+ Nodes.clear();
+
+ EXPECT_EQ(B2.end(), std::next(B2.begin()));
+ EXPECT_EQ("b3", B2.begin()->getFunction().getName());
+ EXPECT_EQ(B3.end(), std::next(B3.begin()));
+ EXPECT_EQ("b1", B3.begin()->getFunction().getName());
+
+ for (LazyCallGraph::Node &N : C1)
+ Nodes.push_back(N.getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ("c2", Nodes[0]);
+ EXPECT_EQ("d2", Nodes[1]);
+ Nodes.clear();
+
+ EXPECT_EQ(C2.end(), std::next(C2.begin()));
+ EXPECT_EQ("c3", C2.begin()->getFunction().getName());
+ EXPECT_EQ(C3.end(), std::next(C3.begin()));
+ EXPECT_EQ("c1", C3.begin()->getFunction().getName());
+
+ EXPECT_EQ(D1.end(), std::next(D1.begin()));
+ EXPECT_EQ("d2", D1.begin()->getFunction().getName());
+ EXPECT_EQ(D2.end(), std::next(D2.begin()));
+ EXPECT_EQ("d3", D2.begin()->getFunction().getName());
+ EXPECT_EQ(D3.end(), std::next(D3.begin()));
+ EXPECT_EQ("d1", D3.begin()->getFunction().getName());
+
+ // Now lets look at the SCCs.
+ auto SCCI = CG.postorder_scc_begin();
+
+ LazyCallGraph::SCC &D = *SCCI++;
+ for (LazyCallGraph::Node *N : D)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("d1", Nodes[0]);
+ EXPECT_EQ("d2", Nodes[1]);
+ EXPECT_EQ("d3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_FALSE(D.isParentOf(D));
+ EXPECT_FALSE(D.isChildOf(D));
+ EXPECT_FALSE(D.isAncestorOf(D));
+ EXPECT_FALSE(D.isDescendantOf(D));
+
+ LazyCallGraph::SCC &C = *SCCI++;
+ for (LazyCallGraph::Node *N : C)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("c1", Nodes[0]);
+ EXPECT_EQ("c2", Nodes[1]);
+ EXPECT_EQ("c3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(C.isParentOf(D));
+ EXPECT_FALSE(C.isChildOf(D));
+ EXPECT_TRUE(C.isAncestorOf(D));
+ EXPECT_FALSE(C.isDescendantOf(D));
+
+ LazyCallGraph::SCC &B = *SCCI++;
+ for (LazyCallGraph::Node *N : B)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("b1", Nodes[0]);
+ EXPECT_EQ("b2", Nodes[1]);
+ EXPECT_EQ("b3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(B.isParentOf(D));
+ EXPECT_FALSE(B.isChildOf(D));
+ EXPECT_TRUE(B.isAncestorOf(D));
+ EXPECT_FALSE(B.isDescendantOf(D));
+ EXPECT_FALSE(B.isAncestorOf(C));
+ EXPECT_FALSE(C.isAncestorOf(B));
+
+ LazyCallGraph::SCC &A = *SCCI++;
+ for (LazyCallGraph::Node *N : A)
+ Nodes.push_back(N->getFunction().getName());
+ std::sort(Nodes.begin(), Nodes.end());
+ EXPECT_EQ(3u, Nodes.size());
+ EXPECT_EQ("a1", Nodes[0]);
+ EXPECT_EQ("a2", Nodes[1]);
+ EXPECT_EQ("a3", Nodes[2]);
+ Nodes.clear();
+ EXPECT_TRUE(A.isParentOf(B));
+ EXPECT_TRUE(A.isParentOf(C));
+ EXPECT_FALSE(A.isParentOf(D));
+ EXPECT_TRUE(A.isAncestorOf(B));
+ EXPECT_TRUE(A.isAncestorOf(C));
+ EXPECT_TRUE(A.isAncestorOf(D));
+
+ EXPECT_EQ(CG.postorder_scc_end(), SCCI);
+}
+
+static Function &lookupFunction(Module &M, StringRef Name) {
+ for (Function &F : M)
+ if (F.getName() == Name)
+ return F;
+ report_fatal_error("Couldn't find function!");
+}
+
+TEST(LazyCallGraphTest, BasicGraphMutation) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ LazyCallGraph::Node &A = CG.get(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = CG.get(lookupFunction(*M, "b"));
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(0, std::distance(B.begin(), B.end()));
+
+ CG.insertEdge(B, lookupFunction(*M, "c"));
+ EXPECT_EQ(1, std::distance(B.begin(), B.end()));
+ LazyCallGraph::Node &C = *B.begin();
+ EXPECT_EQ(0, std::distance(C.begin(), C.end()));
+
+ CG.insertEdge(C, B.getFunction());
+ EXPECT_EQ(1, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&B, &*C.begin());
+
+ CG.insertEdge(C, C.getFunction());
+ EXPECT_EQ(2, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&B, &*C.begin());
+ EXPECT_EQ(&C, &*std::next(C.begin()));
+
+ CG.removeEdge(C, B.getFunction());
+ EXPECT_EQ(1, std::distance(C.begin(), C.end()));
+ EXPECT_EQ(&C, &*C.begin());
+
+ CG.removeEdge(C, C.getFunction());
+ EXPECT_EQ(0, std::distance(C.begin(), C.end()));
+
+ CG.removeEdge(B, C.getFunction());
+ EXPECT_EQ(0, std::distance(B.begin(), B.end()));
+}
+
+TEST(LazyCallGraphTest, MultiArmSCC) {
+ // Two interlocking cycles. The really useful thing about this SCC is that it
+ // will require Tarjan's DFS to backtrack and finish processing all of the
+ // children of each node in the SCC.
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d() {\n"
+ "entry:\n"
+ " call void @e()\n"
+ " ret void\n"
+ "}\n"
+ "define void @e() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
+ LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
+ LazyCallGraph::Node &E = *CG.lookup(lookupFunction(*M, "e"));
+ EXPECT_EQ(&SCC, CG.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG.lookupSCC(C));
+ EXPECT_EQ(&SCC, CG.lookupSCC(D));
+ EXPECT_EQ(&SCC, CG.lookupSCC(E));
+}
+
+TEST(LazyCallGraphTest, OutgoingSCCEdgeInsertion) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @d()\n"
+ " ret void\n"
+ "}\n"
+ "define void @d() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::Node &C = *CG.lookup(lookupFunction(*M, "c"));
+ LazyCallGraph::Node &D = *CG.lookup(lookupFunction(*M, "d"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
+ LazyCallGraph::SCC &CC = *CG.lookupSCC(C);
+ LazyCallGraph::SCC &DC = *CG.lookupSCC(D);
+ EXPECT_TRUE(AC.isAncestorOf(BC));
+ EXPECT_TRUE(AC.isAncestorOf(CC));
+ EXPECT_TRUE(AC.isAncestorOf(DC));
+ EXPECT_TRUE(DC.isDescendantOf(AC));
+ EXPECT_TRUE(DC.isDescendantOf(BC));
+ EXPECT_TRUE(DC.isDescendantOf(CC));
+
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ AC.insertOutgoingEdge(A, D);
+ EXPECT_EQ(3, std::distance(A.begin(), A.end()));
+ EXPECT_TRUE(AC.isParentOf(DC));
+ EXPECT_EQ(&AC, CG.lookupSCC(A));
+ EXPECT_EQ(&BC, CG.lookupSCC(B));
+ EXPECT_EQ(&CC, CG.lookupSCC(C));
+ EXPECT_EQ(&DC, CG.lookupSCC(D));
+}
+
+TEST(LazyCallGraphTest, IncomingSCCEdgeInsertion) {
+ // We want to ensure we can add edges even across complex diamond graphs, so
+ // we use the diamond of triangles graph defined above. The ascii diagram is
+ // repeated here for easy reference.
+ //
+ // d1 |
+ // / \ |
+ // d3--d2 |
+ // / \ |
+ // b1 c1 |
+ // / \ / \ |
+ // b3--b2 c3--c2 |
+ // \ / |
+ // a1 |
+ // / \ |
+ // a3--a2 |
+ //
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A1 = *CG.lookup(lookupFunction(*M, "a1"));
+ LazyCallGraph::Node &A2 = *CG.lookup(lookupFunction(*M, "a2"));
+ LazyCallGraph::Node &A3 = *CG.lookup(lookupFunction(*M, "a3"));
+ LazyCallGraph::Node &B1 = *CG.lookup(lookupFunction(*M, "b1"));
+ LazyCallGraph::Node &B2 = *CG.lookup(lookupFunction(*M, "b2"));
+ LazyCallGraph::Node &B3 = *CG.lookup(lookupFunction(*M, "b3"));
+ LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
+ LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
+ LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
+ LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
+ LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
+ LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A1);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B1);
+ LazyCallGraph::SCC &CC = *CG.lookupSCC(C1);
+ LazyCallGraph::SCC &DC = *CG.lookupSCC(D1);
+ ASSERT_EQ(&AC, CG.lookupSCC(A2));
+ ASSERT_EQ(&AC, CG.lookupSCC(A3));
+ ASSERT_EQ(&BC, CG.lookupSCC(B2));
+ ASSERT_EQ(&BC, CG.lookupSCC(B3));
+ ASSERT_EQ(&CC, CG.lookupSCC(C2));
+ ASSERT_EQ(&CC, CG.lookupSCC(C3));
+ ASSERT_EQ(&DC, CG.lookupSCC(D2));
+ ASSERT_EQ(&DC, CG.lookupSCC(D3));
+ ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
+
+ // Add an edge to make the graph:
+ //
+ // d1 |
+ // / \ |
+ // d3--d2---. |
+ // / \ | |
+ // b1 c1 | |
+ // / \ / \ / |
+ // b3--b2 c3--c2 |
+ // \ / |
+ // a1 |
+ // / \ |
+ // a3--a2 |
+ CC.insertIncomingEdge(D2, C2);
+ // Make sure we connected the nodes.
+ EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
+
+ // Make sure we have the correct nodes in the SCC sets.
+ EXPECT_EQ(&AC, CG.lookupSCC(A1));
+ EXPECT_EQ(&AC, CG.lookupSCC(A2));
+ EXPECT_EQ(&AC, CG.lookupSCC(A3));
+ EXPECT_EQ(&BC, CG.lookupSCC(B1));
+ EXPECT_EQ(&BC, CG.lookupSCC(B2));
+ EXPECT_EQ(&BC, CG.lookupSCC(B3));
+ EXPECT_EQ(&CC, CG.lookupSCC(C1));
+ EXPECT_EQ(&CC, CG.lookupSCC(C2));
+ EXPECT_EQ(&CC, CG.lookupSCC(C3));
+ EXPECT_EQ(&CC, CG.lookupSCC(D1));
+ EXPECT_EQ(&CC, CG.lookupSCC(D2));
+ EXPECT_EQ(&CC, CG.lookupSCC(D3));
+
+ // And that ancestry tests have been updated.
+ EXPECT_TRUE(AC.isParentOf(BC));
+ EXPECT_TRUE(AC.isParentOf(CC));
+ EXPECT_FALSE(AC.isAncestorOf(DC));
+ EXPECT_FALSE(BC.isAncestorOf(DC));
+ EXPECT_FALSE(CC.isAncestorOf(DC));
+}
+
+TEST(LazyCallGraphTest, IncomingSCCEdgeInsertionMidTraversal) {
+ // This is the same fundamental test as the previous, but we perform it
+ // having only partially walked the SCCs of the graph.
+ std::unique_ptr<Module> M = parseAssembly(DiamondOfTriangles);
+ LazyCallGraph CG(*M);
+
+ // Walk the SCCs until we find the one containing 'c1'.
+ auto SCCI = CG.postorder_scc_begin(), SCCE = CG.postorder_scc_end();
+ ASSERT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &DC = *SCCI;
+ ASSERT_NE(&DC, nullptr);
+ ++SCCI;
+ ASSERT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &CC = *SCCI;
+ ASSERT_NE(&CC, nullptr);
+
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a1")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a2")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "a3")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b1")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b2")));
+ ASSERT_EQ(nullptr, CG.lookup(lookupFunction(*M, "b3")));
+ LazyCallGraph::Node &C1 = *CG.lookup(lookupFunction(*M, "c1"));
+ LazyCallGraph::Node &C2 = *CG.lookup(lookupFunction(*M, "c2"));
+ LazyCallGraph::Node &C3 = *CG.lookup(lookupFunction(*M, "c3"));
+ LazyCallGraph::Node &D1 = *CG.lookup(lookupFunction(*M, "d1"));
+ LazyCallGraph::Node &D2 = *CG.lookup(lookupFunction(*M, "d2"));
+ LazyCallGraph::Node &D3 = *CG.lookup(lookupFunction(*M, "d3"));
+ ASSERT_EQ(&CC, CG.lookupSCC(C1));
+ ASSERT_EQ(&CC, CG.lookupSCC(C2));
+ ASSERT_EQ(&CC, CG.lookupSCC(C3));
+ ASSERT_EQ(&DC, CG.lookupSCC(D1));
+ ASSERT_EQ(&DC, CG.lookupSCC(D2));
+ ASSERT_EQ(&DC, CG.lookupSCC(D3));
+ ASSERT_EQ(1, std::distance(D2.begin(), D2.end()));
+
+ CC.insertIncomingEdge(D2, C2);
+ EXPECT_EQ(2, std::distance(D2.begin(), D2.end()));
+
+ // Make sure we have the correct nodes in the SCC sets.
+ EXPECT_EQ(&CC, CG.lookupSCC(C1));
+ EXPECT_EQ(&CC, CG.lookupSCC(C2));
+ EXPECT_EQ(&CC, CG.lookupSCC(C3));
+ EXPECT_EQ(&CC, CG.lookupSCC(D1));
+ EXPECT_EQ(&CC, CG.lookupSCC(D2));
+ EXPECT_EQ(&CC, CG.lookupSCC(D3));
+
+ // Check that we can form the last two SCCs now in a coherent way.
+ ++SCCI;
+ EXPECT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &BC = *SCCI;
+ EXPECT_NE(&BC, nullptr);
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b1"))));
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b2"))));
+ EXPECT_EQ(&BC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "b3"))));
+ ++SCCI;
+ EXPECT_NE(SCCI, SCCE);
+ LazyCallGraph::SCC &AC = *SCCI;
+ EXPECT_NE(&AC, nullptr);
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a1"))));
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a2"))));
+ EXPECT_EQ(&AC, CG.lookupSCC(*CG.lookup(lookupFunction(*M, "a3"))));
+ ++SCCI;
+ EXPECT_EQ(SCCI, SCCE);
+}
+
+TEST(LazyCallGraphTest, InterSCCEdgeRemoval) {
+ std::unique_ptr<Module> M = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG(*M);
+
+ // Force the graph to be fully expanded.
+ for (LazyCallGraph::SCC &C : CG.postorder_sccs())
+ (void)C;
+
+ LazyCallGraph::Node &A = *CG.lookup(lookupFunction(*M, "a"));
+ LazyCallGraph::Node &B = *CG.lookup(lookupFunction(*M, "b"));
+ LazyCallGraph::SCC &AC = *CG.lookupSCC(A);
+ LazyCallGraph::SCC &BC = *CG.lookupSCC(B);
+
+ EXPECT_EQ("b", A.begin()->getFunction().getName());
+ EXPECT_EQ(B.end(), B.begin());
+ EXPECT_EQ(&AC, &*BC.parent_begin());
+
+ AC.removeInterSCCEdge(A, B);
+
+ EXPECT_EQ(A.end(), A.begin());
+ EXPECT_EQ(B.end(), B.begin());
+ EXPECT_EQ(BC.parent_end(), BC.parent_begin());
+}
+
+TEST(LazyCallGraphTest, IntraSCCEdgeInsertion) {
+ std::unique_ptr<Module> M1 = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @b()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG1(*M1);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG1.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
+ LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
+ LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Insert an edge from 'a' to 'c'. Nothing changes about the SCCs.
+ SCC.insertIntraSCCEdge(A, C);
+ EXPECT_EQ(2, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Insert a self edge from 'a' back to 'a'.
+ SCC.insertIntraSCCEdge(A, A);
+ EXPECT_EQ(3, std::distance(A.begin(), A.end()));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+}
+
+TEST(LazyCallGraphTest, IntraSCCEdgeRemoval) {
+ // A nice fully connected (including self-edges) SCC.
+ std::unique_ptr<Module> M1 = parseAssembly(
+ "define void @a() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @b() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n"
+ "define void @c() {\n"
+ "entry:\n"
+ " call void @a()\n"
+ " call void @b()\n"
+ " call void @c()\n"
+ " ret void\n"
+ "}\n");
+ LazyCallGraph CG1(*M1);
+
+ // Force the graph to be fully expanded.
+ auto SCCI = CG1.postorder_scc_begin();
+ LazyCallGraph::SCC &SCC = *SCCI++;
+ EXPECT_EQ(CG1.postorder_scc_end(), SCCI);
+
+ LazyCallGraph::Node &A = *CG1.lookup(lookupFunction(*M1, "a"));
+ LazyCallGraph::Node &B = *CG1.lookup(lookupFunction(*M1, "b"));
+ LazyCallGraph::Node &C = *CG1.lookup(lookupFunction(*M1, "c"));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Remove the edge from b -> a, which should leave the 3 functions still in
+ // a single connected component because of a -> b -> c -> a.
+ SmallVector<LazyCallGraph::SCC *, 1> NewSCCs = SCC.removeIntraSCCEdge(B, A);
+ EXPECT_EQ(0u, NewSCCs.size());
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(B));
+ EXPECT_EQ(&SCC, CG1.lookupSCC(C));
+
+ // Remove the edge from c -> a, which should leave 'a' in the original SCC
+ // and form a new SCC for 'b' and 'c'.
+ NewSCCs = SCC.removeIntraSCCEdge(C, A);
+ EXPECT_EQ(1u, NewSCCs.size());
+ EXPECT_EQ(&SCC, CG1.lookupSCC(A));
+ EXPECT_EQ(1, std::distance(SCC.begin(), SCC.end()));
+ LazyCallGraph::SCC *SCC2 = CG1.lookupSCC(B);
+ EXPECT_EQ(SCC2, CG1.lookupSCC(C));
+ EXPECT_EQ(SCC2, NewSCCs[0]);
+}
+
+}
diff --git a/gnu/llvm/unittests/Analysis/Makefile b/gnu/llvm/unittests/Analysis/Makefile
new file mode 100644
index 00000000000..527f4525e87
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Analysis/Makefile -------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = Analysis
+LINK_COMPONENTS := analysis asmparser
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Analysis/MixedTBAATest.cpp b/gnu/llvm/unittests/Analysis/MixedTBAATest.cpp
new file mode 100644
index 00000000000..d0cfa59f645
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/MixedTBAATest.cpp
@@ -0,0 +1,78 @@
+//===--- MixedTBAATest.cpp - Mixed TBAA 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/Analysis/TypeBasedAliasAnalysis.h"
+#include "llvm/Analysis/Passes.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+class MixedTBAATest : public testing::Test {
+protected:
+ MixedTBAATest() : M("MixedTBAATest", C), MD(C) {}
+
+ LLVMContext C;
+ Module M;
+ MDBuilder MD;
+ legacy::PassManager PM;
+};
+
+TEST_F(MixedTBAATest, MixedTBAA) {
+ // Setup function.
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C),
+ std::vector<Type *>(), false);
+ auto *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ auto *BB = BasicBlock::Create(C, "entry", F);
+ auto IntType = Type::getInt32Ty(C);
+ auto PtrType = Type::getInt32PtrTy(C);
+ auto *Value = ConstantInt::get(IntType, 42);
+ auto *Addr = ConstantPointerNull::get(PtrType);
+
+ auto *Store1 = new StoreInst(Value, Addr, BB);
+ auto *Store2 = new StoreInst(Value, Addr, BB);
+ ReturnInst::Create(C, nullptr, BB);
+
+ // New TBAA metadata
+ {
+ auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
+ auto MD1 = MD.createTBAAScalarTypeNode("omnipotent char", RootMD);
+ auto MD2 = MD.createTBAAScalarTypeNode("int", MD1);
+ auto MD3 = MD.createTBAAStructTagNode(MD2, MD2, 0);
+ Store2->setMetadata(LLVMContext::MD_tbaa, MD3);
+ }
+
+ // Old TBAA metadata
+ {
+ auto RootMD = MD.createTBAARoot("Simple C/C++ TBAA");
+ auto MD1 = MD.createTBAANode("omnipotent char", RootMD);
+ auto MD2 = MD.createTBAANode("int", MD1);
+ Store1->setMetadata(LLVMContext::MD_tbaa, MD2);
+ }
+
+ // Run the TBAA eval pass on a mixture of path-aware and non-path-aware TBAA.
+ // The order of the metadata (path-aware vs non-path-aware) is important,
+ // because the AA eval pass only runs one test per store-pair.
+ const char* args[] = { "MixedTBAATest", "-evaluate-aa-metadata" };
+ cl::ParseCommandLineOptions(sizeof(args) / sizeof(const char*), args);
+ PM.add(createTypeBasedAAWrapperPass());
+ PM.add(createAAEvalPass());
+ PM.run(M);
+}
+
+} // end anonymous namspace
+} // end llvm namespace
+
diff --git a/gnu/llvm/unittests/Analysis/ScalarEvolutionTest.cpp b/gnu/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
new file mode 100644
index 00000000000..938dafe6038
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/ScalarEvolutionTest.cpp
@@ -0,0 +1,241 @@
+//===- ScalarEvolutionsTest.cpp - ScalarEvolution 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/Analysis/ScalarEvolutionExpressions.h"
+#include "llvm/Analysis/AssumptionCache.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+// We use this fixture to ensure that we clean up ScalarEvolution before
+// deleting the PassManager.
+class ScalarEvolutionsTest : public testing::Test {
+protected:
+ LLVMContext Context;
+ Module M;
+ TargetLibraryInfoImpl TLII;
+ TargetLibraryInfo TLI;
+
+ std::unique_ptr<AssumptionCache> AC;
+ std::unique_ptr<DominatorTree> DT;
+ std::unique_ptr<LoopInfo> LI;
+
+ ScalarEvolutionsTest() : M("", Context), TLII(), TLI(TLII) {}
+
+ ScalarEvolution buildSE(Function &F) {
+ AC.reset(new AssumptionCache(F));
+ DT.reset(new DominatorTree(F));
+ LI.reset(new LoopInfo(*DT));
+ return ScalarEvolution(F, TLI, *AC, *DT, *LI);
+ }
+};
+
+TEST_F(ScalarEvolutionsTest, SCEVUnknownRAUW) {
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context),
+ std::vector<Type *>(), false);
+ Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+ ReturnInst::Create(Context, nullptr, BB);
+
+ Type *Ty = Type::getInt1Ty(Context);
+ Constant *Init = Constant::getNullValue(Ty);
+ Value *V0 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V0");
+ Value *V1 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V1");
+ Value *V2 = new GlobalVariable(M, Ty, false, GlobalValue::ExternalLinkage, Init, "V2");
+
+ ScalarEvolution SE = buildSE(*F);
+
+ const SCEV *S0 = SE.getSCEV(V0);
+ const SCEV *S1 = SE.getSCEV(V1);
+ const SCEV *S2 = SE.getSCEV(V2);
+
+ const SCEV *P0 = SE.getAddExpr(S0, S0);
+ const SCEV *P1 = SE.getAddExpr(S1, S1);
+ const SCEV *P2 = SE.getAddExpr(S2, S2);
+
+ const SCEVMulExpr *M0 = cast<SCEVMulExpr>(P0);
+ const SCEVMulExpr *M1 = cast<SCEVMulExpr>(P1);
+ const SCEVMulExpr *M2 = cast<SCEVMulExpr>(P2);
+
+ EXPECT_EQ(cast<SCEVConstant>(M0->getOperand(0))->getValue()->getZExtValue(),
+ 2u);
+ EXPECT_EQ(cast<SCEVConstant>(M1->getOperand(0))->getValue()->getZExtValue(),
+ 2u);
+ EXPECT_EQ(cast<SCEVConstant>(M2->getOperand(0))->getValue()->getZExtValue(),
+ 2u);
+
+ // Before the RAUWs, these are all pointing to separate values.
+ EXPECT_EQ(cast<SCEVUnknown>(M0->getOperand(1))->getValue(), V0);
+ EXPECT_EQ(cast<SCEVUnknown>(M1->getOperand(1))->getValue(), V1);
+ EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V2);
+
+ // Do some RAUWs.
+ V2->replaceAllUsesWith(V1);
+ V1->replaceAllUsesWith(V0);
+
+ // After the RAUWs, these should all be pointing to V0.
+ EXPECT_EQ(cast<SCEVUnknown>(M0->getOperand(1))->getValue(), V0);
+ EXPECT_EQ(cast<SCEVUnknown>(M1->getOperand(1))->getValue(), V0);
+ EXPECT_EQ(cast<SCEVUnknown>(M2->getOperand(1))->getValue(), V0);
+}
+
+TEST_F(ScalarEvolutionsTest, SCEVMultiplyAddRecs) {
+ Type *Ty = Type::getInt32Ty(Context);
+ SmallVector<Type *, 10> Types;
+ Types.append(10, Ty);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Context), Types, false);
+ Function *F = cast<Function>(M.getOrInsertFunction("f", FTy));
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", F);
+ ReturnInst::Create(Context, nullptr, BB);
+
+ ScalarEvolution SE = buildSE(*F);
+
+ // It's possible to produce an empty loop through the default constructor,
+ // but you can't add any blocks to it without a LoopInfo pass.
+ Loop L;
+ const_cast<std::vector<BasicBlock*>&>(L.getBlocks()).push_back(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ SmallVector<const SCEV *, 5> A;
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ A.push_back(SE.getSCEV(&*AI++));
+ const SCEV *A_rec = SE.getAddRecExpr(A, &L, SCEV::FlagAnyWrap);
+
+ SmallVector<const SCEV *, 5> B;
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ B.push_back(SE.getSCEV(&*AI++));
+ const SCEV *B_rec = SE.getAddRecExpr(B, &L, SCEV::FlagAnyWrap);
+
+ /* Spot check that we perform this transformation:
+ {A0,+,A1,+,A2,+,A3,+,A4} * {B0,+,B1,+,B2,+,B3,+,B4} =
+ {A0*B0,+,
+ A1*B0 + A0*B1 + A1*B1,+,
+ A2*B0 + 2A1*B1 + A0*B2 + 2A2*B1 + 2A1*B2 + A2*B2,+,
+ A3*B0 + 3A2*B1 + 3A1*B2 + A0*B3 + 3A3*B1 + 6A2*B2 + 3A1*B3 + 3A3*B2 +
+ 3A2*B3 + A3*B3,+,
+ A4*B0 + 4A3*B1 + 6A2*B2 + 4A1*B3 + A0*B4 + 4A4*B1 + 12A3*B2 + 12A2*B3 +
+ 4A1*B4 + 6A4*B2 + 12A3*B3 + 6A2*B4 + 4A4*B3 + 4A3*B4 + A4*B4,+,
+ 5A4*B1 + 10A3*B2 + 10A2*B3 + 5A1*B4 + 20A4*B2 + 30A3*B3 + 20A2*B4 +
+ 30A4*B3 + 30A3*B4 + 20A4*B4,+,
+ 15A4*B2 + 20A3*B3 + 15A2*B4 + 60A4*B3 + 60A3*B4 + 90A4*B4,+,
+ 35A4*B3 + 35A3*B4 + 140A4*B4,+,
+ 70A4*B4}
+ */
+
+ const SCEVAddRecExpr *Product =
+ dyn_cast<SCEVAddRecExpr>(SE.getMulExpr(A_rec, B_rec));
+ ASSERT_TRUE(Product);
+ ASSERT_EQ(Product->getNumOperands(), 9u);
+
+ SmallVector<const SCEV *, 16> Sum;
+ Sum.push_back(SE.getMulExpr(A[0], B[0]));
+ EXPECT_EQ(Product->getOperand(0), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ // SCEV produces different an equal but different expression for these.
+ // Re-enable when PR11052 is fixed.
+#if 0
+ Sum.push_back(SE.getMulExpr(A[1], B[0]));
+ Sum.push_back(SE.getMulExpr(A[0], B[1]));
+ Sum.push_back(SE.getMulExpr(A[1], B[1]));
+ EXPECT_EQ(Product->getOperand(1), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[2], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[1], B[1]));
+ Sum.push_back(SE.getMulExpr(A[0], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[2], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 2), A[1], B[2]));
+ Sum.push_back(SE.getMulExpr(A[2], B[2]));
+ EXPECT_EQ(Product->getOperand(2), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[3], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[2], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[1], B[2]));
+ Sum.push_back(SE.getMulExpr(A[0], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[3], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[1], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 3), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(A[3], B[3]));
+ EXPECT_EQ(Product->getOperand(3), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(A[4], B[0]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[3], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[1], B[3]));
+ Sum.push_back(SE.getMulExpr(A[0], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[4], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[1], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 12), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 6), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 4), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(4), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 5), A[4], B[1]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 10), A[3], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 10), A[2], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 5), A[1], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 30), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(5), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 15), A[4], B[2]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 20), A[3], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 15), A[2], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 60), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 60), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 90), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(6), SE.getAddExpr(Sum));
+ Sum.clear();
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 35), A[4], B[3]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 35), A[3], B[4]));
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 140), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(7), SE.getAddExpr(Sum));
+ Sum.clear();
+#endif
+
+ Sum.push_back(SE.getMulExpr(SE.getConstant(Ty, 70), A[4], B[4]));
+ EXPECT_EQ(Product->getOperand(8), SE.getAddExpr(Sum));
+}
+
+} // end anonymous namespace
+} // end namespace llvm
diff --git a/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp b/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp
new file mode 100644
index 00000000000..3af856ea203
--- /dev/null
+++ b/gnu/llvm/unittests/Analysis/ValueTrackingTest.cpp
@@ -0,0 +1,189 @@
+//===- ValueTrackingTest.cpp - ValueTracking tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MatchSelectPatternTest : public testing::Test {
+protected:
+ void parseAssembly(const char *Assembly) {
+ SMDiagnostic Error;
+ M = parseAssemblyString(Assembly, Error, getGlobalContext());
+
+ std::string errMsg;
+ raw_string_ostream os(errMsg);
+ Error.print("", os);
+
+ // A failure here means that the test itself is buggy.
+ if (!M)
+ report_fatal_error(os.str());
+
+ Function *F = M->getFunction("test");
+ if (F == nullptr)
+ report_fatal_error("Test must have a function named @test");
+
+ A = nullptr;
+ for (inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ if (I->hasName()) {
+ if (I->getName() == "A")
+ A = &*I;
+ }
+ }
+ if (A == nullptr)
+ report_fatal_error("@test must have an instruction %A");
+ }
+
+ void expectPattern(const SelectPatternResult &P) {
+ Value *LHS, *RHS;
+ Instruction::CastOps CastOp;
+ SelectPatternResult R = matchSelectPattern(A, LHS, RHS, &CastOp);
+ EXPECT_EQ(P.Flavor, R.Flavor);
+ EXPECT_EQ(P.NaNBehavior, R.NaNBehavior);
+ EXPECT_EQ(P.Ordered, R.Ordered);
+ }
+
+ std::unique_ptr<Module> M;
+ Instruction *A, *B;
+};
+
+}
+
+TEST_F(MatchSelectPatternTest, SimpleFMin) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ult float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_NAN, false});
+}
+
+TEST_F(MatchSelectPatternTest, SimpleFMax) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ogt float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp olt float 5.0, %a\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, false});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax2) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp olt float %a, 5.0\n"
+ " %A = select i1 %1, float 5.0, float %a\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_NAN, false});
+}
+
+TEST_F(MatchSelectPatternTest, SwappedFMax3) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ult float %a, 5.0\n"
+ " %A = select i1 %1, float 5.0, float %a\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMAXNUM, SPNB_RETURNS_OTHER, true});
+}
+
+TEST_F(MatchSelectPatternTest, FastFMin) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp nnan olt float %a, 5.0\n"
+ " %A = select i1 %1, float %a, float 5.0\n"
+ " ret float %A\n"
+ "}\n");
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_ANY, false});
+}
+
+TEST_F(MatchSelectPatternTest, FMinConstantZero) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp ole float %a, 0.0\n"
+ " %A = select i1 %1, float %a, float 0.0\n"
+ " ret float %A\n"
+ "}\n");
+ // This shouldn't be matched, as %a could be -0.0.
+ expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, FMinConstantZeroNsz) {
+ parseAssembly(
+ "define float @test(float %a) {\n"
+ " %1 = fcmp nsz ole float %a, 0.0\n"
+ " %A = select i1 %1, float %a, float 0.0\n"
+ " ret float %A\n"
+ "}\n");
+ // But this should be, because we've ignored signed zeroes.
+ expectPattern({SPF_FMINNUM, SPNB_RETURNS_OTHER, true});
+}
+
+TEST_F(MatchSelectPatternTest, DoubleCastU) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp ult i8 %a, %b\n"
+ " %2 = zext i8 %a to i32\n"
+ " %3 = zext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // We should be able to look through the situation where we cast both operands
+ // to the select.
+ expectPattern({SPF_UMIN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, DoubleCastS) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp slt i8 %a, %b\n"
+ " %2 = sext i8 %a to i32\n"
+ " %3 = sext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // We should be able to look through the situation where we cast both operands
+ // to the select.
+ expectPattern({SPF_SMIN, SPNB_NA, false});
+}
+
+TEST_F(MatchSelectPatternTest, DoubleCastBad) {
+ parseAssembly(
+ "define i32 @test(i8 %a, i8 %b) {\n"
+ " %1 = icmp ult i8 %a, %b\n"
+ " %2 = zext i8 %a to i32\n"
+ " %3 = sext i8 %b to i32\n"
+ " %A = select i1 %1, i32 %2, i32 %3\n"
+ " ret i32 %A\n"
+ "}\n");
+ // The cast types here aren't the same, so we cannot match an UMIN.
+ expectPattern({SPF_UNKNOWN, SPNB_NA, false});
+}
diff --git a/gnu/llvm/unittests/AsmParser/AsmParserTest.cpp b/gnu/llvm/unittests/AsmParser/AsmParserTest.cpp
new file mode 100644
index 00000000000..4189310fda2
--- /dev/null
+++ b/gnu/llvm/unittests/AsmParser/AsmParserTest.cpp
@@ -0,0 +1,155 @@
+//===- llvm/unittest/AsmParser/AsmParserTest.cpp - asm parser unittests ---===//
+//
+// 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/AsmParser/Parser.h"
+#include "llvm/AsmParser/SlotMapping.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(AsmParserTest, NullTerminatedInput) {
+ LLVMContext &Ctx = getGlobalContext();
+ StringRef Source = "; Empty module \n";
+ SMDiagnostic Error;
+ auto Mod = parseAssemblyString(Source, Error, Ctx);
+
+ EXPECT_TRUE(Mod != nullptr);
+ EXPECT_TRUE(Error.getMessage().empty());
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+
+TEST(AsmParserTest, NonNullTerminatedInput) {
+ LLVMContext &Ctx = getGlobalContext();
+ StringRef Source = "; Empty module \n\1\2";
+ SMDiagnostic Error;
+ std::unique_ptr<Module> Mod;
+ EXPECT_DEATH(Mod = parseAssemblyString(Source.substr(0, Source.size() - 2),
+ Error, Ctx),
+ "Buffer is not null terminated!");
+}
+
+#endif
+#endif
+
+TEST(AsmParserTest, SlotMappingTest) {
+ LLVMContext &Ctx = getGlobalContext();
+ StringRef Source = "@0 = global i32 0\n !0 = !{}\n !42 = !{i32 42}";
+ SMDiagnostic Error;
+ SlotMapping Mapping;
+ auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);
+
+ EXPECT_TRUE(Mod != nullptr);
+ EXPECT_TRUE(Error.getMessage().empty());
+
+ ASSERT_EQ(Mapping.GlobalValues.size(), 1u);
+ EXPECT_TRUE(isa<GlobalVariable>(Mapping.GlobalValues[0]));
+
+ EXPECT_EQ(Mapping.MetadataNodes.size(), 2u);
+ EXPECT_EQ(Mapping.MetadataNodes.count(0), 1u);
+ EXPECT_EQ(Mapping.MetadataNodes.count(42), 1u);
+ EXPECT_EQ(Mapping.MetadataNodes.count(1), 0u);
+}
+
+TEST(AsmParserTest, TypeAndConstantValueParsing) {
+ LLVMContext &Ctx = getGlobalContext();
+ SMDiagnostic Error;
+ StringRef Source = "define void @test() {\n entry:\n ret void\n}";
+ auto Mod = parseAssemblyString(Source, Error, Ctx);
+ ASSERT_TRUE(Mod != nullptr);
+ auto &M = *Mod;
+
+ const Value *V;
+ V = parseConstantValue("double 3.5", Error, M);
+ ASSERT_TRUE(V);
+ EXPECT_TRUE(V->getType()->isDoubleTy());
+ ASSERT_TRUE(isa<ConstantFP>(V));
+ EXPECT_TRUE(cast<ConstantFP>(V)->isExactlyValue(3.5));
+
+ V = parseConstantValue("i32 42", Error, M);
+ ASSERT_TRUE(V);
+ EXPECT_TRUE(V->getType()->isIntegerTy());
+ ASSERT_TRUE(isa<ConstantInt>(V));
+ EXPECT_TRUE(cast<ConstantInt>(V)->equalsInt(42));
+
+ V = parseConstantValue("<4 x i32> <i32 0, i32 1, i32 2, i32 3>", Error, M);
+ ASSERT_TRUE(V);
+ EXPECT_TRUE(V->getType()->isVectorTy());
+ ASSERT_TRUE(isa<ConstantDataVector>(V));
+
+ V = parseConstantValue("i32 add (i32 1, i32 2)", Error, M);
+ ASSERT_TRUE(V);
+ ASSERT_TRUE(isa<ConstantInt>(V));
+
+ V = parseConstantValue("i8* blockaddress(@test, %entry)", Error, M);
+ ASSERT_TRUE(V);
+ ASSERT_TRUE(isa<BlockAddress>(V));
+
+ V = parseConstantValue("i8** undef", Error, M);
+ ASSERT_TRUE(V);
+ ASSERT_TRUE(isa<UndefValue>(V));
+
+ EXPECT_FALSE(parseConstantValue("duble 3.25", Error, M));
+ EXPECT_EQ(Error.getMessage(), "expected type");
+
+ EXPECT_FALSE(parseConstantValue("i32 3.25", Error, M));
+ EXPECT_EQ(Error.getMessage(), "floating point constant invalid for type");
+
+ EXPECT_FALSE(parseConstantValue("i32* @foo", Error, M));
+ EXPECT_EQ(Error.getMessage(), "expected a constant value");
+
+ EXPECT_FALSE(parseConstantValue("i32 3, ", Error, M));
+ EXPECT_EQ(Error.getMessage(), "expected end of string");
+}
+
+TEST(AsmParserTest, TypeAndConstantValueWithSlotMappingParsing) {
+ LLVMContext &Ctx = getGlobalContext();
+ SMDiagnostic Error;
+ StringRef Source =
+ "%st = type { i32, i32 }\n"
+ "@v = common global [50 x %st] zeroinitializer, align 16\n"
+ "%0 = type { i32, i32, i32, i32 }\n"
+ "@g = common global [50 x %0] zeroinitializer, align 16\n"
+ "define void @marker4(i64 %d) {\n"
+ "entry:\n"
+ " %conv = trunc i64 %d to i32\n"
+ " store i32 %conv, i32* getelementptr inbounds "
+ " ([50 x %st], [50 x %st]* @v, i64 0, i64 0, i32 0), align 16\n"
+ " store i32 %conv, i32* getelementptr inbounds "
+ " ([50 x %0], [50 x %0]* @g, i64 0, i64 0, i32 0), align 16\n"
+ " ret void\n"
+ "}";
+ SlotMapping Mapping;
+ auto Mod = parseAssemblyString(Source, Error, Ctx, &Mapping);
+ ASSERT_TRUE(Mod != nullptr);
+ auto &M = *Mod;
+
+ const Value *V;
+ V = parseConstantValue("i32* getelementptr inbounds ([50 x %st], [50 x %st]* "
+ "@v, i64 0, i64 0, i32 0)",
+ Error, M, &Mapping);
+ ASSERT_TRUE(V);
+ ASSERT_TRUE(isa<ConstantExpr>(V));
+
+ V = parseConstantValue("i32* getelementptr inbounds ([50 x %0], [50 x %0]* "
+ "@g, i64 0, i64 0, i32 0)",
+ Error, M, &Mapping);
+ ASSERT_TRUE(V);
+ ASSERT_TRUE(isa<ConstantExpr>(V));
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/AsmParser/CMakeLists.txt b/gnu/llvm/unittests/AsmParser/CMakeLists.txt
new file mode 100644
index 00000000000..1920bfaa3aa
--- /dev/null
+++ b/gnu/llvm/unittests/AsmParser/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ AsmParser
+ Core
+ Support
+ )
+
+add_llvm_unittest(AsmParserTests
+ AsmParserTest.cpp
+ )
diff --git a/gnu/llvm/unittests/AsmParser/Makefile b/gnu/llvm/unittests/AsmParser/Makefile
new file mode 100644
index 00000000000..41eadd43043
--- /dev/null
+++ b/gnu/llvm/unittests/AsmParser/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/AsmParser/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = AsmParser
+LINK_COMPONENTS := AsmParser Core Support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Bitcode/BitReaderTest.cpp b/gnu/llvm/unittests/Bitcode/BitReaderTest.cpp
new file mode 100644
index 00000000000..420aca2443b
--- /dev/null
+++ b/gnu/llvm/unittests/Bitcode/BitReaderTest.cpp
@@ -0,0 +1,275 @@
+//===- llvm/unittest/Bitcode/BitReaderTest.cpp - Tests for BitReader ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "llvm/Bitcode/BitstreamWriter.h"
+#include "llvm/Bitcode/ReaderWriter.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/DataStream.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/StreamingMemoryObject.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+std::unique_ptr<Module> parseAssembly(const char *Assembly) {
+ SMDiagnostic Error;
+ std::unique_ptr<Module> M =
+ parseAssemblyString(Assembly, Error, getGlobalContext());
+
+ std::string ErrMsg;
+ raw_string_ostream OS(ErrMsg);
+ Error.print("", OS);
+
+ // A failure here means that the test itself is buggy.
+ if (!M)
+ report_fatal_error(OS.str().c_str());
+
+ return M;
+}
+
+static void writeModuleToBuffer(std::unique_ptr<Module> Mod,
+ SmallVectorImpl<char> &Buffer) {
+ raw_svector_ostream OS(Buffer);
+ WriteBitcodeToFile(Mod.get(), OS);
+}
+
+static std::unique_ptr<Module> getLazyModuleFromAssembly(LLVMContext &Context,
+ SmallString<1024> &Mem,
+ const char *Assembly) {
+ writeModuleToBuffer(parseAssembly(Assembly), Mem);
+ std::unique_ptr<MemoryBuffer> Buffer =
+ MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
+ ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
+ getLazyBitcodeModule(std::move(Buffer), Context);
+ return std::move(ModuleOrErr.get());
+}
+
+class BufferDataStreamer : public DataStreamer {
+ std::unique_ptr<MemoryBuffer> Buffer;
+ unsigned Pos = 0;
+ size_t GetBytes(unsigned char *Out, size_t Len) override {
+ StringRef Buf = Buffer->getBuffer();
+ size_t Left = Buf.size() - Pos;
+ Len = std::min(Left, Len);
+ memcpy(Out, Buffer->getBuffer().substr(Pos).data(), Len);
+ Pos += Len;
+ return Len;
+ }
+
+public:
+ BufferDataStreamer(std::unique_ptr<MemoryBuffer> Buffer)
+ : Buffer(std::move(Buffer)) {}
+};
+
+static std::unique_ptr<Module>
+getStreamedModuleFromAssembly(LLVMContext &Context, SmallString<1024> &Mem,
+ const char *Assembly) {
+ writeModuleToBuffer(parseAssembly(Assembly), Mem);
+ std::unique_ptr<MemoryBuffer> Buffer =
+ MemoryBuffer::getMemBuffer(Mem.str(), "test", false);
+ auto Streamer = llvm::make_unique<BufferDataStreamer>(std::move(Buffer));
+ ErrorOr<std::unique_ptr<Module>> ModuleOrErr =
+ getStreamedBitcodeModule("test", std::move(Streamer), Context);
+ return std::move(ModuleOrErr.get());
+}
+
+// Checks if we correctly detect eof if we try to read N bits when there are not
+// enough bits left on the input stream to read N bits, and we are using a data
+// streamer. In particular, it checks if we properly set the object size when
+// the eof is reached under such conditions.
+TEST(BitReaderTest, TestForEofAfterReadFailureOnDataStreamer) {
+ // Note: Because StreamingMemoryObject does a call to method GetBytes in it's
+ // constructor, using internal constant kChunkSize, we must fill the input
+ // with more characters than that amount.
+ static size_t InputSize = StreamingMemoryObject::kChunkSize + 5;
+ char *Text = new char[InputSize];
+ std::memset(Text, 'a', InputSize);
+ Text[InputSize - 1] = '\0';
+ StringRef Input(Text);
+
+ // Build bitsteam reader using data streamer.
+ auto MemoryBuf = MemoryBuffer::getMemBuffer(Input);
+ std::unique_ptr<DataStreamer> Streamer(
+ new BufferDataStreamer(std::move(MemoryBuf)));
+ auto OwnedBytes =
+ llvm::make_unique<StreamingMemoryObject>(std::move(Streamer));
+ auto Reader = llvm::make_unique<BitstreamReader>(std::move(OwnedBytes));
+ BitstreamCursor Cursor;
+ Cursor.init(Reader.get());
+
+ // Jump to two bytes before end of stream.
+ Cursor.JumpToBit((InputSize - 4) * CHAR_BIT);
+ // Try to read 4 bytes when only 2 are present, resulting in error value 0.
+ const size_t ReadErrorValue = 0;
+ EXPECT_EQ(ReadErrorValue, Cursor.Read(32));
+ // Should be at eof now.
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+
+ delete[] Text;
+}
+
+TEST(BitReaderTest, MateralizeForwardRefWithStream) {
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getStreamedModuleFromAssembly(
+ Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
+ "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n");
+ EXPECT_FALSE(M->getFunction("func")->empty());
+}
+
+// Tests that lazy evaluation can parse functions out of order.
+TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
+ SmallString<1024> Mem;
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "define void @f() {\n"
+ " unreachable\n"
+ "}\n"
+ "define void @g() {\n"
+ " unreachable\n"
+ "}\n"
+ "define void @h() {\n"
+ " unreachable\n"
+ "}\n"
+ "define void @j() {\n"
+ " unreachable\n"
+ "}\n");
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ Function *F = M->getFunction("f");
+ Function *G = M->getFunction("g");
+ Function *H = M->getFunction("h");
+ Function *J = M->getFunction("j");
+
+ // Initially all functions are not materialized (no basic blocks).
+ EXPECT_TRUE(F->empty());
+ EXPECT_TRUE(G->empty());
+ EXPECT_TRUE(H->empty());
+ EXPECT_TRUE(J->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize h.
+ H->materialize();
+ EXPECT_TRUE(F->empty());
+ EXPECT_TRUE(G->empty());
+ EXPECT_FALSE(H->empty());
+ EXPECT_TRUE(J->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize g.
+ G->materialize();
+ EXPECT_TRUE(F->empty());
+ EXPECT_FALSE(G->empty());
+ EXPECT_FALSE(H->empty());
+ EXPECT_TRUE(J->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize j.
+ J->materialize();
+ EXPECT_TRUE(F->empty());
+ EXPECT_FALSE(G->empty());
+ EXPECT_FALSE(H->empty());
+ EXPECT_FALSE(J->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize f.
+ F->materialize();
+ EXPECT_FALSE(F->empty());
+ EXPECT_FALSE(G->empty());
+ EXPECT_FALSE(H->empty());
+ EXPECT_FALSE(J->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+}
+
+TEST(BitReaderTest, MaterializeFunctionsForBlockAddr) { // PR11677
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "@table = constant i8* blockaddress(@func, %bb)\n"
+ "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n");
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+}
+
+TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionBefore) {
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "define i8* @before() {\n"
+ " ret i8* blockaddress(@func, %bb)\n"
+ "}\n"
+ "define void @other() {\n"
+ " unreachable\n"
+ "}\n"
+ "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n");
+ EXPECT_TRUE(M->getFunction("before")->empty());
+ EXPECT_TRUE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize @before, pulling in @func.
+ EXPECT_FALSE(M->getFunction("before")->materialize());
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_TRUE(M->getFunction("other")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+}
+
+TEST(BitReaderTest, MaterializeFunctionsForBlockAddrInFunctionAfter) {
+ SmallString<1024> Mem;
+
+ LLVMContext Context;
+ std::unique_ptr<Module> M = getLazyModuleFromAssembly(
+ Context, Mem, "define void @func() {\n"
+ " unreachable\n"
+ "bb:\n"
+ " unreachable\n"
+ "}\n"
+ "define void @other() {\n"
+ " unreachable\n"
+ "}\n"
+ "define i8* @after() {\n"
+ " ret i8* blockaddress(@func, %bb)\n"
+ "}\n");
+ EXPECT_TRUE(M->getFunction("after")->empty());
+ EXPECT_TRUE(M->getFunction("func")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+
+ // Materialize @after, pulling in @func.
+ EXPECT_FALSE(M->getFunction("after")->materialize());
+ EXPECT_FALSE(M->getFunction("func")->empty());
+ EXPECT_TRUE(M->getFunction("other")->empty());
+ EXPECT_FALSE(verifyModule(*M, &dbgs()));
+}
+
+} // end namespace
diff --git a/gnu/llvm/unittests/Bitcode/BitstreamReaderTest.cpp b/gnu/llvm/unittests/Bitcode/BitstreamReaderTest.cpp
new file mode 100644
index 00000000000..b11d7fde774
--- /dev/null
+++ b/gnu/llvm/unittests/Bitcode/BitstreamReaderTest.cpp
@@ -0,0 +1,56 @@
+//===- BitstreamReaderTest.cpp - Tests for BitstreamReader ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Bitcode/BitstreamReader.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(BitstreamReaderTest, AtEndOfStream) {
+ uint8_t Bytes[4] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
+ BitstreamCursor Cursor(Reader);
+
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+ (void)Cursor.Read(8);
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+ (void)Cursor.Read(24);
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+
+ Cursor.JumpToBit(0);
+ EXPECT_FALSE(Cursor.AtEndOfStream());
+
+ Cursor.JumpToBit(32);
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+TEST(BitstreamReaderTest, AtEndOfStreamJump) {
+ uint8_t Bytes[4] = {
+ 0x00, 0x01, 0x02, 0x03
+ };
+ BitstreamReader Reader(std::begin(Bytes), std::end(Bytes));
+ BitstreamCursor Cursor(Reader);
+
+ Cursor.JumpToBit(32);
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+TEST(BitstreamReaderTest, AtEndOfStreamEmpty) {
+ uint8_t Dummy = 0xFF;
+ BitstreamReader Reader(&Dummy, &Dummy);
+ BitstreamCursor Cursor(Reader);
+
+ EXPECT_TRUE(Cursor.AtEndOfStream());
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Bitcode/CMakeLists.txt b/gnu/llvm/unittests/Bitcode/CMakeLists.txt
new file mode 100644
index 00000000000..09cbcdc7284
--- /dev/null
+++ b/gnu/llvm/unittests/Bitcode/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+ AsmParser
+ BitReader
+ BitWriter
+ Core
+ Support
+ )
+
+add_llvm_unittest(BitcodeTests
+ BitReaderTest.cpp
+ BitstreamReaderTest.cpp
+ )
diff --git a/gnu/llvm/unittests/Bitcode/Makefile b/gnu/llvm/unittests/Bitcode/Makefile
new file mode 100644
index 00000000000..33b09b914b5
--- /dev/null
+++ b/gnu/llvm/unittests/Bitcode/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Bitcode/Makefile --------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = Bitcode
+LINK_COMPONENTS := AsmParser BitReader BitWriter Core Support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/CMakeLists.txt b/gnu/llvm/unittests/CMakeLists.txt
new file mode 100644
index 00000000000..e5befcec6e0
--- /dev/null
+++ b/gnu/llvm/unittests/CMakeLists.txt
@@ -0,0 +1,28 @@
+add_custom_target(UnitTests)
+set_target_properties(UnitTests PROPERTIES FOLDER "Tests")
+
+if (APPLE)
+ set(CMAKE_INSTALL_RPATH "@executable_path/../../lib")
+else(UNIX)
+ set(CMAKE_INSTALL_RPATH "\$ORIGIN/../../lib${LLVM_LIBDIR_SUFFIX}")
+endif()
+
+function(add_llvm_unittest test_dirname)
+ add_unittest(UnitTests ${test_dirname} ${ARGN})
+endfunction()
+
+add_subdirectory(ADT)
+add_subdirectory(Analysis)
+add_subdirectory(AsmParser)
+add_subdirectory(Bitcode)
+add_subdirectory(CodeGen)
+add_subdirectory(DebugInfo)
+add_subdirectory(ExecutionEngine)
+add_subdirectory(IR)
+add_subdirectory(LineEditor)
+add_subdirectory(Linker)
+add_subdirectory(MC)
+add_subdirectory(Option)
+add_subdirectory(ProfileData)
+add_subdirectory(Support)
+add_subdirectory(Transforms)
diff --git a/gnu/llvm/unittests/CodeGen/CMakeLists.txt b/gnu/llvm/unittests/CodeGen/CMakeLists.txt
new file mode 100644
index 00000000000..65c0ac3f20e
--- /dev/null
+++ b/gnu/llvm/unittests/CodeGen/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+ AsmPrinter
+ Support
+ )
+
+set(CodeGenSources
+ DIEHashTest.cpp
+ )
+
+add_llvm_unittest(CodeGenTests
+ ${CodeGenSources}
+ )
diff --git a/gnu/llvm/unittests/CodeGen/DIEHashTest.cpp b/gnu/llvm/unittests/CodeGen/DIEHashTest.cpp
new file mode 100644
index 00000000000..e3a9e562827
--- /dev/null
+++ b/gnu/llvm/unittests/CodeGen/DIEHashTest.cpp
@@ -0,0 +1,699 @@
+//===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/DIE.h"
+#include "../lib/CodeGen/AsmPrinter/DIEHash.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/DwarfStringPoolEntry.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture
+class DIEHashTest : public testing::Test {
+public:
+ BumpPtrAllocator Alloc;
+
+private:
+ StringMap<DwarfStringPoolEntry> Pool;
+
+public:
+ DIEString getString(StringRef S) {
+ DwarfStringPoolEntry Entry = {nullptr, 1, 1};
+ return DIEString(
+ DwarfStringPoolEntryRef(*Pool.insert(std::make_pair(S, Entry)).first));
+ }
+};
+
+TEST_F(DIEHashTest, Data1) {
+ DIEHash Hash;
+ DIE &Die = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
+ DIEInteger Size(4);
+ Die.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Size);
+ uint64_t MD5Res = Hash.computeTypeSignature(Die);
+ ASSERT_EQ(0x1AFE116E83701108ULL, MD5Res);
+}
+
+// struct {};
+TEST_F(DIEHashTest, TrivialType) {
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ // Line and file number are ignored.
+ Unnamed.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0x715305ce6cfd9ad1ULL, MD5Res);
+}
+
+// struct foo { };
+TEST_F(DIEHashTest, NamedType) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xd566dbd2ca5265ffULL, MD5Res);
+}
+
+// namespace space { struct foo { }; }
+TEST_F(DIEHashTest, NamespacedType) {
+ DIE &CU = *DIE::get(Alloc, dwarf::DW_TAG_compile_unit);
+
+ auto Space = DIE::get(Alloc, dwarf::DW_TAG_namespace);
+ DIEInteger One(1);
+ DIEString SpaceStr = getString("space");
+ Space->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, SpaceStr);
+ // DW_AT_declaration is ignored.
+ Space->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+ // sibling?
+
+ auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEString FooStr = getString("foo");
+ Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+ Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ DIE &N = *Foo;
+ Space->addChild(std::move(Foo));
+ CU.addChild(std::move(Space));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(N);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0x7b80381fd17f1e33ULL, MD5Res);
+}
+
+// struct { int member; };
+TEST_F(DIEHashTest, TypeWithMember) {
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Four(4);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
+
+ DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
+ DIEString IntStr = getString("int");
+ Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
+ Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
+ DIEInteger Five(5);
+ Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
+
+ DIEEntry IntRef(Int);
+
+ auto Member = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemberStr = getString("member");
+ Member->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemberStr);
+ DIEInteger Zero(0);
+ Member->addValue(Alloc, dwarf::DW_AT_data_member_location,
+ dwarf::DW_FORM_data1, Zero);
+ Member->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
+
+ Unnamed.addChild(std::move(Member));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ ASSERT_EQ(0x5646aa436b7e07c6ULL, MD5Res);
+}
+
+// struct foo { int mem1, mem2; };
+TEST_F(DIEHashTest, ReusedType) {
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+
+ DIEInteger Four(4);
+ DIE &Int = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
+ DIEString IntStr = getString("int");
+ Int.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, IntStr);
+ Int.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
+ DIEInteger Five(5);
+ Int.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
+
+ DIEEntry IntRef(Int);
+
+ auto Mem1 = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString Mem1Str = getString("mem1");
+ Mem1->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem1Str);
+ DIEInteger Zero(0);
+ Mem1->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+ Mem1->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
+
+ Unnamed.addChild(std::move(Mem1));
+
+ auto Mem2 = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString Mem2Str = getString("mem2");
+ Mem2->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, Mem2Str);
+ Mem2->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Four);
+ Mem2->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntRef);
+
+ Unnamed.addChild(std::move(Mem2));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ ASSERT_EQ(0x3a7dc3ed7b76b2f8ULL, MD5Res);
+}
+
+// struct foo { static foo f; };
+TEST_F(DIEHashTest, RecursiveType) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemStr = getString("mem");
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ DIEEntry FooRef(Foo);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
+ // DW_AT_external and DW_AT_declaration are ignored anyway, so skip them.
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x73d8b25aef227b06ULL, MD5Res);
+}
+
+// struct foo { foo *mem; };
+TEST_F(DIEHashTest, Pointer) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemStr = getString("mem");
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+
+ DIE &FooPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
+ FooPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEEntry FooRef(Foo);
+ FooPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRef);
+
+ DIEEntry FooPtrRef(FooPtr);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooPtrRef);
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x74ea73862e8708d2ULL, MD5Res);
+}
+
+// struct foo { foo &mem; };
+TEST_F(DIEHashTest, Reference) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemStr = getString("mem");
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+
+ DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_reference_type);
+ FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEEntry FooEntry(Foo);
+ FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
+
+ DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
+ DIEEntry FooRefRef(FooRef);
+ FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ FooRefRef);
+
+ DIEEntry FooRefConstRef(FooRefConst);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0xa0b15f467ad4525bULL, MD5Res);
+}
+
+// struct foo { foo &&mem; };
+TEST_F(DIEHashTest, RValueReference) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemStr = getString("mem");
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+
+ DIE &FooRef = *DIE::get(Alloc, dwarf::DW_TAG_rvalue_reference_type);
+ FooRef.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEEntry FooEntry(Foo);
+ FooRef.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
+
+ DIE &FooRefConst = *DIE::get(Alloc, dwarf::DW_TAG_const_type);
+ DIEEntry FooRefRef(FooRef);
+ FooRefConst.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ FooRefRef);
+
+ DIEEntry FooRefConstRef(FooRefConst);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooRefConstRef);
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0xad211c8c3b31e57ULL, MD5Res);
+}
+
+// struct foo { foo foo::*mem; };
+TEST_F(DIEHashTest, PtrToMember) {
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger Eight(8);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ DIEString FooStr = getString("foo");
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString MemStr = getString("mem");
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ DIEInteger Zero(0);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+
+ DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry FooEntry(Foo);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FooEntry);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4,
+ FooEntry);
+
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PtrToFooMemRef);
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x852e0c9ff7c04ebULL, MD5Res);
+}
+
+// Check that the hash for a pointer-to-member matches regardless of whether the
+// pointed-to type is a declaration or a definition.
+//
+// struct bar; // { };
+// struct foo { bar foo::*mem; };
+TEST_F(DIEHashTest, PtrToMemberDeclDefMatch) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr = getString("foo");
+ DIEString BarStr = getString("bar");
+ DIEString MemStr = getString("mem");
+ uint64_t MD5ResDecl;
+ {
+ DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
+ Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
+ dwarf::DW_FORM_data1, Zero);
+
+ DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(Bar);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ BarEntry);
+ DIEEntry FooEntry(Foo);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
+ dwarf::DW_FORM_ref4, FooEntry);
+
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ PtrToFooMemRef);
+
+ Foo.addChild(std::move(Mem));
+
+ MD5ResDecl = DIEHash().computeTypeSignature(Foo);
+ }
+ uint64_t MD5ResDef;
+ {
+ DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
+ Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
+ dwarf::DW_FORM_data1, Zero);
+
+ DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(Bar);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ BarEntry);
+ DIEEntry FooEntry(Foo);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
+ dwarf::DW_FORM_ref4, FooEntry);
+
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ PtrToFooMemRef);
+
+ Foo.addChild(std::move(Mem));
+
+ MD5ResDef = DIEHash().computeTypeSignature(Foo);
+ }
+ ASSERT_EQ(MD5ResDef, MD5ResDecl);
+}
+
+// Check that the hash for a pointer-to-member matches regardless of whether the
+// pointed-to type is a declaration or a definition.
+//
+// struct bar; // { };
+// struct foo { bar bar::*mem; };
+TEST_F(DIEHashTest, PtrToMemberDeclDefMisMatch) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr = getString("foo");
+ DIEString BarStr = getString("bar");
+ DIEString MemStr = getString("mem");
+ uint64_t MD5ResDecl;
+ {
+ DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
+ Bar.addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
+ dwarf::DW_FORM_data1, Zero);
+
+ DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(Bar);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ BarEntry);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
+ dwarf::DW_FORM_ref4, BarEntry);
+
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ PtrToFooMemRef);
+
+ Foo.addChild(std::move(Mem));
+
+ MD5ResDecl = DIEHash().computeTypeSignature(Foo);
+ }
+ uint64_t MD5ResDef;
+ {
+ DIE &Bar = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Bar.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, BarStr);
+ Bar.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location,
+ dwarf::DW_FORM_data1, Zero);
+
+ DIE &PtrToFooMem = *DIE::get(Alloc, dwarf::DW_TAG_ptr_to_member_type);
+ DIEEntry BarEntry(Bar);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ BarEntry);
+ PtrToFooMem.addValue(Alloc, dwarf::DW_AT_containing_type,
+ dwarf::DW_FORM_ref4, BarEntry);
+
+ DIEEntry PtrToFooMemRef(PtrToFooMem);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ PtrToFooMemRef);
+
+ Foo.addChild(std::move(Mem));
+
+ MD5ResDef = DIEHash().computeTypeSignature(Foo);
+ }
+ // FIXME: This seems to be a bug in the DWARF type hashing specification that
+ // only uses the brief name hashing for types referenced via DW_AT_type. In
+ // this case the type is referenced via DW_AT_containing_type and full hashing
+ // causes a hash to differ when the containing type is a declaration in one TU
+ // and a definition in another.
+ ASSERT_NE(MD5ResDef, MD5ResDecl);
+}
+
+// struct { } a;
+// struct foo { decltype(a) mem; };
+TEST_F(DIEHashTest, RefUnnamedType) {
+ DIEInteger Zero(0);
+ DIEInteger One(1);
+ DIEInteger Eight(8);
+ DIEString FooStr = getString("foo");
+ DIEString MemStr = getString("mem");
+
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ DIE &Foo = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ Foo.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Eight);
+ Foo.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+
+ auto Mem = DIE::get(Alloc, dwarf::DW_TAG_member);
+ Mem->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, MemStr);
+ Mem->addValue(Alloc, dwarf::DW_AT_data_member_location, dwarf::DW_FORM_data1,
+ Zero);
+
+ DIE &UnnamedPtr = *DIE::get(Alloc, dwarf::DW_TAG_pointer_type);
+ UnnamedPtr.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ Eight);
+ DIEEntry UnnamedRef(Unnamed);
+ UnnamedPtr.addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4,
+ UnnamedRef);
+
+ DIEEntry UnnamedPtrRef(UnnamedPtr);
+ Mem->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, UnnamedPtrRef);
+
+ Foo.addChild(std::move(Mem));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Foo);
+
+ ASSERT_EQ(0x954e026f01c02529ULL, MD5Res);
+}
+
+// struct { struct foo { }; };
+TEST_F(DIEHashTest, NestedType) {
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ auto Foo = DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEString FooStr = getString("foo");
+ Foo->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FooStr);
+ Foo->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ Unnamed.addChild(std::move(Foo));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xde8a3b7b43807f4aULL, MD5Res);
+}
+
+// struct { static void func(); };
+TEST_F(DIEHashTest, MemberFunc) {
+ DIE &Unnamed = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ Unnamed.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+
+ auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
+ DIEString FuncStr = getString("func");
+ Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
+
+ Unnamed.addChild(std::move(Func));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(Unnamed);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0xd36a1b6dfb604ba0ULL, MD5Res);
+}
+
+// struct A {
+// static void func();
+// };
+TEST_F(DIEHashTest, MemberFuncFlag) {
+ DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ DIEString AStr = getString("A");
+ A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
+ A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
+
+ auto Func = DIE::get(Alloc, dwarf::DW_TAG_subprogram);
+ DIEString FuncStr = getString("func");
+ DIEString FuncLinkage = getString("_ZN1A4funcEv");
+ DIEInteger Two(2);
+ Func->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present,
+ One);
+ Func->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FuncStr);
+ Func->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ Func->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
+ Func->addValue(Alloc, dwarf::DW_AT_linkage_name, dwarf::DW_FORM_strp,
+ FuncLinkage);
+ Func->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+
+ A.addChild(std::move(Func));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(A);
+
+ // The exact same hash GCC produces for this DIE.
+ ASSERT_EQ(0x8f78211ddce3df10ULL, MD5Res);
+}
+
+// Derived from:
+// struct A {
+// const static int PI = -3;
+// };
+// A a;
+TEST_F(DIEHashTest, MemberSdata) {
+ DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ DIEString AStr = getString("A");
+ A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
+ A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
+
+ DIEInteger Four(4);
+ DIEInteger Five(5);
+ DIEString FStr = getString("int");
+ DIE &IntTyDIE = *DIE::get(Alloc, dwarf::DW_TAG_base_type);
+ IntTyDIE.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, Four);
+ IntTyDIE.addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Five);
+ IntTyDIE.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
+
+ DIEEntry IntTy(IntTyDIE);
+ auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
+ PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IntTy);
+
+ DIEEntry PITy(*PITyDIE);
+ auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString PIStr = getString("PI");
+ DIEInteger Two(2);
+ DIEInteger NegThree(-3);
+ PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
+ PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
+ PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
+ PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
+ PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+ PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, NegThree);
+
+ A.addChild(std::move(PI));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(A);
+ ASSERT_EQ(0x9a216000dd3788a7ULL, MD5Res);
+}
+
+// Derived from:
+// struct A {
+// const static float PI = 3.14;
+// };
+// A a;
+TEST_F(DIEHashTest, MemberBlock) {
+ DIE &A = *DIE::get(Alloc, dwarf::DW_TAG_structure_type);
+ DIEInteger One(1);
+ DIEString AStr = getString("A");
+ A.addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, AStr);
+ A.addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ A.addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, One);
+
+ DIEInteger Four(4);
+ DIEString FStr = getString("float");
+ auto FloatTyDIE = DIE::get(Alloc, dwarf::DW_TAG_base_type);
+ FloatTyDIE->addValue(Alloc, dwarf::DW_AT_byte_size, dwarf::DW_FORM_data1,
+ Four);
+ FloatTyDIE->addValue(Alloc, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
+ Four);
+ FloatTyDIE->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, FStr);
+ DIEEntry FloatTy(*FloatTyDIE);
+ auto PITyDIE = DIE::get(Alloc, dwarf::DW_TAG_const_type);
+ PITyDIE->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, FloatTy);
+
+ DIEEntry PITy(*PITyDIE);
+ auto PI = DIE::get(Alloc, dwarf::DW_TAG_member);
+ DIEString PIStr = getString("PI");
+ DIEInteger Two(2);
+ PI->addValue(Alloc, dwarf::DW_AT_name, dwarf::DW_FORM_strp, PIStr);
+ PI->addValue(Alloc, dwarf::DW_AT_decl_file, dwarf::DW_FORM_data1, One);
+ PI->addValue(Alloc, dwarf::DW_AT_decl_line, dwarf::DW_FORM_data1, Two);
+ PI->addValue(Alloc, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, PITy);
+ PI->addValue(Alloc, dwarf::DW_AT_external, dwarf::DW_FORM_flag_present, One);
+ PI->addValue(Alloc, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag_present,
+ One);
+
+ DIEBlock PIBlock;
+ DIEInteger Blk1(0xc3);
+ DIEInteger Blk2(0xf5);
+ DIEInteger Blk3(0x48);
+ DIEInteger Blk4(0x40);
+
+ PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk1);
+ PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk2);
+ PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk3);
+ PIBlock.addValue(Alloc, (dwarf::Attribute)0, dwarf::DW_FORM_data1, Blk4);
+
+ PI->addValue(Alloc, dwarf::DW_AT_const_value, dwarf::DW_FORM_block1,
+ &PIBlock);
+
+ A.addChild(std::move(PI));
+
+ uint64_t MD5Res = DIEHash().computeTypeSignature(A);
+ ASSERT_EQ(0x493af53ad3d3f651ULL, MD5Res);
+}
+}
diff --git a/gnu/llvm/unittests/CodeGen/Makefile b/gnu/llvm/unittests/CodeGen/Makefile
new file mode 100644
index 00000000000..4f07017c291
--- /dev/null
+++ b/gnu/llvm/unittests/CodeGen/Makefile
@@ -0,0 +1,16 @@
+##===- unittests/DebugInfo/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = CodeGen
+LINK_COMPONENTS := asmprinter codegen support
+
+include $(LEVEL)/Makefile.config
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/DebugInfo/CMakeLists.txt b/gnu/llvm/unittests/DebugInfo/CMakeLists.txt
new file mode 100644
index 00000000000..dae472bafdd
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/CMakeLists.txt
@@ -0,0 +1,3 @@
+
+add_subdirectory(DWARF)
+add_subdirectory(PDB)
diff --git a/gnu/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/gnu/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
new file mode 100644
index 00000000000..4bec17cbb52
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ DebugInfoDWARF
+ )
+
+set(DebugInfoSources
+ DWARFFormValueTest.cpp
+ )
+
+add_llvm_unittest(DebugInfoDWARFTests
+ ${DebugInfoSources}
+ )
diff --git a/gnu/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp b/gnu/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
new file mode 100644
index 00000000000..371e2af95de
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/DWARF/DWARFFormValueTest.cpp
@@ -0,0 +1,124 @@
+//===- llvm/unittest/DebugInfo/DWARFFormValueTest.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/LEB128.h"
+#include "gtest/gtest.h"
+#include <climits>
+using namespace llvm;
+using namespace dwarf;
+
+namespace {
+
+TEST(DWARFFormValue, FixedFormSizes) {
+ // Size of DW_FORM_addr and DW_FORM_ref_addr are equal in DWARF2,
+ // DW_FORM_ref_addr is always 4 bytes in DWARF32 starting from DWARF3.
+ ArrayRef<uint8_t> sizes = DWARFFormValue::getFixedFormSizes(4, 2);
+ EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]);
+ sizes = DWARFFormValue::getFixedFormSizes(8, 2);
+ EXPECT_EQ(sizes[DW_FORM_addr], sizes[DW_FORM_ref_addr]);
+ sizes = DWARFFormValue::getFixedFormSizes(8, 3);
+ EXPECT_EQ(4, sizes[DW_FORM_ref_addr]);
+ // Check that we don't have fixed form sizes for weird address sizes.
+ EXPECT_EQ(0U, DWARFFormValue::getFixedFormSizes(16, 2).size());
+}
+
+bool isFormClass(uint16_t Form, DWARFFormValue::FormClass FC) {
+ return DWARFFormValue(Form).isFormClass(FC);
+}
+
+TEST(DWARFFormValue, FormClass) {
+ EXPECT_TRUE(isFormClass(DW_FORM_addr, DWARFFormValue::FC_Address));
+ EXPECT_FALSE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Address));
+ EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_Constant));
+ EXPECT_TRUE(isFormClass(DW_FORM_data8, DWARFFormValue::FC_SectionOffset));
+ EXPECT_TRUE(
+ isFormClass(DW_FORM_sec_offset, DWARFFormValue::FC_SectionOffset));
+ EXPECT_TRUE(isFormClass(DW_FORM_GNU_str_index, DWARFFormValue::FC_String));
+ EXPECT_TRUE(isFormClass(DW_FORM_GNU_addr_index, DWARFFormValue::FC_Address));
+ EXPECT_FALSE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Address));
+ EXPECT_TRUE(isFormClass(DW_FORM_ref_addr, DWARFFormValue::FC_Reference));
+ EXPECT_TRUE(isFormClass(DW_FORM_ref_sig8, DWARFFormValue::FC_Reference));
+}
+
+template<typename RawTypeT>
+DWARFFormValue createDataXFormValue(uint16_t Form, RawTypeT Value) {
+ char Raw[sizeof(RawTypeT)];
+ memcpy(Raw, &Value, sizeof(RawTypeT));
+ uint32_t Offset = 0;
+ DWARFFormValue Result(Form);
+ DataExtractor Data(StringRef(Raw, sizeof(RawTypeT)),
+ sys::IsLittleEndianHost, sizeof(void*));
+ Result.extractValue(Data, &Offset, nullptr);
+ return Result;
+}
+
+DWARFFormValue createULEBFormValue(uint64_t Value) {
+ SmallString<10> RawData;
+ raw_svector_ostream OS(RawData);
+ encodeULEB128(Value, OS);
+ uint32_t Offset = 0;
+ DWARFFormValue Result(DW_FORM_udata);
+ DataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void*));
+ Result.extractValue(Data, &Offset, nullptr);
+ return Result;
+}
+
+DWARFFormValue createSLEBFormValue(int64_t Value) {
+ SmallString<10> RawData;
+ raw_svector_ostream OS(RawData);
+ encodeSLEB128(Value, OS);
+ uint32_t Offset = 0;
+ DWARFFormValue Result(DW_FORM_sdata);
+ DataExtractor Data(OS.str(), sys::IsLittleEndianHost, sizeof(void*));
+ Result.extractValue(Data, &Offset, nullptr);
+ return Result;
+}
+
+TEST(DWARFFormValue, SignedConstantForms) {
+ // Check that we correctly sign extend fixed size forms.
+ auto Sign1 = createDataXFormValue<uint8_t>(DW_FORM_data1, -123);
+ auto Sign2 = createDataXFormValue<uint16_t>(DW_FORM_data2, -12345);
+ auto Sign4 = createDataXFormValue<uint32_t>(DW_FORM_data4, -123456789);
+ auto Sign8 = createDataXFormValue<uint64_t>(DW_FORM_data8, -1);
+ EXPECT_EQ(Sign1.getAsSignedConstant().getValue(), -123);
+ EXPECT_EQ(Sign2.getAsSignedConstant().getValue(), -12345);
+ EXPECT_EQ(Sign4.getAsSignedConstant().getValue(), -123456789);
+ EXPECT_EQ(Sign8.getAsSignedConstant().getValue(), -1);
+
+ // Check that we can handle big positive values, but that we return
+ // an error just over the limit.
+ auto UMax = createULEBFormValue(LLONG_MAX);
+ auto TooBig = createULEBFormValue(uint64_t(LLONG_MAX) + 1);
+ EXPECT_EQ(UMax.getAsSignedConstant().getValue(), LLONG_MAX);
+ EXPECT_EQ(TooBig.getAsSignedConstant().hasValue(), false);
+
+ // Sanity check some other forms.
+ auto Data1 = createDataXFormValue<uint8_t>(DW_FORM_data1, 120);
+ auto Data2 = createDataXFormValue<uint16_t>(DW_FORM_data2, 32000);
+ auto Data4 = createDataXFormValue<uint32_t>(DW_FORM_data4, 2000000000);
+ auto Data8 = createDataXFormValue<uint64_t>(DW_FORM_data8, 0x1234567812345678LL);
+ auto LEBMin = createSLEBFormValue(LLONG_MIN);
+ auto LEBMax = createSLEBFormValue(LLONG_MAX);
+ auto LEB1 = createSLEBFormValue(-42);
+ auto LEB2 = createSLEBFormValue(42);
+ EXPECT_EQ(Data1.getAsSignedConstant().getValue(), 120);
+ EXPECT_EQ(Data2.getAsSignedConstant().getValue(), 32000);
+ EXPECT_EQ(Data4.getAsSignedConstant().getValue(), 2000000000);
+ EXPECT_EQ(Data8.getAsSignedConstant().getValue(), 0x1234567812345678LL);
+ EXPECT_EQ(LEBMin.getAsSignedConstant().getValue(), LLONG_MIN);
+ EXPECT_EQ(LEBMax.getAsSignedConstant().getValue(), LLONG_MAX);
+ EXPECT_EQ(LEB1.getAsSignedConstant().getValue(), -42);
+ EXPECT_EQ(LEB2.getAsSignedConstant().getValue(), 42);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/DebugInfo/DWARF/Makefile b/gnu/llvm/unittests/DebugInfo/DWARF/Makefile
new file mode 100644
index 00000000000..b0f40e1ca9d
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/DWARF/Makefile
@@ -0,0 +1,16 @@
+##===- unittests/DebugInfo/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = DebugInfoDWARF
+LINK_COMPONENTS := DebugInfoDWARF object support
+
+include $(LEVEL)/Makefile.config
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/DebugInfo/Makefile b/gnu/llvm/unittests/DebugInfo/Makefile
new file mode 100644
index 00000000000..1889ad22db1
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/DebugInfo/Makefile ------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../..
+
+include $(LEVEL)/Makefile.config
+
+PARALLEL_DIRS := DWARF PDB
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/DebugInfo/PDB/CMakeLists.txt b/gnu/llvm/unittests/DebugInfo/PDB/CMakeLists.txt
new file mode 100644
index 00000000000..91924a5a875
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/PDB/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ DebugInfoPDB
+ )
+
+set(DebugInfoPDBSources
+ PDBApiTest.cpp
+ )
+
+add_llvm_unittest(DebugInfoPDBTests
+ ${DebugInfoPDBSources}
+ )
diff --git a/gnu/llvm/unittests/DebugInfo/PDB/Makefile b/gnu/llvm/unittests/DebugInfo/PDB/Makefile
new file mode 100644
index 00000000000..eb118a3fd2b
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/PDB/Makefile
@@ -0,0 +1,16 @@
+##===- unittests/DebugInfo/PDB/Makefile -------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = DebugInfoPDB
+LINK_COMPONENTS := DebugInfoPDB support
+
+include $(LEVEL)/Makefile.config
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp b/gnu/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
new file mode 100644
index 00000000000..ebd3d7bb6b3
--- /dev/null
+++ b/gnu/llvm/unittests/DebugInfo/PDB/PDBApiTest.cpp
@@ -0,0 +1,397 @@
+//===- llvm/unittest/DebugInfo/PDB/PDBApiTest.cpp -------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <unordered_map>
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+#define MOCK_SYMBOL_ACCESSOR(Func) \
+ decltype(std::declval<IPDBRawSymbol>().Func()) Func() const override { \
+ typedef decltype(IPDBRawSymbol::Func()) ReturnType; \
+ return ReturnType(); \
+ }
+
+class MockSession : public IPDBSession {
+ uint64_t getLoadAddress() const override { return 0; }
+ void setLoadAddress(uint64_t Address) override {}
+ std::unique_ptr<PDBSymbolExe> getGlobalScope() const override {
+ return nullptr;
+ }
+ std::unique_ptr<PDBSymbol> getSymbolById(uint32_t SymbolId) const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBSourceFile>
+ getSourceFileById(uint32_t SymbolId) const override {
+ return nullptr;
+ }
+
+ std::unique_ptr<PDBSymbol>
+ findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByAddress(uint64_t Address, uint32_t Length) const override {
+ return nullptr;
+ }
+
+ std::unique_ptr<IPDBEnumSourceFiles> getAllSourceFiles() const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBEnumSourceFiles> getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const override {
+ return nullptr;
+ }
+
+ std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override {
+ return nullptr;
+ }
+};
+
+class MockRawSymbol : public IPDBRawSymbol {
+public:
+ MockRawSymbol(PDB_SymType SymType)
+ : Type(SymType) {}
+
+ void dump(raw_ostream &OS, int Indent) const override {}
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildrenByRVA(PDB_SymType Type, StringRef Name, PDB_NameSearchFlags Flags,
+ uint32_t RVA) const override {
+ return nullptr;
+ }
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByRVA(uint32_t RVA) const override {
+ return nullptr;
+ }
+
+ void getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const override {}
+ void getFrontEndVersion(VersionInfo &Version) const override {}
+ void getBackEndVersion(VersionInfo &Version) const override {}
+
+ PDB_SymType getSymTag() const override { return Type; }
+
+ MOCK_SYMBOL_ACCESSOR(getAccess)
+ MOCK_SYMBOL_ACCESSOR(getAddressOffset)
+ MOCK_SYMBOL_ACCESSOR(getAddressSection)
+ MOCK_SYMBOL_ACCESSOR(getAge)
+ MOCK_SYMBOL_ACCESSOR(getArrayIndexTypeId)
+ MOCK_SYMBOL_ACCESSOR(getBaseDataOffset)
+ MOCK_SYMBOL_ACCESSOR(getBaseDataSlot)
+ MOCK_SYMBOL_ACCESSOR(getBaseSymbolId)
+ MOCK_SYMBOL_ACCESSOR(getBuiltinType)
+ MOCK_SYMBOL_ACCESSOR(getBitPosition)
+ MOCK_SYMBOL_ACCESSOR(getCallingConvention)
+ MOCK_SYMBOL_ACCESSOR(getClassParentId)
+ MOCK_SYMBOL_ACCESSOR(getCompilerName)
+ MOCK_SYMBOL_ACCESSOR(getCount)
+ MOCK_SYMBOL_ACCESSOR(getCountLiveRanges)
+ MOCK_SYMBOL_ACCESSOR(getLanguage)
+ MOCK_SYMBOL_ACCESSOR(getLexicalParentId)
+ MOCK_SYMBOL_ACCESSOR(getLibraryName)
+ MOCK_SYMBOL_ACCESSOR(getLiveRangeStartAddressOffset)
+ MOCK_SYMBOL_ACCESSOR(getLiveRangeStartAddressSection)
+ MOCK_SYMBOL_ACCESSOR(getLiveRangeStartRelativeVirtualAddress)
+ MOCK_SYMBOL_ACCESSOR(getLocalBasePointerRegisterId)
+ MOCK_SYMBOL_ACCESSOR(getLowerBoundId)
+ MOCK_SYMBOL_ACCESSOR(getMemorySpaceKind)
+ MOCK_SYMBOL_ACCESSOR(getName)
+ MOCK_SYMBOL_ACCESSOR(getNumberOfAcceleratorPointerTags)
+ MOCK_SYMBOL_ACCESSOR(getNumberOfColumns)
+ MOCK_SYMBOL_ACCESSOR(getNumberOfModifiers)
+ MOCK_SYMBOL_ACCESSOR(getNumberOfRegisterIndices)
+ MOCK_SYMBOL_ACCESSOR(getNumberOfRows)
+ MOCK_SYMBOL_ACCESSOR(getObjectFileName)
+ MOCK_SYMBOL_ACCESSOR(getOemId)
+ MOCK_SYMBOL_ACCESSOR(getOemSymbolId)
+ MOCK_SYMBOL_ACCESSOR(getOffsetInUdt)
+ MOCK_SYMBOL_ACCESSOR(getPlatform)
+ MOCK_SYMBOL_ACCESSOR(getRank)
+ MOCK_SYMBOL_ACCESSOR(getRegisterId)
+ MOCK_SYMBOL_ACCESSOR(getRegisterType)
+ MOCK_SYMBOL_ACCESSOR(getRelativeVirtualAddress)
+ MOCK_SYMBOL_ACCESSOR(getSamplerSlot)
+ MOCK_SYMBOL_ACCESSOR(getSignature)
+ MOCK_SYMBOL_ACCESSOR(getSizeInUdt)
+ MOCK_SYMBOL_ACCESSOR(getSlot)
+ MOCK_SYMBOL_ACCESSOR(getSourceFileName)
+ MOCK_SYMBOL_ACCESSOR(getStride)
+ MOCK_SYMBOL_ACCESSOR(getSubTypeId)
+ MOCK_SYMBOL_ACCESSOR(getSymbolsFileName)
+ MOCK_SYMBOL_ACCESSOR(getSymIndexId)
+ MOCK_SYMBOL_ACCESSOR(getTargetOffset)
+ MOCK_SYMBOL_ACCESSOR(getTargetRelativeVirtualAddress)
+ MOCK_SYMBOL_ACCESSOR(getTargetVirtualAddress)
+ MOCK_SYMBOL_ACCESSOR(getTargetSection)
+ MOCK_SYMBOL_ACCESSOR(getTextureSlot)
+ MOCK_SYMBOL_ACCESSOR(getTimeStamp)
+ MOCK_SYMBOL_ACCESSOR(getToken)
+ MOCK_SYMBOL_ACCESSOR(getTypeId)
+ MOCK_SYMBOL_ACCESSOR(getUavSlot)
+ MOCK_SYMBOL_ACCESSOR(getUndecoratedName)
+ MOCK_SYMBOL_ACCESSOR(getUnmodifiedTypeId)
+ MOCK_SYMBOL_ACCESSOR(getUpperBoundId)
+ MOCK_SYMBOL_ACCESSOR(getVirtualBaseDispIndex)
+ MOCK_SYMBOL_ACCESSOR(getVirtualBaseOffset)
+ MOCK_SYMBOL_ACCESSOR(getVirtualTableShapeId)
+ MOCK_SYMBOL_ACCESSOR(getDataKind)
+ MOCK_SYMBOL_ACCESSOR(getGuid)
+ MOCK_SYMBOL_ACCESSOR(getOffset)
+ MOCK_SYMBOL_ACCESSOR(getThisAdjust)
+ MOCK_SYMBOL_ACCESSOR(getVirtualBasePointerOffset)
+ MOCK_SYMBOL_ACCESSOR(getLocationType)
+ MOCK_SYMBOL_ACCESSOR(getMachineType)
+ MOCK_SYMBOL_ACCESSOR(getThunkOrdinal)
+ MOCK_SYMBOL_ACCESSOR(getLength)
+ MOCK_SYMBOL_ACCESSOR(getLiveRangeLength)
+ MOCK_SYMBOL_ACCESSOR(getVirtualAddress)
+ MOCK_SYMBOL_ACCESSOR(getUdtKind)
+ MOCK_SYMBOL_ACCESSOR(hasConstructor)
+ MOCK_SYMBOL_ACCESSOR(hasCustomCallingConvention)
+ MOCK_SYMBOL_ACCESSOR(hasFarReturn)
+ MOCK_SYMBOL_ACCESSOR(isCode)
+ MOCK_SYMBOL_ACCESSOR(isCompilerGenerated)
+ MOCK_SYMBOL_ACCESSOR(isConstType)
+ MOCK_SYMBOL_ACCESSOR(isEditAndContinueEnabled)
+ MOCK_SYMBOL_ACCESSOR(isFunction)
+ MOCK_SYMBOL_ACCESSOR(getAddressTaken)
+ MOCK_SYMBOL_ACCESSOR(getNoStackOrdering)
+ MOCK_SYMBOL_ACCESSOR(hasAlloca)
+ MOCK_SYMBOL_ACCESSOR(hasAssignmentOperator)
+ MOCK_SYMBOL_ACCESSOR(hasCTypes)
+ MOCK_SYMBOL_ACCESSOR(hasCastOperator)
+ MOCK_SYMBOL_ACCESSOR(hasDebugInfo)
+ MOCK_SYMBOL_ACCESSOR(hasEH)
+ MOCK_SYMBOL_ACCESSOR(hasEHa)
+ MOCK_SYMBOL_ACCESSOR(hasFramePointer)
+ MOCK_SYMBOL_ACCESSOR(hasInlAsm)
+ MOCK_SYMBOL_ACCESSOR(hasInlineAttribute)
+ MOCK_SYMBOL_ACCESSOR(hasInterruptReturn)
+ MOCK_SYMBOL_ACCESSOR(hasLongJump)
+ MOCK_SYMBOL_ACCESSOR(hasManagedCode)
+ MOCK_SYMBOL_ACCESSOR(hasNestedTypes)
+ MOCK_SYMBOL_ACCESSOR(hasNoInlineAttribute)
+ MOCK_SYMBOL_ACCESSOR(hasNoReturnAttribute)
+ MOCK_SYMBOL_ACCESSOR(hasOptimizedCodeDebugInfo)
+ MOCK_SYMBOL_ACCESSOR(hasOverloadedOperator)
+ MOCK_SYMBOL_ACCESSOR(hasSEH)
+ MOCK_SYMBOL_ACCESSOR(hasSecurityChecks)
+ MOCK_SYMBOL_ACCESSOR(hasSetJump)
+ MOCK_SYMBOL_ACCESSOR(hasStrictGSCheck)
+ MOCK_SYMBOL_ACCESSOR(isAcceleratorGroupSharedLocal)
+ MOCK_SYMBOL_ACCESSOR(isAcceleratorPointerTagLiveRange)
+ MOCK_SYMBOL_ACCESSOR(isAcceleratorStubFunction)
+ MOCK_SYMBOL_ACCESSOR(isAggregated)
+ MOCK_SYMBOL_ACCESSOR(isIntroVirtualFunction)
+ MOCK_SYMBOL_ACCESSOR(isCVTCIL)
+ MOCK_SYMBOL_ACCESSOR(isConstructorVirtualBase)
+ MOCK_SYMBOL_ACCESSOR(isCxxReturnUdt)
+ MOCK_SYMBOL_ACCESSOR(isDataAligned)
+ MOCK_SYMBOL_ACCESSOR(isHLSLData)
+ MOCK_SYMBOL_ACCESSOR(isHotpatchable)
+ MOCK_SYMBOL_ACCESSOR(isIndirectVirtualBaseClass)
+ MOCK_SYMBOL_ACCESSOR(isInterfaceUdt)
+ MOCK_SYMBOL_ACCESSOR(isIntrinsic)
+ MOCK_SYMBOL_ACCESSOR(isLTCG)
+ MOCK_SYMBOL_ACCESSOR(isLocationControlFlowDependent)
+ MOCK_SYMBOL_ACCESSOR(isMSILNetmodule)
+ MOCK_SYMBOL_ACCESSOR(isMatrixRowMajor)
+ MOCK_SYMBOL_ACCESSOR(isManagedCode)
+ MOCK_SYMBOL_ACCESSOR(isMSILCode)
+ MOCK_SYMBOL_ACCESSOR(isMultipleInheritance)
+ MOCK_SYMBOL_ACCESSOR(isNaked)
+ MOCK_SYMBOL_ACCESSOR(isNested)
+ MOCK_SYMBOL_ACCESSOR(isOptimizedAway)
+ MOCK_SYMBOL_ACCESSOR(isPacked)
+ MOCK_SYMBOL_ACCESSOR(isPointerBasedOnSymbolValue)
+ MOCK_SYMBOL_ACCESSOR(isPointerToDataMember)
+ MOCK_SYMBOL_ACCESSOR(isPointerToMemberFunction)
+ MOCK_SYMBOL_ACCESSOR(isPureVirtual)
+ MOCK_SYMBOL_ACCESSOR(isRValueReference)
+ MOCK_SYMBOL_ACCESSOR(isRefUdt)
+ MOCK_SYMBOL_ACCESSOR(isReference)
+ MOCK_SYMBOL_ACCESSOR(isRestrictedType)
+ MOCK_SYMBOL_ACCESSOR(isReturnValue)
+ MOCK_SYMBOL_ACCESSOR(isSafeBuffers)
+ MOCK_SYMBOL_ACCESSOR(isScoped)
+ MOCK_SYMBOL_ACCESSOR(isSdl)
+ MOCK_SYMBOL_ACCESSOR(isSingleInheritance)
+ MOCK_SYMBOL_ACCESSOR(isSplitted)
+ MOCK_SYMBOL_ACCESSOR(isStatic)
+ MOCK_SYMBOL_ACCESSOR(hasPrivateSymbols)
+ MOCK_SYMBOL_ACCESSOR(isUnalignedType)
+ MOCK_SYMBOL_ACCESSOR(isUnreached)
+ MOCK_SYMBOL_ACCESSOR(isValueUdt)
+ MOCK_SYMBOL_ACCESSOR(isVirtual)
+ MOCK_SYMBOL_ACCESSOR(isVirtualBaseClass)
+ MOCK_SYMBOL_ACCESSOR(isVirtualInheritance)
+ MOCK_SYMBOL_ACCESSOR(isVolatileType)
+ MOCK_SYMBOL_ACCESSOR(getValue)
+ MOCK_SYMBOL_ACCESSOR(wasInlined)
+ MOCK_SYMBOL_ACCESSOR(getUnused)
+
+private:
+ PDB_SymType Type;
+};
+
+class PDBApiTest : public testing::Test {
+public:
+ std::unordered_map<PDB_SymType, std::unique_ptr<PDBSymbol>> SymbolMap;
+
+ void SetUp() override {
+ Session.reset(new MockSession());
+
+ InsertItemWithTag(PDB_SymType::None);
+ InsertItemWithTag(PDB_SymType::Exe);
+ InsertItemWithTag(PDB_SymType::Compiland);
+ InsertItemWithTag(PDB_SymType::CompilandDetails);
+ InsertItemWithTag(PDB_SymType::CompilandEnv);
+ InsertItemWithTag(PDB_SymType::Function);
+ InsertItemWithTag(PDB_SymType::Block);
+ InsertItemWithTag(PDB_SymType::Data);
+ InsertItemWithTag(PDB_SymType::Annotation);
+ InsertItemWithTag(PDB_SymType::Label);
+ InsertItemWithTag(PDB_SymType::PublicSymbol);
+ InsertItemWithTag(PDB_SymType::UDT);
+ InsertItemWithTag(PDB_SymType::Enum);
+ InsertItemWithTag(PDB_SymType::FunctionSig);
+ InsertItemWithTag(PDB_SymType::PointerType);
+ InsertItemWithTag(PDB_SymType::ArrayType);
+ InsertItemWithTag(PDB_SymType::BuiltinType);
+ InsertItemWithTag(PDB_SymType::Typedef);
+ InsertItemWithTag(PDB_SymType::BaseClass);
+ InsertItemWithTag(PDB_SymType::Friend);
+ InsertItemWithTag(PDB_SymType::FunctionArg);
+ InsertItemWithTag(PDB_SymType::FuncDebugStart);
+ InsertItemWithTag(PDB_SymType::FuncDebugEnd);
+ InsertItemWithTag(PDB_SymType::UsingNamespace);
+ InsertItemWithTag(PDB_SymType::VTableShape);
+ InsertItemWithTag(PDB_SymType::VTable);
+ InsertItemWithTag(PDB_SymType::Custom);
+ InsertItemWithTag(PDB_SymType::Thunk);
+ InsertItemWithTag(PDB_SymType::CustomType);
+ InsertItemWithTag(PDB_SymType::ManagedType);
+ InsertItemWithTag(PDB_SymType::Dimension);
+ InsertItemWithTag(PDB_SymType::Max);
+ }
+
+ template <class ExpectedType> void VerifyDyncast(PDB_SymType Tag) {
+ for (auto item = SymbolMap.begin(); item != SymbolMap.end(); ++item) {
+ EXPECT_EQ(item->first == Tag, llvm::isa<ExpectedType>(*item->second));
+ }
+ }
+
+ void VerifyUnknownDyncasts() {
+ for (auto item = SymbolMap.begin(); item != SymbolMap.end(); ++item) {
+ bool should_match = false;
+ if (item->first == PDB_SymType::None || item->first >= PDB_SymType::Max)
+ should_match = true;
+
+ EXPECT_EQ(should_match, llvm::isa<PDBSymbolUnknown>(*item->second));
+ }
+ }
+
+private:
+ std::unique_ptr<IPDBSession> Session;
+
+ void InsertItemWithTag(PDB_SymType Tag) {
+ auto RawSymbol = llvm::make_unique<MockRawSymbol>(Tag);
+ auto Symbol = PDBSymbol::create(*Session, std::move(RawSymbol));
+ SymbolMap.insert(std::make_pair(Tag, std::move(Symbol)));
+ }
+};
+
+TEST_F(PDBApiTest, Dyncast) {
+
+ // Most of the types have a one-to-one mapping between Tag and concrete type.
+ VerifyDyncast<PDBSymbolExe>(PDB_SymType::Exe);
+ VerifyDyncast<PDBSymbolCompiland>(PDB_SymType::Compiland);
+ VerifyDyncast<PDBSymbolCompilandDetails>(PDB_SymType::CompilandDetails);
+ VerifyDyncast<PDBSymbolCompilandEnv>(PDB_SymType::CompilandEnv);
+ VerifyDyncast<PDBSymbolFunc>(PDB_SymType::Function);
+ VerifyDyncast<PDBSymbolBlock>(PDB_SymType::Block);
+ VerifyDyncast<PDBSymbolData>(PDB_SymType::Data);
+ VerifyDyncast<PDBSymbolAnnotation>(PDB_SymType::Annotation);
+ VerifyDyncast<PDBSymbolLabel>(PDB_SymType::Label);
+ VerifyDyncast<PDBSymbolPublicSymbol>(PDB_SymType::PublicSymbol);
+ VerifyDyncast<PDBSymbolTypeUDT>(PDB_SymType::UDT);
+ VerifyDyncast<PDBSymbolTypeEnum>(PDB_SymType::Enum);
+ VerifyDyncast<PDBSymbolTypeFunctionSig>(PDB_SymType::FunctionSig);
+ VerifyDyncast<PDBSymbolTypePointer>(PDB_SymType::PointerType);
+ VerifyDyncast<PDBSymbolTypeArray>(PDB_SymType::ArrayType);
+ VerifyDyncast<PDBSymbolTypeBuiltin>(PDB_SymType::BuiltinType);
+ VerifyDyncast<PDBSymbolTypeTypedef>(PDB_SymType::Typedef);
+ VerifyDyncast<PDBSymbolTypeBaseClass>(PDB_SymType::BaseClass);
+ VerifyDyncast<PDBSymbolTypeFriend>(PDB_SymType::Friend);
+ VerifyDyncast<PDBSymbolTypeFunctionArg>(PDB_SymType::FunctionArg);
+ VerifyDyncast<PDBSymbolFuncDebugStart>(PDB_SymType::FuncDebugStart);
+ VerifyDyncast<PDBSymbolFuncDebugEnd>(PDB_SymType::FuncDebugEnd);
+ VerifyDyncast<PDBSymbolUsingNamespace>(PDB_SymType::UsingNamespace);
+ VerifyDyncast<PDBSymbolTypeVTableShape>(PDB_SymType::VTableShape);
+ VerifyDyncast<PDBSymbolTypeVTable>(PDB_SymType::VTable);
+ VerifyDyncast<PDBSymbolCustom>(PDB_SymType::Custom);
+ VerifyDyncast<PDBSymbolThunk>(PDB_SymType::Thunk);
+ VerifyDyncast<PDBSymbolTypeCustom>(PDB_SymType::CustomType);
+ VerifyDyncast<PDBSymbolTypeManaged>(PDB_SymType::ManagedType);
+ VerifyDyncast<PDBSymbolTypeDimension>(PDB_SymType::Dimension);
+
+ VerifyUnknownDyncasts();
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ExecutionEngine/CMakeLists.txt b/gnu/llvm/unittests/ExecutionEngine/CMakeLists.txt
new file mode 100644
index 00000000000..302de9943ff
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/CMakeLists.txt
@@ -0,0 +1,22 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ ExecutionEngine
+ Interpreter
+ MC
+ OrcJIT
+ RuntimeDyld
+ Support
+ )
+
+add_llvm_unittest(ExecutionEngineTests
+ ExecutionEngineTest.cpp
+ )
+
+add_subdirectory(Orc)
+
+# Include MCJIT tests only if native arch is a built JIT target.
+list(FIND LLVM_TARGETS_TO_BUILD "${LLVM_NATIVE_ARCH}" build_idx)
+list(FIND LLVM_TARGETS_WITH_JIT "${LLVM_NATIVE_ARCH}" jit_idx)
+if (NOT build_idx LESS 0 AND NOT jit_idx LESS 0)
+ add_subdirectory(MCJIT)
+endif()
diff --git a/gnu/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp b/gnu/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp
new file mode 100644
index 00000000000..bb47c4c0030
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/ExecutionEngineTest.cpp
@@ -0,0 +1,170 @@
+//===- ExecutionEngineTest.cpp - Unit tests for ExecutionEngine -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Interpreter.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class ExecutionEngineTest : public testing::Test {
+private:
+ llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
+
+protected:
+ ExecutionEngineTest() {
+ auto Owner = make_unique<Module>("<main>", getGlobalContext());
+ M = Owner.get();
+ Engine.reset(EngineBuilder(std::move(Owner)).setErrorStr(&Error).create());
+ }
+
+ void SetUp() override {
+ ASSERT_TRUE(Engine.get() != nullptr) << "EngineBuilder returned error: '"
+ << Error << "'";
+ }
+
+ GlobalVariable *NewExtGlobal(Type *T, const Twine &Name) {
+ return new GlobalVariable(*M, T, false, // Not constant.
+ GlobalValue::ExternalLinkage, nullptr, Name);
+ }
+
+ std::string Error;
+ Module *M; // Owned by ExecutionEngine.
+ std::unique_ptr<ExecutionEngine> Engine;
+};
+
+TEST_F(ExecutionEngineTest, ForwardGlobalMapping) {
+ GlobalVariable *G1 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
+ int32_t Mem1 = 3;
+ Engine->addGlobalMapping(G1, &Mem1);
+ EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G1));
+ EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable("Global1"));
+ int32_t Mem2 = 4;
+ Engine->updateGlobalMapping(G1, &Mem2);
+ EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
+ Engine->updateGlobalMapping(G1, nullptr);
+ EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G1));
+ Engine->updateGlobalMapping(G1, &Mem2);
+ EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1));
+
+ GlobalVariable *G2 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
+ EXPECT_EQ(nullptr, Engine->getPointerToGlobalIfAvailable(G2))
+ << "The NULL return shouldn't depend on having called"
+ << " updateGlobalMapping(..., NULL)";
+ // Check that update...() can be called before add...().
+ Engine->updateGlobalMapping(G2, &Mem1);
+ EXPECT_EQ(&Mem1, Engine->getPointerToGlobalIfAvailable(G2));
+ EXPECT_EQ(&Mem2, Engine->getPointerToGlobalIfAvailable(G1))
+ << "A second mapping shouldn't affect the first.";
+}
+
+TEST_F(ExecutionEngineTest, ReverseGlobalMapping) {
+ GlobalVariable *G1 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
+
+ int32_t Mem1 = 3;
+ Engine->addGlobalMapping(G1, &Mem1);
+ EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
+ int32_t Mem2 = 4;
+ Engine->updateGlobalMapping(G1, &Mem2);
+ EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
+ EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
+
+ GlobalVariable *G2 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2");
+ Engine->updateGlobalMapping(G2, &Mem1);
+ EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
+ EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem2));
+ Engine->updateGlobalMapping(G1, nullptr);
+ EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1))
+ << "Removing one mapping doesn't affect a different one.";
+ EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem2));
+ Engine->updateGlobalMapping(G2, &Mem2);
+ EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
+ EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem2))
+ << "Once a mapping is removed, we can point another GV at the"
+ << " now-free address.";
+}
+
+TEST_F(ExecutionEngineTest, ClearModuleMappings) {
+ GlobalVariable *G1 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
+
+ int32_t Mem1 = 3;
+ Engine->addGlobalMapping(G1, &Mem1);
+ EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
+
+ Engine->clearGlobalMappingsFromModule(M);
+
+ EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
+
+ GlobalVariable *G2 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global2");
+ // After clearing the module mappings, we can assign a new GV to the
+ // same address.
+ Engine->addGlobalMapping(G2, &Mem1);
+ EXPECT_EQ(G2, Engine->getGlobalValueAtAddress(&Mem1));
+}
+
+TEST_F(ExecutionEngineTest, DestructionRemovesGlobalMapping) {
+ GlobalVariable *G1 =
+ NewExtGlobal(Type::getInt32Ty(getGlobalContext()), "Global1");
+ int32_t Mem1 = 3;
+ Engine->addGlobalMapping(G1, &Mem1);
+ // Make sure the reverse mapping is enabled.
+ EXPECT_EQ(G1, Engine->getGlobalValueAtAddress(&Mem1));
+ // When the GV goes away, the ExecutionEngine should remove any
+ // mappings that refer to it.
+ G1->eraseFromParent();
+ EXPECT_EQ(nullptr, Engine->getGlobalValueAtAddress(&Mem1));
+}
+
+TEST_F(ExecutionEngineTest, LookupWithMangledName) {
+ int x;
+ llvm::sys::DynamicLibrary::AddSymbol("x", &x);
+
+ // Demonstrate that getSymbolAddress accepts mangled names and always strips
+ // the leading underscore.
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
+TEST_F(ExecutionEngineTest, LookupWithMangledAndDemangledSymbol) {
+ int x;
+ int _x;
+ llvm::sys::DynamicLibrary::AddSymbol("x", &x);
+ llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
+
+ // Lookup the demangled name first, even if there's a demangled symbol that
+ // matches the input already.
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
+TEST_F(ExecutionEngineTest, LookupwithDemangledName) {
+ int _x;
+ llvm::sys::DynamicLibrary::AddSymbol("_x", &_x);
+
+ // But do fallback to looking up a demangled name if there's no ambiguity
+ EXPECT_EQ(reinterpret_cast<uint64_t>(&_x),
+ RTDyldMemoryManager::getSymbolAddressInProcess("_x"));
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt b/gnu/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
new file mode 100644
index 00000000000..e29787f8f42
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/CMakeLists.txt
@@ -0,0 +1,33 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ Core
+ ExecutionEngine
+ IPO
+ MC
+ MCJIT
+ RuntimeDyld
+ ScalarOpts
+ Support
+ Target
+ nativecodegen
+ )
+
+set(MCJITTestsSources
+ MCJITTest.cpp
+ MCJITCAPITest.cpp
+ MCJITMemoryManagerTest.cpp
+ MCJITMultipleModuleTest.cpp
+ MCJITObjectCacheTest.cpp
+ )
+
+if(MSVC)
+ list(APPEND MCJITTestsSources MCJITTests.def)
+endif()
+
+add_llvm_unittest(MCJITTests
+ ${MCJITTestsSources}
+ )
+
+if(MINGW OR CYGWIN)
+ set_property(TARGET MCJITTests PROPERTY LINK_FLAGS -Wl,--export-all-symbols)
+endif()
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
new file mode 100644
index 00000000000..c8c244d22ed
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp
@@ -0,0 +1,510 @@
+//===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This test suite verifies basic MCJIT functionality when invoked form the C
+// API.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Analysis.h"
+#include "MCJITTestAPICommon.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/ExecutionEngine.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/Transforms/PassManagerBuilder.h"
+#include "llvm-c/Transforms/Scalar.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Host.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static bool didCallAllocateCodeSection;
+static bool didAllocateCompactUnwindSection;
+static bool didCallYield;
+
+static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
+ unsigned alignment,
+ unsigned sectionID,
+ const char *sectionName) {
+ didCallAllocateCodeSection = true;
+ return static_cast<SectionMemoryManager*>(object)->allocateCodeSection(
+ size, alignment, sectionID, sectionName);
+}
+
+static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size,
+ unsigned alignment,
+ unsigned sectionID,
+ const char *sectionName,
+ LLVMBool isReadOnly) {
+ if (!strcmp(sectionName, "__compact_unwind"))
+ didAllocateCompactUnwindSection = true;
+ return static_cast<SectionMemoryManager*>(object)->allocateDataSection(
+ size, alignment, sectionID, sectionName, isReadOnly);
+}
+
+static LLVMBool roundTripFinalizeMemory(void *object, char **errMsg) {
+ std::string errMsgString;
+ bool result =
+ static_cast<SectionMemoryManager*>(object)->finalizeMemory(&errMsgString);
+ if (result) {
+ *errMsg = LLVMCreateMessage(errMsgString.c_str());
+ return 1;
+ }
+ return 0;
+}
+
+static void roundTripDestroy(void *object) {
+ delete static_cast<SectionMemoryManager*>(object);
+}
+
+static void yield(LLVMContextRef, void *) {
+ didCallYield = true;
+}
+
+namespace {
+
+// memory manager to test reserve allocation space callback
+class TestReserveAllocationSpaceMemoryManager: public SectionMemoryManager {
+public:
+ uintptr_t ReservedCodeSize;
+ uintptr_t UsedCodeSize;
+ uintptr_t ReservedDataSizeRO;
+ uintptr_t UsedDataSizeRO;
+ uintptr_t ReservedDataSizeRW;
+ uintptr_t UsedDataSizeRW;
+
+ TestReserveAllocationSpaceMemoryManager() :
+ ReservedCodeSize(0), UsedCodeSize(0), ReservedDataSizeRO(0),
+ UsedDataSizeRO(0), ReservedDataSizeRW(0), UsedDataSizeRW(0) {
+ }
+
+ bool needsToReserveAllocationSpace() override { return true; }
+
+ void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
+ uintptr_t DataSizeRO, uint32_t RODataAlign,
+ uintptr_t DataSizeRW, uint32_t RWDataAlign) override {
+ ReservedCodeSize = CodeSize;
+ ReservedDataSizeRO = DataSizeRO;
+ ReservedDataSizeRW = DataSizeRW;
+ }
+
+ void useSpace(uintptr_t* UsedSize, uintptr_t Size, unsigned Alignment) {
+ uintptr_t AlignedSize = (Size + Alignment - 1) / Alignment * Alignment;
+ uintptr_t AlignedBegin = (*UsedSize + Alignment - 1) / Alignment * Alignment;
+ *UsedSize = AlignedBegin + AlignedSize;
+ }
+
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID, StringRef SectionName,
+ bool IsReadOnly) override {
+ useSpace(IsReadOnly ? &UsedDataSizeRO : &UsedDataSizeRW, Size, Alignment);
+ return SectionMemoryManager::allocateDataSection(Size, Alignment,
+ SectionID, SectionName, IsReadOnly);
+ }
+
+ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) override {
+ useSpace(&UsedCodeSize, Size, Alignment);
+ return SectionMemoryManager::allocateCodeSection(Size, Alignment,
+ SectionID, SectionName);
+ }
+};
+
+class MCJITCAPITest : public testing::Test, public MCJITTestAPICommon {
+protected:
+ MCJITCAPITest() {
+ // The architectures below are known to be compatible with MCJIT as they
+ // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
+ // kept in sync.
+ SupportedArchs.push_back(Triple::aarch64);
+ SupportedArchs.push_back(Triple::arm);
+ SupportedArchs.push_back(Triple::mips);
+ SupportedArchs.push_back(Triple::mips64);
+ SupportedArchs.push_back(Triple::mips64el);
+ SupportedArchs.push_back(Triple::x86);
+ SupportedArchs.push_back(Triple::x86_64);
+
+ // Some architectures have sub-architectures in which tests will fail, like
+ // ARM. These two vectors will define if they do have sub-archs (to avoid
+ // extra work for those who don't), and if so, if they are listed to work
+ HasSubArchs.push_back(Triple::arm);
+ SupportedSubArchs.push_back("armv6");
+ SupportedSubArchs.push_back("armv7");
+
+ // The operating systems below are known to be sufficiently incompatible
+ // that they will fail the MCJIT C API tests.
+ UnsupportedEnvironments.push_back(Triple::Cygnus);
+ }
+
+ void SetUp() override {
+ didCallAllocateCodeSection = false;
+ didAllocateCompactUnwindSection = false;
+ didCallYield = false;
+ Module = nullptr;
+ Function = nullptr;
+ Engine = nullptr;
+ Error = nullptr;
+ }
+
+ void TearDown() override {
+ if (Engine)
+ LLVMDisposeExecutionEngine(Engine);
+ else if (Module)
+ LLVMDisposeModule(Module);
+ }
+
+ void buildSimpleFunction() {
+ Module = LLVMModuleCreateWithName("simple_module");
+
+ LLVMSetTarget(Module, HostTriple.c_str());
+
+ Function = LLVMAddFunction(Module, "simple_function",
+ LLVMFunctionType(LLVMInt32Type(), nullptr,0, 0));
+ LLVMSetFunctionCallConv(Function, LLVMCCallConv);
+
+ LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
+ LLVMBuilderRef builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, entry);
+ LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ LLVMDisposeBuilder(builder);
+ }
+
+ void buildFunctionThatUsesStackmap() {
+ Module = LLVMModuleCreateWithName("simple_module");
+
+ LLVMSetTarget(Module, HostTriple.c_str());
+
+ LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
+ LLVMValueRef stackmap = LLVMAddFunction(
+ Module, "llvm.experimental.stackmap",
+ LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1));
+ LLVMSetLinkage(stackmap, LLVMExternalLinkage);
+
+ Function = LLVMAddFunction(Module, "simple_function",
+ LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
+
+ LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
+ LLVMBuilderRef builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(builder, entry);
+ LLVMValueRef stackmapArgs[] = {
+ LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
+ LLVMConstInt(LLVMInt32Type(), 42, 0)
+ };
+ LLVMBuildCall(builder, stackmap, stackmapArgs, 3, "");
+ LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ LLVMDisposeBuilder(builder);
+ }
+
+ void buildModuleWithCodeAndData() {
+ Module = LLVMModuleCreateWithName("simple_module");
+
+ LLVMSetTarget(Module, HostTriple.c_str());
+
+ // build a global int32 variable initialized to 42.
+ LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "intVal");
+ LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
+
+ {
+ Function = LLVMAddFunction(Module, "getGlobal",
+ LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0));
+ LLVMSetFunctionCallConv(Function, LLVMCCallConv);
+
+ LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "entry");
+ LLVMBuilderRef Builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(Builder, Entry);
+
+ LLVMValueRef IntVal = LLVMBuildLoad(Builder, GlobalVar, "intVal");
+ LLVMBuildRet(Builder, IntVal);
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ LLVMDisposeBuilder(Builder);
+ }
+
+ {
+ LLVMTypeRef ParamTypes[] = { LLVMInt32Type() };
+ Function2 = LLVMAddFunction(
+ Module, "setGlobal", LLVMFunctionType(LLVMVoidType(), ParamTypes, 1, 0));
+ LLVMSetFunctionCallConv(Function2, LLVMCCallConv);
+
+ LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function2, "entry");
+ LLVMBuilderRef Builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(Builder, Entry);
+
+ LLVMValueRef Arg = LLVMGetParam(Function2, 0);
+ LLVMBuildStore(Builder, Arg, GlobalVar);
+ LLVMBuildRetVoid(Builder);
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ LLVMDisposeBuilder(Builder);
+ }
+ }
+
+ void buildMCJITOptions() {
+ LLVMInitializeMCJITCompilerOptions(&Options, sizeof(Options));
+ Options.OptLevel = 2;
+
+ // Just ensure that this field still exists.
+ Options.NoFramePointerElim = false;
+ }
+
+ void useRoundTripSectionMemoryManager() {
+ Options.MCJMM = LLVMCreateSimpleMCJITMemoryManager(
+ new SectionMemoryManager(),
+ roundTripAllocateCodeSection,
+ roundTripAllocateDataSection,
+ roundTripFinalizeMemory,
+ roundTripDestroy);
+ }
+
+ void buildMCJITEngine() {
+ ASSERT_EQ(
+ 0, LLVMCreateMCJITCompilerForModule(&Engine, Module, &Options,
+ sizeof(Options), &Error));
+ }
+
+ void buildAndRunPasses() {
+ LLVMPassManagerRef pass = LLVMCreatePassManager();
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), pass);
+ LLVMAddConstantPropagationPass(pass);
+ LLVMAddInstructionCombiningPass(pass);
+ LLVMRunPassManager(pass, Module);
+ LLVMDisposePassManager(pass);
+ }
+
+ void buildAndRunOptPasses() {
+ LLVMPassManagerBuilderRef passBuilder;
+
+ passBuilder = LLVMPassManagerBuilderCreate();
+ LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
+ LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
+
+ LLVMPassManagerRef functionPasses =
+ LLVMCreateFunctionPassManagerForModule(Module);
+ LLVMPassManagerRef modulePasses =
+ LLVMCreatePassManager();
+
+ LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses);
+
+ LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
+ functionPasses);
+ LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
+
+ LLVMPassManagerBuilderDispose(passBuilder);
+
+ LLVMInitializeFunctionPassManager(functionPasses);
+ for (LLVMValueRef value = LLVMGetFirstFunction(Module);
+ value; value = LLVMGetNextFunction(value))
+ LLVMRunFunctionPassManager(functionPasses, value);
+ LLVMFinalizeFunctionPassManager(functionPasses);
+
+ LLVMRunPassManager(modulePasses, Module);
+
+ LLVMDisposePassManager(functionPasses);
+ LLVMDisposePassManager(modulePasses);
+ }
+
+ LLVMModuleRef Module;
+ LLVMValueRef Function;
+ LLVMValueRef Function2;
+ LLVMMCJITCompilerOptions Options;
+ LLVMExecutionEngineRef Engine;
+ char *Error;
+};
+} // end anonymous namespace
+
+TEST_F(MCJITCAPITest, simple_function) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ buildSimpleFunction();
+ buildMCJITOptions();
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ auto *functionPointer = reinterpret_cast<int (*)()>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
+
+ EXPECT_EQ(42, functionPointer());
+}
+
+TEST_F(MCJITCAPITest, gva) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Module = LLVMModuleCreateWithName("simple_module");
+ LLVMSetTarget(Module, HostTriple.c_str());
+ LLVMValueRef GlobalVar = LLVMAddGlobal(Module, LLVMInt32Type(), "simple_value");
+ LLVMSetInitializer(GlobalVar, LLVMConstInt(LLVMInt32Type(), 42, 0));
+
+ buildMCJITOptions();
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ uint64_t raw = LLVMGetGlobalValueAddress(Engine, "simple_value");
+ int32_t *usable = (int32_t *) raw;
+
+ EXPECT_EQ(42, *usable);
+}
+
+TEST_F(MCJITCAPITest, gfa) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ buildSimpleFunction();
+ buildMCJITOptions();
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ uint64_t raw = LLVMGetFunctionAddress(Engine, "simple_function");
+ int (*usable)() = (int (*)()) raw;
+
+ EXPECT_EQ(42, usable());
+}
+
+TEST_F(MCJITCAPITest, custom_memory_manager) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ buildSimpleFunction();
+ buildMCJITOptions();
+ useRoundTripSectionMemoryManager();
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ auto *functionPointer = reinterpret_cast<int (*)()>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
+
+ EXPECT_EQ(42, functionPointer());
+ EXPECT_TRUE(didCallAllocateCodeSection);
+}
+
+TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ // This test is also not supported on non-x86 platforms.
+ if (Triple(HostTriple).getArch() != Triple::x86_64)
+ return;
+
+ buildFunctionThatUsesStackmap();
+ buildMCJITOptions();
+ useRoundTripSectionMemoryManager();
+ buildMCJITEngine();
+ buildAndRunOptPasses();
+
+ auto *functionPointer = reinterpret_cast<int (*)()>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
+
+ EXPECT_EQ(42, functionPointer());
+ EXPECT_TRUE(didCallAllocateCodeSection);
+
+ // Up to this point, the test is specific only to X86-64. But this next
+ // expectation is only valid on Darwin because it assumes that unwind
+ // data is made available only through compact_unwind. It would be
+ // worthwhile to extend this to handle non-Darwin platforms, in which
+ // case you'd want to look for an eh_frame or something.
+ //
+ // FIXME: Currently, MCJIT relies on a configure-time check to determine which
+ // sections to emit. The JIT client should have runtime control over this.
+ EXPECT_TRUE(
+ Triple(HostTriple).getOS() != Triple::Darwin ||
+ Triple(HostTriple).isMacOSXVersionLT(10, 7) ||
+ didAllocateCompactUnwindSection);
+}
+
+TEST_F(MCJITCAPITest, reserve_allocation_space) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ TestReserveAllocationSpaceMemoryManager* MM = new TestReserveAllocationSpaceMemoryManager();
+
+ buildModuleWithCodeAndData();
+ buildMCJITOptions();
+ Options.MCJMM = wrap(MM);
+ buildMCJITEngine();
+ buildAndRunPasses();
+
+ auto GetGlobalFct = reinterpret_cast<int (*)()>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
+
+ auto SetGlobalFct = reinterpret_cast<void (*)(int)>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function2)));
+
+ SetGlobalFct(789);
+ EXPECT_EQ(789, GetGlobalFct());
+ EXPECT_LE(MM->UsedCodeSize, MM->ReservedCodeSize);
+ EXPECT_LE(MM->UsedDataSizeRO, MM->ReservedDataSizeRO);
+ EXPECT_LE(MM->UsedDataSizeRW, MM->ReservedDataSizeRW);
+ EXPECT_TRUE(MM->UsedCodeSize > 0);
+ EXPECT_TRUE(MM->UsedDataSizeRW > 0);
+}
+
+TEST_F(MCJITCAPITest, yield) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ buildSimpleFunction();
+ buildMCJITOptions();
+ buildMCJITEngine();
+ LLVMContextRef C = LLVMGetGlobalContext();
+ LLVMContextSetYieldCallback(C, yield, nullptr);
+ buildAndRunPasses();
+
+ auto *functionPointer = reinterpret_cast<int (*)()>(
+ reinterpret_cast<uintptr_t>(LLVMGetPointerToGlobal(Engine, Function)));
+
+ EXPECT_EQ(42, functionPointer());
+ EXPECT_TRUE(didCallYield);
+}
+
+static int localTestFunc() {
+ return 42;
+}
+
+TEST_F(MCJITCAPITest, addGlobalMapping) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Module = LLVMModuleCreateWithName("testModule");
+ LLVMSetTarget(Module, HostTriple.c_str());
+ LLVMTypeRef FunctionType = LLVMFunctionType(LLVMInt32Type(), nullptr, 0, 0);
+ LLVMValueRef MappedFn = LLVMAddFunction(Module, "mapped_fn", FunctionType);
+
+ Function = LLVMAddFunction(Module, "test_fn", FunctionType);
+ LLVMBasicBlockRef Entry = LLVMAppendBasicBlock(Function, "");
+ LLVMBuilderRef Builder = LLVMCreateBuilder();
+ LLVMPositionBuilderAtEnd(Builder, Entry);
+ LLVMValueRef RetVal = LLVMBuildCall(Builder, MappedFn, nullptr, 0, "");
+ LLVMBuildRet(Builder, RetVal);
+ LLVMDisposeBuilder(Builder);
+
+ LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
+ LLVMDisposeMessage(Error);
+
+ buildMCJITOptions();
+ buildMCJITEngine();
+
+ LLVMAddGlobalMapping(
+ Engine, MappedFn,
+ reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(&localTestFunc)));
+
+ buildAndRunPasses();
+
+ uint64_t raw = LLVMGetFunctionAddress(Engine, "test_fn");
+ int (*usable)() = (int (*)()) raw;
+
+ EXPECT_EQ(42, usable());
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
new file mode 100644
index 00000000000..0582c92b5f8
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMemoryManagerTest.cpp
@@ -0,0 +1,170 @@
+//===- MCJITMemoryManagerTest.cpp - Unit tests for the JIT memory manager -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(MCJITMemoryManagerTest, BasicAllocations) {
+ std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
+
+ uint8_t *code1 = MemMgr->allocateCodeSection(256, 0, 1, "");
+ uint8_t *data1 = MemMgr->allocateDataSection(256, 0, 2, "", true);
+ uint8_t *code2 = MemMgr->allocateCodeSection(256, 0, 3, "");
+ uint8_t *data2 = MemMgr->allocateDataSection(256, 0, 4, "", false);
+
+ EXPECT_NE((uint8_t*)nullptr, code1);
+ EXPECT_NE((uint8_t*)nullptr, code2);
+ EXPECT_NE((uint8_t*)nullptr, data1);
+ EXPECT_NE((uint8_t*)nullptr, data2);
+
+ // Initialize the data
+ for (unsigned i = 0; i < 256; ++i) {
+ code1[i] = 1;
+ code2[i] = 2;
+ data1[i] = 3;
+ data2[i] = 4;
+ }
+
+ // Verify the data (this is checking for overlaps in the addresses)
+ for (unsigned i = 0; i < 256; ++i) {
+ EXPECT_EQ(1, code1[i]);
+ EXPECT_EQ(2, code2[i]);
+ EXPECT_EQ(3, data1[i]);
+ EXPECT_EQ(4, data2[i]);
+ }
+
+ std::string Error;
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
+}
+
+TEST(MCJITMemoryManagerTest, LargeAllocations) {
+ std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
+
+ uint8_t *code1 = MemMgr->allocateCodeSection(0x100000, 0, 1, "");
+ uint8_t *data1 = MemMgr->allocateDataSection(0x100000, 0, 2, "", true);
+ uint8_t *code2 = MemMgr->allocateCodeSection(0x100000, 0, 3, "");
+ uint8_t *data2 = MemMgr->allocateDataSection(0x100000, 0, 4, "", false);
+
+ EXPECT_NE((uint8_t*)nullptr, code1);
+ EXPECT_NE((uint8_t*)nullptr, code2);
+ EXPECT_NE((uint8_t*)nullptr, data1);
+ EXPECT_NE((uint8_t*)nullptr, data2);
+
+ // Initialize the data
+ for (unsigned i = 0; i < 0x100000; ++i) {
+ code1[i] = 1;
+ code2[i] = 2;
+ data1[i] = 3;
+ data2[i] = 4;
+ }
+
+ // Verify the data (this is checking for overlaps in the addresses)
+ for (unsigned i = 0; i < 0x100000; ++i) {
+ EXPECT_EQ(1, code1[i]);
+ EXPECT_EQ(2, code2[i]);
+ EXPECT_EQ(3, data1[i]);
+ EXPECT_EQ(4, data2[i]);
+ }
+
+ std::string Error;
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
+}
+
+TEST(MCJITMemoryManagerTest, ManyAllocations) {
+ std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
+
+ uint8_t* code[10000];
+ uint8_t* data[10000];
+
+ for (unsigned i = 0; i < 10000; ++i) {
+ const bool isReadOnly = i % 2 == 0;
+
+ code[i] = MemMgr->allocateCodeSection(32, 0, 1, "");
+ data[i] = MemMgr->allocateDataSection(32, 0, 2, "", isReadOnly);
+
+ for (unsigned j = 0; j < 32; j++) {
+ code[i][j] = 1 + (i % 254);
+ data[i][j] = 2 + (i % 254);
+ }
+
+ EXPECT_NE((uint8_t *)nullptr, code[i]);
+ EXPECT_NE((uint8_t *)nullptr, data[i]);
+ }
+
+ // Verify the data (this is checking for overlaps in the addresses)
+ for (unsigned i = 0; i < 10000; ++i) {
+ for (unsigned j = 0; j < 32;j++ ) {
+ uint8_t ExpectedCode = 1 + (i % 254);
+ uint8_t ExpectedData = 2 + (i % 254);
+ EXPECT_EQ(ExpectedCode, code[i][j]);
+ EXPECT_EQ(ExpectedData, data[i][j]);
+ }
+ }
+
+ std::string Error;
+ EXPECT_FALSE(MemMgr->finalizeMemory(&Error));
+}
+
+TEST(MCJITMemoryManagerTest, ManyVariedAllocations) {
+ std::unique_ptr<SectionMemoryManager> MemMgr(new SectionMemoryManager());
+
+ uint8_t* code[10000];
+ uint8_t* data[10000];
+
+ for (unsigned i = 0; i < 10000; ++i) {
+ uintptr_t CodeSize = i % 16 + 1;
+ uintptr_t DataSize = i % 8 + 1;
+
+ bool isReadOnly = i % 3 == 0;
+ unsigned Align = 8 << (i % 4);
+
+ code[i] = MemMgr->allocateCodeSection(CodeSize, Align, i, "");
+ data[i] = MemMgr->allocateDataSection(DataSize, Align, i + 10000, "",
+ isReadOnly);
+
+ for (unsigned j = 0; j < CodeSize; j++) {
+ code[i][j] = 1 + (i % 254);
+ }
+
+ for (unsigned j = 0; j < DataSize; j++) {
+ data[i][j] = 2 + (i % 254);
+ }
+
+ EXPECT_NE((uint8_t *)nullptr, code[i]);
+ EXPECT_NE((uint8_t *)nullptr, data[i]);
+
+ uintptr_t CodeAlign = Align ? (uintptr_t)code[i] % Align : 0;
+ uintptr_t DataAlign = Align ? (uintptr_t)data[i] % Align : 0;
+
+ EXPECT_EQ((uintptr_t)0, CodeAlign);
+ EXPECT_EQ((uintptr_t)0, DataAlign);
+ }
+
+ for (unsigned i = 0; i < 10000; ++i) {
+ uintptr_t CodeSize = i % 16 + 1;
+ uintptr_t DataSize = i % 8 + 1;
+
+ for (unsigned j = 0; j < CodeSize; j++) {
+ uint8_t ExpectedCode = 1 + (i % 254);
+ EXPECT_EQ(ExpectedCode, code[i][j]);
+ }
+
+ for (unsigned j = 0; j < DataSize; j++) {
+ uint8_t ExpectedData = 2 + (i % 254);
+ EXPECT_EQ(ExpectedData, data[i][j]);
+ }
+ }
+}
+
+} // Namespace
+
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
new file mode 100644
index 00000000000..65f969f24c6
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITMultipleModuleTest.cpp
@@ -0,0 +1,423 @@
+//===- MCJITMultipeModuleTest.cpp - Unit tests for the MCJIT ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This test suite verifies MCJIT for handling multiple modules in a single
+// ExecutionEngine by building multiple modules, making function calls across
+// modules, accessing global variables, etc.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "MCJITTestBase.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MCJITMultipleModuleTest : public testing::Test, public MCJITTestBase {};
+
+// FIXME: ExecutionEngine has no support empty modules
+/*
+TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ createJIT(M.take());
+ // JIT-compile
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+
+ TheJIT->addModule(createEmptyModule("<other module>"));
+ TheJIT->addModule(createEmptyModule("<other other module>"));
+
+ // JIT again
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+}
+*/
+
+// Helper Function to test add operation
+void checkAdd(uint64_t ptr) {
+ ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
+ int (*AddPtr)(int, int) = (int (*)(int, int))ptr;
+ EXPECT_EQ(0, AddPtr(0, 0));
+ EXPECT_EQ(1, AddPtr(1, 0));
+ EXPECT_EQ(3, AddPtr(1, 2));
+ EXPECT_EQ(-5, AddPtr(-2, -3));
+ EXPECT_EQ(30, AddPtr(10, 20));
+ EXPECT_EQ(-30, AddPtr(-10, -20));
+ EXPECT_EQ(-40, AddPtr(-10, -30));
+}
+
+void checkAccumulate(uint64_t ptr) {
+ ASSERT_TRUE(ptr != 0) << "Unable to get pointer to function.";
+ int32_t (*FPtr)(int32_t) = (int32_t (*)(int32_t))(intptr_t)ptr;
+ EXPECT_EQ(0, FPtr(0));
+ EXPECT_EQ(1, FPtr(1));
+ EXPECT_EQ(3, FPtr(2));
+ EXPECT_EQ(6, FPtr(3));
+ EXPECT_EQ(10, FPtr(4));
+ EXPECT_EQ(15, FPtr(5));
+}
+
+// FIXME: ExecutionEngine has no support empty modules
+/*
+TEST_F(MCJITMultipleModuleTest, multiple_empty_modules) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ createJIT(M.take());
+ // JIT-compile
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+
+ TheJIT->addModule(createEmptyModule("<other module>"));
+ TheJIT->addModule(createEmptyModule("<other other module>"));
+
+ // JIT again
+ EXPECT_NE(0, TheJIT->getObjectImage())
+ << "Unable to generate executable loaded object image";
+}
+*/
+
+// Module A { Function FA },
+// Module B { Function FB },
+// execute FA then FB
+TEST_F(MCJITMultipleModuleTest, two_module_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleCase(A, FA, B, FB);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Function FB },
+// execute FB then FA
+TEST_F(MCJITMultipleModuleTest, two_module_reverse_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleCase(A, FA, B, FB);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// execute FB then FA
+TEST_F(MCJITMultipleModuleTest, two_module_extern_reverse_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleExternCase(A, FA, B, FB);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// execute FA then FB
+TEST_F(MCJITMultipleModuleTest, two_module_extern_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB;
+ createTwoModuleExternCase(A, FA, B, FB);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA1, Function FA2 which calls FA1 },
+// Module B { Extern FA1, Function FB which calls FA1 },
+// execute FB then FA2
+TEST_F(MCJITMultipleModuleTest, two_module_consecutive_call_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA1, *FA2, *FB;
+ createTwoModuleExternCase(A, FA1, B, FB);
+ FA2 = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(A.get(), FA1);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA2->getName().str());
+ checkAdd(ptr);
+}
+
+// TODO:
+// Module A { Extern Global GVB, Global Variable GVA, Function FA loads GVB },
+// Module B { Extern Global GVA, Global Variable GVB, Function FB loads GVA },
+
+
+// Module A { Global Variable GVA, Function FA loads GVA },
+// Module B { Global Variable GVB, Internal Global GVC, Function FB loads GVB },
+// execute FB then FA, also check that the global variables are properly accesible
+// through the ExecutionEngine APIs
+TEST_F(MCJITMultipleModuleTest, two_module_global_variables_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB;
+ GlobalVariable *GVA, *GVB, *GVC;
+ A.reset(createEmptyModule("A"));
+ B.reset(createEmptyModule("B"));
+
+ int32_t initialNum = 7;
+ GVA = insertGlobalInt32(A.get(), "GVA", initialNum);
+ GVB = insertGlobalInt32(B.get(), "GVB", initialNum);
+ FA = startFunction<int32_t(void)>(A.get(), "FA");
+ endFunctionWithRet(FA, Builder.CreateLoad(GVA));
+ FB = startFunction<int32_t(void)>(B.get(), "FB");
+ endFunctionWithRet(FB, Builder.CreateLoad(GVB));
+
+ GVC = insertGlobalInt32(B.get(), "GVC", initialNum);
+ GVC->setLinkage(GlobalValue::InternalLinkage);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ EXPECT_EQ(GVA, TheJIT->FindGlobalVariableNamed("GVA"));
+ EXPECT_EQ(GVB, TheJIT->FindGlobalVariableNamed("GVB"));
+ EXPECT_EQ(GVC, TheJIT->FindGlobalVariableNamed("GVC",true));
+ EXPECT_EQ(nullptr, TheJIT->FindGlobalVariableNamed("GVC"));
+
+ uint64_t FBPtr = TheJIT->getFunctionAddress(FB->getName().str());
+ TheJIT->finalizeObject();
+ EXPECT_TRUE(0 != FBPtr);
+ int32_t(*FuncPtr)() = (int32_t(*)())FBPtr;
+ EXPECT_EQ(initialNum, FuncPtr())
+ << "Invalid value for global returned from JITted function in module B";
+
+ uint64_t FAPtr = TheJIT->getFunctionAddress(FA->getName().str());
+ EXPECT_TRUE(0 != FAPtr);
+ FuncPtr = (int32_t(*)())FAPtr;
+ EXPECT_EQ(initialNum, FuncPtr())
+ << "Invalid value for global returned from JITted function in module A";
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FA, Function FC which calls FA },
+// execute FC, FB, FA
+TEST_F(MCJITMultipleModuleTest, three_module_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleCase(A, FA, B, FB, C, FC);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FA, Function FC which calls FA },
+// execute FA, FB, FC
+TEST_F(MCJITMultipleModuleTest, three_module_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleCase(A, FA, B, FB, C, FC);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FB, Function FC which calls FB },
+// execute FC, FB, FA
+TEST_F(MCJITMultipleModuleTest, three_module_chain_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Function FA },
+// Module B { Extern FA, Function FB which calls FA },
+// Module C { Extern FB, Function FC which calls FB },
+// execute FA, FB, FC
+TEST_F(MCJITMultipleModuleTest, three_modules_chain_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B, C;
+ Function *FA, *FB, *FC;
+ createThreeModuleChainedCallsCase(A, FA, B, FB, C, FC);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+ TheJIT->addModule(std::move(C));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB->getName().str());
+ checkAdd(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FC->getName().str());
+ checkAdd(ptr);
+}
+
+// Module A { Extern FB, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FA, then FB1
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+}
+
+// Module A { Extern FB, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FB1 then FA
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case_reverse_order) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FA->getName().str());
+ checkAccumulate(ptr);
+}
+
+// Module A { Extern FB1, Function FA which calls FB1 },
+// Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+// execute FB1 then FB2
+// FIXME: this test case is not supported by MCJIT
+TEST_F(MCJITMultipleModuleTest, cross_module_dependency_case3) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ uint64_t ptr = TheJIT->getFunctionAddress(FB1->getName().str());
+ checkAccumulate(ptr);
+
+ ptr = TheJIT->getFunctionAddress(FB2->getName().str());
+ checkAccumulate(ptr);
+}
+
+// Test that FindFunctionNamed finds the definition of
+// a function in the correct module. We check two functions
+// in two different modules, to make sure that for at least
+// one of them MCJIT had to ignore the extern declaration.
+TEST_F(MCJITMultipleModuleTest, FindFunctionNamed_test) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<Module> A, B;
+ Function *FA, *FB1, *FB2;
+ createCrossModuleRecursiveCase(A, FA, B, FB1, FB2);
+
+ createJIT(std::move(A));
+ TheJIT->addModule(std::move(B));
+
+ EXPECT_EQ(FA, TheJIT->FindFunctionNamed(FA->getName().data()));
+ EXPECT_EQ(FB1, TheJIT->FindFunctionNamed(FB1->getName().data()));
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
new file mode 100644
index 00000000000..2e3d2b6665a
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITObjectCacheTest.cpp
@@ -0,0 +1,229 @@
+//===- MCJITObjectCacheTest.cpp - Unit tests for MCJIT object caching -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCJITTestBase.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/ExecutionEngine/ObjectCache.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class TestObjectCache : public ObjectCache {
+public:
+ TestObjectCache() : DuplicateInserted(false) { }
+
+ void notifyObjectCompiled(const Module *M, MemoryBufferRef Obj) override {
+ // If we've seen this module before, note that.
+ const std::string ModuleID = M->getModuleIdentifier();
+ if (ObjMap.find(ModuleID) != ObjMap.end())
+ DuplicateInserted = true;
+ // Store a copy of the buffer in our map.
+ ObjMap[ModuleID] = copyBuffer(Obj);
+ }
+
+ std::unique_ptr<MemoryBuffer> getObject(const Module *M) override {
+ const MemoryBuffer* BufferFound = getObjectInternal(M);
+ ModulesLookedUp.insert(M->getModuleIdentifier());
+ if (!BufferFound)
+ return nullptr;
+ // Our test cache wants to maintain ownership of its object buffers
+ // so we make a copy here for the execution engine.
+ return MemoryBuffer::getMemBufferCopy(BufferFound->getBuffer());
+ }
+
+ // Test-harness-specific functions
+ bool wereDuplicatesInserted() { return DuplicateInserted; }
+
+ bool wasModuleLookedUp(const Module *M) {
+ return ModulesLookedUp.find(M->getModuleIdentifier())
+ != ModulesLookedUp.end();
+ }
+
+ const MemoryBuffer* getObjectInternal(const Module* M) {
+ // Look for the module in our map.
+ const std::string ModuleID = M->getModuleIdentifier();
+ StringMap<const MemoryBuffer *>::iterator it = ObjMap.find(ModuleID);
+ if (it == ObjMap.end())
+ return nullptr;
+ return it->second;
+ }
+
+private:
+ MemoryBuffer *copyBuffer(MemoryBufferRef Buf) {
+ // Create a local copy of the buffer.
+ std::unique_ptr<MemoryBuffer> NewBuffer =
+ MemoryBuffer::getMemBufferCopy(Buf.getBuffer());
+ MemoryBuffer *Ret = NewBuffer.get();
+ AllocatedBuffers.push_back(std::move(NewBuffer));
+ return Ret;
+ }
+
+ StringMap<const MemoryBuffer *> ObjMap;
+ StringSet<> ModulesLookedUp;
+ SmallVector<std::unique_ptr<MemoryBuffer>, 2> AllocatedBuffers;
+ bool DuplicateInserted;
+};
+
+class MCJITObjectCacheTest : public testing::Test, public MCJITTestBase {
+protected:
+ enum {
+ OriginalRC = 6,
+ ReplacementRC = 7
+ };
+
+ void SetUp() override {
+ M.reset(createEmptyModule("<main>"));
+ Main = insertMainFunction(M.get(), OriginalRC);
+ }
+
+ void compileAndRun(int ExpectedRC = OriginalRC) {
+ // This function shouldn't be called until after SetUp.
+ ASSERT_TRUE(bool(TheJIT));
+ ASSERT_TRUE(nullptr != Main);
+
+ // We may be using a null cache, so ensure compilation is valid.
+ TheJIT->finalizeObject();
+ void *vPtr = TheJIT->getPointerToFunction(Main);
+
+ EXPECT_TRUE(nullptr != vPtr)
+ << "Unable to get pointer to main() from JIT";
+
+ int (*FuncPtr)() = (int(*)())(intptr_t)vPtr;
+ int returnCode = FuncPtr();
+ EXPECT_EQ(returnCode, ExpectedRC);
+ }
+
+ Function *Main;
+};
+
+TEST_F(MCJITObjectCacheTest, SetNullObjectCache) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ createJIT(std::move(M));
+
+ TheJIT->setObjectCache(nullptr);
+
+ compileAndRun();
+}
+
+TEST_F(MCJITObjectCacheTest, VerifyBasicObjectCaching) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
+
+ // Save a copy of the module pointer before handing it off to MCJIT.
+ const Module * SavedModulePointer = M.get();
+
+ createJIT(std::move(M));
+
+ TheJIT->setObjectCache(Cache.get());
+
+ // Verify that our object cache does not contain the module yet.
+ const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
+ EXPECT_EQ(nullptr, ObjBuffer);
+
+ compileAndRun();
+
+ // Verify that MCJIT tried to look-up this module in the cache.
+ EXPECT_TRUE(Cache->wasModuleLookedUp(SavedModulePointer));
+
+ // Verify that our object cache now contains the module.
+ ObjBuffer = Cache->getObjectInternal(SavedModulePointer);
+ EXPECT_TRUE(nullptr != ObjBuffer);
+
+ // Verify that the cache was only notified once.
+ EXPECT_FALSE(Cache->wereDuplicatesInserted());
+}
+
+TEST_F(MCJITObjectCacheTest, VerifyLoadFromCache) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
+
+ // Compile this module with an MCJIT engine
+ createJIT(std::move(M));
+ TheJIT->setObjectCache(Cache.get());
+ TheJIT->finalizeObject();
+
+ // Destroy the MCJIT engine we just used
+ TheJIT.reset();
+
+ // Create a new memory manager.
+ MM.reset(new SectionMemoryManager());
+
+ // Create a new module and save it. Use a different return code so we can
+ // tell if MCJIT compiled this module or used the cache.
+ M.reset(createEmptyModule("<main>"));
+ Main = insertMainFunction(M.get(), ReplacementRC);
+ const Module * SecondModulePointer = M.get();
+
+ // Create a new MCJIT instance to load this module then execute it.
+ createJIT(std::move(M));
+ TheJIT->setObjectCache(Cache.get());
+ compileAndRun();
+
+ // Verify that MCJIT tried to look-up this module in the cache.
+ EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
+
+ // Verify that MCJIT didn't try to cache this again.
+ EXPECT_FALSE(Cache->wereDuplicatesInserted());
+}
+
+TEST_F(MCJITObjectCacheTest, VerifyNonLoadFromCache) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ std::unique_ptr<TestObjectCache> Cache(new TestObjectCache);
+
+ // Compile this module with an MCJIT engine
+ createJIT(std::move(M));
+ TheJIT->setObjectCache(Cache.get());
+ TheJIT->finalizeObject();
+
+ // Destroy the MCJIT engine we just used
+ TheJIT.reset();
+
+ // Create a new memory manager.
+ MM.reset(new SectionMemoryManager());
+
+ // Create a new module and save it. Use a different return code so we can
+ // tell if MCJIT compiled this module or used the cache. Note that we use
+ // a new module name here so the module shouldn't be found in the cache.
+ M.reset(createEmptyModule("<not-main>"));
+ Main = insertMainFunction(M.get(), ReplacementRC);
+ const Module * SecondModulePointer = M.get();
+
+ // Create a new MCJIT instance to load this module then execute it.
+ createJIT(std::move(M));
+ TheJIT->setObjectCache(Cache.get());
+
+ // Verify that our object cache does not contain the module yet.
+ const MemoryBuffer *ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
+ EXPECT_EQ(nullptr, ObjBuffer);
+
+ // Run the function and look for the replacement return code.
+ compileAndRun(ReplacementRC);
+
+ // Verify that MCJIT tried to look-up this module in the cache.
+ EXPECT_TRUE(Cache->wasModuleLookedUp(SecondModulePointer));
+
+ // Verify that our object cache now contains the module.
+ ObjBuffer = Cache->getObjectInternal(SecondModulePointer);
+ EXPECT_TRUE(nullptr != ObjBuffer);
+
+ // Verify that MCJIT didn't try to cache this again.
+ EXPECT_FALSE(Cache->wereDuplicatesInserted());
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
new file mode 100644
index 00000000000..744bfdb4a01
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTest.cpp
@@ -0,0 +1,284 @@
+//===- MCJITTest.cpp - Unit tests for the MCJIT -----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This test suite verifies basic MCJIT functionality such as making function
+// calls, using global variables, and compiling multpile modules.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/MCJIT.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "MCJITTestBase.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MCJITTest : public testing::Test, public MCJITTestBase {
+protected:
+ void SetUp() override { M.reset(createEmptyModule("<main>")); }
+};
+
+// FIXME: Ensure creating an execution engine does not crash when constructed
+// with a null module.
+/*
+TEST_F(MCJITTest, null_module) {
+ createJIT(0);
+}
+*/
+
+// FIXME: In order to JIT an empty module, there needs to be
+// an interface to ExecutionEngine that forces compilation but
+// does not require retrieval of a pointer to a function/global.
+/*
+TEST_F(MCJITTest, empty_module) {
+ createJIT(M.take());
+ //EXPECT_NE(0, TheJIT->getObjectImage())
+ // << "Unable to generate executable loaded object image";
+}
+*/
+
+TEST_F(MCJITTest, global_variable) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ int initialValue = 5;
+ GlobalValue *Global = insertGlobalInt32(M.get(), "test_global", initialValue);
+ createJIT(std::move(M));
+ void *globalPtr = TheJIT->getPointerToGlobal(Global);
+ EXPECT_TRUE(nullptr != globalPtr)
+ << "Unable to get pointer to global value from JIT";
+
+ EXPECT_EQ(initialValue, *(int32_t*)globalPtr)
+ << "Unexpected initial value of global";
+}
+
+TEST_F(MCJITTest, add_function) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Function *F = insertAddFunction(M.get());
+ createJIT(std::move(M));
+ uint64_t addPtr = TheJIT->getFunctionAddress(F->getName().str());
+ EXPECT_TRUE(0 != addPtr)
+ << "Unable to get pointer to function from JIT";
+
+ ASSERT_TRUE(addPtr != 0) << "Unable to get pointer to function .";
+ int (*AddPtr)(int, int) = (int(*)(int, int))addPtr ;
+ EXPECT_EQ(0, AddPtr(0, 0));
+ EXPECT_EQ(1, AddPtr(1, 0));
+ EXPECT_EQ(3, AddPtr(1, 2));
+ EXPECT_EQ(-5, AddPtr(-2, -3));
+ EXPECT_EQ(30, AddPtr(10, 20));
+ EXPECT_EQ(-30, AddPtr(-10, -20));
+ EXPECT_EQ(-40, AddPtr(-10, -30));
+}
+
+TEST_F(MCJITTest, run_main) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ int rc = 6;
+ Function *Main = insertMainFunction(M.get(), 6);
+ createJIT(std::move(M));
+ uint64_t ptr = TheJIT->getFunctionAddress(Main->getName().str());
+ EXPECT_TRUE(0 != ptr)
+ << "Unable to get pointer to main() from JIT";
+
+ int (*FuncPtr)() = (int(*)())ptr;
+ int returnCode = FuncPtr();
+ EXPECT_EQ(returnCode, rc);
+}
+
+TEST_F(MCJITTest, return_global) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ int32_t initialNum = 7;
+ GlobalVariable *GV = insertGlobalInt32(M.get(), "myglob", initialNum);
+
+ Function *ReturnGlobal = startFunction<int32_t(void)>(M.get(),
+ "ReturnGlobal");
+ Value *ReadGlobal = Builder.CreateLoad(GV);
+ endFunctionWithRet(ReturnGlobal, ReadGlobal);
+
+ createJIT(std::move(M));
+ uint64_t rgvPtr = TheJIT->getFunctionAddress(ReturnGlobal->getName().str());
+ EXPECT_TRUE(0 != rgvPtr);
+
+ int32_t(*FuncPtr)() = (int32_t(*)())rgvPtr;
+ EXPECT_EQ(initialNum, FuncPtr())
+ << "Invalid value for global returned from JITted function";
+}
+
+// FIXME: This case fails due to a bug with getPointerToGlobal().
+// The bug is due to MCJIT not having an implementation of getPointerToGlobal()
+// which results in falling back on the ExecutionEngine implementation that
+// allocates a new memory block for the global instead of using the same
+// global variable that is emitted by MCJIT. Hence, the pointer (gvPtr below)
+// has the correct initial value, but updates to the real global (accessed by
+// JITted code) are not propagated. Instead, getPointerToGlobal() should return
+// a pointer into the loaded ObjectImage to reference the emitted global.
+/*
+TEST_F(MCJITTest, increment_global) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ int32_t initialNum = 5;
+ Function *IncrementGlobal = startFunction<int32_t(void)>(M.get(), "IncrementGlobal");
+ GlobalVariable *GV = insertGlobalInt32(M.get(), "my_global", initialNum);
+ Value *DerefGV = Builder.CreateLoad(GV);
+ Value *AddResult = Builder.CreateAdd(DerefGV,
+ ConstantInt::get(Context, APInt(32, 1)));
+ Builder.CreateStore(AddResult, GV);
+ endFunctionWithRet(IncrementGlobal, AddResult);
+
+ createJIT(M.take());
+ void *gvPtr = TheJIT->getPointerToGlobal(GV);
+ EXPECT_EQ(initialNum, *(int32_t*)gvPtr);
+
+ void *vPtr = TheJIT->getFunctionAddress(IncrementGlobal->getName().str());
+ EXPECT_TRUE(0 != vPtr)
+ << "Unable to get pointer to main() from JIT";
+
+ int32_t(*FuncPtr)(void) = (int32_t(*)(void))(intptr_t)vPtr;
+
+ for(int i = 1; i < 3; ++i) {
+ int32_t result = FuncPtr();
+ EXPECT_EQ(initialNum + i, result); // OK
+ EXPECT_EQ(initialNum + i, *(int32_t*)gvPtr); // FAILS
+ }
+}
+*/
+
+// PR16013: XFAIL this test on ARM, which currently can't handle multiple relocations.
+#if !defined(__arm__)
+
+TEST_F(MCJITTest, multiple_functions) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ unsigned int numLevels = 23;
+ int32_t innerRetVal= 5;
+
+ Function *Inner = startFunction<int32_t(void)>(M.get(), "Inner");
+ endFunctionWithRet(Inner, ConstantInt::get(Context, APInt(32, innerRetVal)));
+
+ Function *Outer;
+ for (unsigned int i = 0; i < numLevels; ++i) {
+ std::stringstream funcName;
+ funcName << "level_" << i;
+ Outer = startFunction<int32_t(void)>(M.get(), funcName.str());
+ Value *innerResult = Builder.CreateCall(Inner, {});
+ endFunctionWithRet(Outer, innerResult);
+
+ Inner = Outer;
+ }
+
+ createJIT(std::move(M));
+ uint64_t ptr = TheJIT->getFunctionAddress(Outer->getName().str());
+ EXPECT_TRUE(0 != ptr)
+ << "Unable to get pointer to outer function from JIT";
+
+ int32_t(*FuncPtr)() = (int32_t(*)())ptr;
+ EXPECT_EQ(innerRetVal, FuncPtr())
+ << "Incorrect result returned from function";
+}
+
+#endif /*!defined(__arm__)*/
+
+TEST_F(MCJITTest, multiple_decl_lookups) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Function *Foo = insertExternalReferenceToFunction<void(void)>(M.get(), "_exit");
+ createJIT(std::move(M));
+ void *A = TheJIT->getPointerToFunction(Foo);
+ void *B = TheJIT->getPointerToFunction(Foo);
+
+ EXPECT_TRUE(A != nullptr) << "Failed lookup - test not correctly configured.";
+ EXPECT_EQ(A, B) << "Repeat calls to getPointerToFunction fail.";
+}
+
+typedef void * (*FunctionHandlerPtr)(const std::string &str);
+
+TEST_F(MCJITTest, lazy_function_creator_pointer) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Function *Foo = insertExternalReferenceToFunction<int32_t(void)>(M.get(),
+ "\1Foo");
+ startFunction<int32_t(void)>(M.get(), "Parent");
+ CallInst *Call = Builder.CreateCall(Foo, {});
+ Builder.CreateRet(Call);
+
+ createJIT(std::move(M));
+
+ // Set up the lazy function creator that records the name of the last
+ // unresolved external function found in the module. Using a function pointer
+ // prevents us from capturing local variables, which is why this is static.
+ static std::string UnresolvedExternal;
+ FunctionHandlerPtr UnresolvedHandler = [] (const std::string &str) {
+ // Try to resolve the function in the current process before marking it as
+ // unresolved. This solves an issue on ARM where '__aeabi_*' function names
+ // are passed to this handler.
+ void *symbol =
+ llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str());
+ if (symbol) {
+ return symbol;
+ }
+
+ UnresolvedExternal = str;
+ return (void *)(uintptr_t)-1;
+ };
+ TheJIT->InstallLazyFunctionCreator(UnresolvedHandler);
+
+ // JIT the module.
+ TheJIT->finalizeObject();
+
+ // Verify that our handler was called.
+ EXPECT_EQ(UnresolvedExternal, "Foo");
+}
+
+TEST_F(MCJITTest, lazy_function_creator_lambda) {
+ SKIP_UNSUPPORTED_PLATFORM;
+
+ Function *Foo1 = insertExternalReferenceToFunction<int32_t(void)>(M.get(),
+ "\1Foo1");
+ Function *Foo2 = insertExternalReferenceToFunction<int32_t(void)>(M.get(),
+ "\1Foo2");
+ startFunction<int32_t(void)>(M.get(), "Parent");
+ CallInst *Call1 = Builder.CreateCall(Foo1, {});
+ CallInst *Call2 = Builder.CreateCall(Foo2, {});
+ Value *Result = Builder.CreateAdd(Call1, Call2);
+ Builder.CreateRet(Result);
+
+ createJIT(std::move(M));
+
+ // Set up the lazy function creator that records the name of unresolved
+ // external functions in the module.
+ std::vector<std::string> UnresolvedExternals;
+ auto UnresolvedHandler = [&UnresolvedExternals] (const std::string &str) {
+ // Try to resolve the function in the current process before marking it as
+ // unresolved. This solves an issue on ARM where '__aeabi_*' function names
+ // are passed to this handler.
+ void *symbol =
+ llvm::sys::DynamicLibrary::SearchForAddressOfSymbol(str.c_str());
+ if (symbol) {
+ return symbol;
+ }
+ UnresolvedExternals.push_back(str);
+ return (void *)(uintptr_t)-1;
+ };
+ TheJIT->InstallLazyFunctionCreator(UnresolvedHandler);
+
+ // JIT the module.
+ TheJIT->finalizeObject();
+
+ // Verify that our handler was called for each unresolved function.
+ auto I = UnresolvedExternals.begin(), E = UnresolvedExternals.end();
+ EXPECT_EQ(UnresolvedExternals.size(), 2u);
+ EXPECT_FALSE(std::find(I, E, "Foo1") == E);
+ EXPECT_FALSE(std::find(I, E, "Foo2") == E);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
new file mode 100644
index 00000000000..21def6e9eb1
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestAPICommon.h
@@ -0,0 +1,103 @@
+//===- MCJITTestBase.h - Common base class for MCJIT Unit tests ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements functionality shared by both MCJIT C API tests, and
+// the C++ API tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H
+#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTAPICOMMON_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetSelect.h"
+
+// Used to skip tests on unsupported architectures and operating systems.
+// To skip a test, add this macro at the top of a test-case in a suite that
+// inherits from MCJITTestBase. See MCJITTest.cpp for examples.
+#define SKIP_UNSUPPORTED_PLATFORM \
+ do \
+ if (!ArchSupportsMCJIT() || !OSSupportsMCJIT()) \
+ return; \
+ while(0)
+
+namespace llvm {
+
+class MCJITTestAPICommon {
+protected:
+ MCJITTestAPICommon()
+ : HostTriple(sys::getProcessTriple())
+ {
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmPrinter();
+
+ // FIXME: It isn't at all clear why this is necesasry, but without it we
+ // fail to initialize the AssumptionCacheTracker.
+ initializeAssumptionCacheTrackerPass(*PassRegistry::getPassRegistry());
+
+#ifdef LLVM_ON_WIN32
+ // On Windows, generate ELF objects by specifying "-elf" in triple
+ HostTriple += "-elf";
+#endif // LLVM_ON_WIN32
+ HostTriple = Triple::normalize(HostTriple);
+ }
+
+ /// Returns true if the host architecture is known to support MCJIT
+ bool ArchSupportsMCJIT() {
+ Triple Host(HostTriple);
+ // If ARCH is not supported, bail
+ if (std::find(SupportedArchs.begin(), SupportedArchs.end(), Host.getArch())
+ == SupportedArchs.end())
+ return false;
+
+ // If ARCH is supported and has no specific sub-arch support
+ if (std::find(HasSubArchs.begin(), HasSubArchs.end(), Host.getArch())
+ == HasSubArchs.end())
+ return true;
+
+ // If ARCH has sub-arch support, find it
+ SmallVectorImpl<std::string>::const_iterator I = SupportedSubArchs.begin();
+ for(; I != SupportedSubArchs.end(); ++I)
+ if (Host.getArchName().startswith(I->c_str()))
+ return true;
+
+ return false;
+ }
+
+ /// Returns true if the host OS is known to support MCJIT
+ bool OSSupportsMCJIT() {
+ Triple Host(HostTriple);
+
+ if (std::find(UnsupportedEnvironments.begin(), UnsupportedEnvironments.end(),
+ Host.getEnvironment()) != UnsupportedEnvironments.end())
+ return false;
+
+ if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS())
+ == UnsupportedOSs.end())
+ return true;
+
+ return false;
+ }
+
+ std::string HostTriple;
+ SmallVector<Triple::ArchType, 4> SupportedArchs;
+ SmallVector<Triple::ArchType, 1> HasSubArchs;
+ SmallVector<std::string, 2> SupportedSubArchs; // We need to own the memory
+ SmallVector<Triple::OSType, 4> UnsupportedOSs;
+ SmallVector<Triple::EnvironmentType, 1> UnsupportedEnvironments;
+};
+
+} // namespace llvm
+
+#endif
+
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
new file mode 100644
index 00000000000..609ac844c47
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTestBase.h
@@ -0,0 +1,347 @@
+//===- MCJITTestBase.h - Common base class for MCJIT Unit tests -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class implements common functionality required by the MCJIT unit tests,
+// as well as logic to skip tests on unsupported architectures and operating
+// systems.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
+#define LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
+
+#include "MCJITTestAPICommon.h"
+#include "llvm/Config/config.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/TypeBuilder.h"
+#include "llvm/Support/CodeGen.h"
+
+namespace llvm {
+
+/// Helper class that can build very simple Modules
+class TrivialModuleBuilder {
+protected:
+ LLVMContext Context;
+ IRBuilder<> Builder;
+ std::string BuilderTriple;
+
+ TrivialModuleBuilder(const std::string &Triple)
+ : Builder(Context), BuilderTriple(Triple) {}
+
+ Module *createEmptyModule(StringRef Name = StringRef()) {
+ Module * M = new Module(Name, Context);
+ M->setTargetTriple(Triple::normalize(BuilderTriple));
+ return M;
+ }
+
+ template<typename FuncType>
+ Function *startFunction(Module *M, StringRef Name) {
+ Function *Result = Function::Create(
+ TypeBuilder<FuncType, false>::get(Context),
+ GlobalValue::ExternalLinkage, Name, M);
+
+ BasicBlock *BB = BasicBlock::Create(Context, Name, Result);
+ Builder.SetInsertPoint(BB);
+
+ return Result;
+ }
+
+ void endFunctionWithRet(Function *Func, Value *RetValue) {
+ Builder.CreateRet(RetValue);
+ }
+
+ // Inserts a simple function that invokes Callee and takes the same arguments:
+ // int Caller(...) { return Callee(...); }
+ template<typename Signature>
+ Function *insertSimpleCallFunction(Module *M, Function *Callee) {
+ Function *Result = startFunction<Signature>(M, "caller");
+
+ SmallVector<Value*, 1> CallArgs;
+
+ for (Argument &A : Result->args())
+ CallArgs.push_back(&A);
+
+ Value *ReturnCode = Builder.CreateCall(Callee, CallArgs);
+ Builder.CreateRet(ReturnCode);
+ return Result;
+ }
+
+ // Inserts a function named 'main' that returns a uint32_t:
+ // int32_t main() { return X; }
+ // where X is given by returnCode
+ Function *insertMainFunction(Module *M, uint32_t returnCode) {
+ Function *Result = startFunction<int32_t(void)>(M, "main");
+
+ Value *ReturnVal = ConstantInt::get(Context, APInt(32, returnCode));
+ endFunctionWithRet(Result, ReturnVal);
+
+ return Result;
+ }
+
+ // Inserts a function
+ // int32_t add(int32_t a, int32_t b) { return a + b; }
+ // in the current module and returns a pointer to it.
+ Function *insertAddFunction(Module *M, StringRef Name = "add") {
+ Function *Result = startFunction<int32_t(int32_t, int32_t)>(M, Name);
+
+ Function::arg_iterator args = Result->arg_begin();
+ Value *Arg1 = &*args;
+ Value *Arg2 = &*++args;
+ Value *AddResult = Builder.CreateAdd(Arg1, Arg2);
+
+ endFunctionWithRet(Result, AddResult);
+
+ return Result;
+ }
+
+ // Inserts a declaration to a function defined elsewhere
+ template <typename FuncType>
+ Function *insertExternalReferenceToFunction(Module *M, StringRef Name) {
+ Function *Result = Function::Create(
+ TypeBuilder<FuncType, false>::get(Context),
+ GlobalValue::ExternalLinkage, Name, M);
+ return Result;
+ }
+
+ // Inserts an declaration to a function defined elsewhere
+ Function *insertExternalReferenceToFunction(Module *M, StringRef Name,
+ FunctionType *FuncTy) {
+ Function *Result = Function::Create(FuncTy,
+ GlobalValue::ExternalLinkage,
+ Name, M);
+ return Result;
+ }
+
+ // Inserts an declaration to a function defined elsewhere
+ Function *insertExternalReferenceToFunction(Module *M, Function *Func) {
+ Function *Result = Function::Create(Func->getFunctionType(),
+ GlobalValue::ExternalLinkage,
+ Func->getName(), M);
+ return Result;
+ }
+
+ // Inserts a global variable of type int32
+ // FIXME: make this a template function to support any type
+ GlobalVariable *insertGlobalInt32(Module *M,
+ StringRef name,
+ int32_t InitialValue) {
+ Type *GlobalTy = TypeBuilder<types::i<32>, true>::get(Context);
+ Constant *IV = ConstantInt::get(Context, APInt(32, InitialValue));
+ GlobalVariable *Global = new GlobalVariable(*M,
+ GlobalTy,
+ false,
+ GlobalValue::ExternalLinkage,
+ IV,
+ name);
+ return Global;
+ }
+
+ // Inserts a function
+ // int32_t recursive_add(int32_t num) {
+ // if (num == 0) {
+ // return num;
+ // } else {
+ // int32_t recursive_param = num - 1;
+ // return num + Helper(recursive_param);
+ // }
+ // }
+ // NOTE: if Helper is left as the default parameter, Helper == recursive_add.
+ Function *insertAccumulateFunction(Module *M,
+ Function *Helper = nullptr,
+ StringRef Name = "accumulate") {
+ Function *Result = startFunction<int32_t(int32_t)>(M, Name);
+ if (!Helper)
+ Helper = Result;
+
+ BasicBlock *BaseCase = BasicBlock::Create(Context, "", Result);
+ BasicBlock *RecursiveCase = BasicBlock::Create(Context, "", Result);
+
+ // if (num == 0)
+ Value *Param = &*Result->arg_begin();
+ Value *Zero = ConstantInt::get(Context, APInt(32, 0));
+ Builder.CreateCondBr(Builder.CreateICmpEQ(Param, Zero),
+ BaseCase, RecursiveCase);
+
+ // return num;
+ Builder.SetInsertPoint(BaseCase);
+ Builder.CreateRet(Param);
+
+ // int32_t recursive_param = num - 1;
+ // return Helper(recursive_param);
+ Builder.SetInsertPoint(RecursiveCase);
+ Value *One = ConstantInt::get(Context, APInt(32, 1));
+ Value *RecursiveParam = Builder.CreateSub(Param, One);
+ Value *RecursiveReturn = Builder.CreateCall(Helper, RecursiveParam);
+ Value *Accumulator = Builder.CreateAdd(Param, RecursiveReturn);
+ Builder.CreateRet(Accumulator);
+
+ return Result;
+ }
+
+ // Populates Modules A and B:
+ // Module A { Extern FB1, Function FA which calls FB1 },
+ // Module B { Extern FA, Function FB1, Function FB2 which calls FA },
+ void createCrossModuleRecursiveCase(std::unique_ptr<Module> &A, Function *&FA,
+ std::unique_ptr<Module> &B,
+ Function *&FB1, Function *&FB2) {
+ // Define FB1 in B.
+ B.reset(createEmptyModule("B"));
+ FB1 = insertAccumulateFunction(B.get(), nullptr, "FB1");
+
+ // Declare FB1 in A (as an external).
+ A.reset(createEmptyModule("A"));
+ Function *FB1Extern = insertExternalReferenceToFunction(A.get(), FB1);
+
+ // Define FA in A (with a call to FB1).
+ FA = insertAccumulateFunction(A.get(), FB1Extern, "FA");
+
+ // Declare FA in B (as an external)
+ Function *FAExtern = insertExternalReferenceToFunction(B.get(), FA);
+
+ // Define FB2 in B (with a call to FA)
+ FB2 = insertAccumulateFunction(B.get(), FAExtern, "FB2");
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA },
+ // Module C { Extern FB, Function FC which calls FB },
+ void
+ createThreeModuleChainedCallsCase(std::unique_ptr<Module> &A, Function *&FA,
+ std::unique_ptr<Module> &B, Function *&FB,
+ std::unique_ptr<Module> &C, Function *&FC) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B);
+
+ C.reset(createEmptyModule("C"));
+ Function *FBExtern_in_C = insertExternalReferenceToFunction(C.get(), FB);
+ FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FBExtern_in_C);
+ }
+
+ // Module A { Function FA },
+ // Populates Modules A and B:
+ // Module B { Function FB }
+ void createTwoModuleCase(std::unique_ptr<Module> &A, Function *&FA,
+ std::unique_ptr<Module> &B, Function *&FB) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ FB = insertAddFunction(B.get());
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA }
+ void createTwoModuleExternCase(std::unique_ptr<Module> &A, Function *&FA,
+ std::unique_ptr<Module> &B, Function *&FB) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(),
+ FAExtern_in_B);
+ }
+
+ // Module A { Function FA },
+ // Module B { Extern FA, Function FB which calls FA },
+ // Module C { Extern FB, Function FC which calls FA },
+ void createThreeModuleCase(std::unique_ptr<Module> &A, Function *&FA,
+ std::unique_ptr<Module> &B, Function *&FB,
+ std::unique_ptr<Module> &C, Function *&FC) {
+ A.reset(createEmptyModule("A"));
+ FA = insertAddFunction(A.get());
+
+ B.reset(createEmptyModule("B"));
+ Function *FAExtern_in_B = insertExternalReferenceToFunction(B.get(), FA);
+ FB = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(B.get(), FAExtern_in_B);
+
+ C.reset(createEmptyModule("C"));
+ Function *FAExtern_in_C = insertExternalReferenceToFunction(C.get(), FA);
+ FC = insertSimpleCallFunction<int32_t(int32_t, int32_t)>(C.get(), FAExtern_in_C);
+ }
+};
+
+class MCJITTestBase : public MCJITTestAPICommon, public TrivialModuleBuilder {
+protected:
+
+ MCJITTestBase()
+ : TrivialModuleBuilder(HostTriple)
+ , OptLevel(CodeGenOpt::None)
+ , RelocModel(Reloc::Default)
+ , CodeModel(CodeModel::Default)
+ , MArch("")
+ , MM(new SectionMemoryManager)
+ {
+ // The architectures below are known to be compatible with MCJIT as they
+ // are copied from test/ExecutionEngine/MCJIT/lit.local.cfg and should be
+ // kept in sync.
+ SupportedArchs.push_back(Triple::aarch64);
+ SupportedArchs.push_back(Triple::arm);
+ SupportedArchs.push_back(Triple::mips);
+ SupportedArchs.push_back(Triple::mipsel);
+ SupportedArchs.push_back(Triple::mips64);
+ SupportedArchs.push_back(Triple::mips64el);
+ SupportedArchs.push_back(Triple::x86);
+ SupportedArchs.push_back(Triple::x86_64);
+
+ // Some architectures have sub-architectures in which tests will fail, like
+ // ARM. These two vectors will define if they do have sub-archs (to avoid
+ // extra work for those who don't), and if so, if they are listed to work
+ HasSubArchs.push_back(Triple::arm);
+ SupportedSubArchs.push_back("armv6");
+ SupportedSubArchs.push_back("armv7");
+
+ UnsupportedEnvironments.push_back(Triple::Cygnus);
+ }
+
+ void createJIT(std::unique_ptr<Module> M) {
+
+ // Due to the EngineBuilder constructor, it is required to have a Module
+ // in order to construct an ExecutionEngine (i.e. MCJIT)
+ assert(M != 0 && "a non-null Module must be provided to create MCJIT");
+
+ EngineBuilder EB(std::move(M));
+ std::string Error;
+ TheJIT.reset(EB.setEngineKind(EngineKind::JIT)
+ .setMCJITMemoryManager(std::move(MM))
+ .setErrorStr(&Error)
+ .setOptLevel(CodeGenOpt::None)
+ .setCodeModel(CodeModel::JITDefault)
+ .setRelocationModel(Reloc::Default)
+ .setMArch(MArch)
+ .setMCPU(sys::getHostCPUName())
+ //.setMAttrs(MAttrs)
+ .create());
+ // At this point, we cannot modify the module any more.
+ assert(TheJIT.get() != NULL && "error creating MCJIT with EngineBuilder");
+ }
+
+ CodeGenOpt::Level OptLevel;
+ Reloc::Model RelocModel;
+ CodeModel::Model CodeModel;
+ StringRef MArch;
+ SmallVector<std::string, 1> MAttrs;
+ std::unique_ptr<ExecutionEngine> TheJIT;
+ std::unique_ptr<RTDyldMemoryManager> MM;
+
+ std::unique_ptr<Module> M;
+};
+
+} // namespace llvm
+
+#endif // LLVM_UNITTESTS_EXECUTIONENGINE_MCJIT_MCJITTESTBASE_H
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTests.def b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTests.def
new file mode 100644
index 00000000000..aabd2247c04
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/MCJITTests.def
@@ -0,0 +1 @@
+EXPORTS
diff --git a/gnu/llvm/unittests/ExecutionEngine/MCJIT/Makefile b/gnu/llvm/unittests/ExecutionEngine/MCJIT/Makefile
new file mode 100644
index 00000000000..2822b20cdda
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/MCJIT/Makefile
@@ -0,0 +1,18 @@
+##===- unittests/ExecutionEngine/MCJIT/Makefile ------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = MCJIT
+LINK_COMPONENTS := core ipo mcjit native support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+# Permit these tests to use the MCJIT's symbolic lookup.
+LD.Flags += $(RDYNAMIC)
diff --git a/gnu/llvm/unittests/ExecutionEngine/Makefile b/gnu/llvm/unittests/ExecutionEngine/Makefile
new file mode 100644
index 00000000000..c19f8d688d1
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Makefile
@@ -0,0 +1,22 @@
+##===- unittests/ExecutionEngine/Makefile ------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = ExecutionEngine
+LINK_COMPONENTS :=interpreter
+
+include $(LEVEL)/Makefile.config
+
+PARALLEL_DIRS = Orc
+
+ifeq ($(TARGET_HAS_JIT),1)
+ PARALLEL_DIRS += MCJIT
+endif
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
new file mode 100644
index 00000000000..41fef24556b
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -0,0 +1,22 @@
+
+set(LLVM_LINK_COMPONENTS
+ Core
+ ExecutionEngine
+ Object
+ OrcJIT
+ RuntimeDyld
+ Support
+ native
+ )
+
+add_llvm_unittest(OrcJITTests
+ CompileOnDemandLayerTest.cpp
+ IndirectionUtilsTest.cpp
+ GlobalMappingLayerTest.cpp
+ LazyEmittingLayerTest.cpp
+ ObjectLinkingLayerTest.cpp
+ ObjectTransformLayerTest.cpp
+ OrcCAPITest.cpp
+ OrcTestCommon.cpp
+ RPCUtilsTest.cpp
+ )
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
new file mode 100644
index 00000000000..a27e649b616
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/CompileOnDemandLayerTest.cpp
@@ -0,0 +1,75 @@
+//===----- CompileOnDemandLayerTest.cpp - Unit tests for the COD layer ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+class DummyCallbackManager : public orc::JITCompileCallbackManager {
+public:
+ DummyCallbackManager() : JITCompileCallbackManager(0) { }
+public:
+ void grow() override { llvm_unreachable("not implemented"); }
+};
+
+class DummyStubsManager : public orc::IndirectStubsManager {
+public:
+ std::error_code createStub(StringRef StubName, TargetAddress InitAddr,
+ JITSymbolFlags Flags) override {
+ llvm_unreachable("Not implemented");
+ }
+
+ std::error_code createStubs(const StubInitsMap &StubInits) override {
+ llvm_unreachable("Not implemented");
+ }
+
+ JITSymbol findStub(StringRef Name, bool ExportedStubsOnly) override {
+ llvm_unreachable("Not implemented");
+ }
+
+ JITSymbol findPointer(StringRef Name) override {
+ llvm_unreachable("Not implemented");
+ }
+
+ std::error_code updatePointer(StringRef Name,
+ TargetAddress NewAddr) override {
+ llvm_unreachable("Not implemented");
+ }
+};
+
+TEST(CompileOnDemandLayerTest, FindSymbol) {
+ auto MockBaseLayer =
+ createMockBaseLayer<int>(DoNothingAndReturn<int>(0),
+ DoNothingAndReturn<void>(),
+ [](const std::string &Name, bool) {
+ if (Name == "foo")
+ return JITSymbol(1, JITSymbolFlags::Exported);
+ return JITSymbol(nullptr);
+ },
+ DoNothingAndReturn<JITSymbol>(nullptr));
+
+ typedef decltype(MockBaseLayer) MockBaseLayerT;
+ DummyCallbackManager CallbackMgr;
+
+ llvm::orc::CompileOnDemandLayer<MockBaseLayerT> COD(
+ MockBaseLayer, [](Function &F) { return std::set<Function *>{&F}; },
+ CallbackMgr, [] { return llvm::make_unique<DummyStubsManager>(); }, true);
+
+ auto Sym = COD.findSymbol("foo", true);
+
+ EXPECT_TRUE(!!Sym)
+ << "CompileOnDemand::findSymbol should call findSymbol in the base layer.";
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp
new file mode 100644
index 00000000000..054fc16cabd
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/GlobalMappingLayerTest.cpp
@@ -0,0 +1,55 @@
+//===--- GlobalMappingLayerTest.cpp - Unit test the global mapping layer --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/GlobalMappingLayer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+struct MockBaseLayer {
+
+ typedef int ModuleSetHandleT;
+
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ if (Name == "bar")
+ return llvm::orc::JITSymbol(0x4567, JITSymbolFlags::Exported);
+ return nullptr;
+ }
+
+};
+
+TEST(GlobalMappingLayerTest, Empty) {
+ MockBaseLayer M;
+ GlobalMappingLayer<MockBaseLayer> L(M);
+
+ // Test fall-through for missing symbol.
+ auto FooSym = L.findSymbol("foo", true);
+ EXPECT_FALSE(FooSym) << "Found unexpected symbol.";
+
+ // Test fall-through for symbol in base layer.
+ auto BarSym = L.findSymbol("bar", true);
+ EXPECT_EQ(BarSym.getAddress(), static_cast<TargetAddress>(0x4567))
+ << "Symbol lookup fall-through failed.";
+
+ // Test setup of a global mapping.
+ L.setGlobalMapping("foo", 0x0123);
+ auto FooSym2 = L.findSymbol("foo", true);
+ EXPECT_EQ(FooSym2.getAddress(), static_cast<TargetAddress>(0x0123))
+ << "Symbol mapping setup failed.";
+
+ // Test removal of a global mapping.
+ L.eraseGlobalMapping("foo");
+ auto FooSym3 = L.findSymbol("foo", true);
+ EXPECT_FALSE(FooSym3) << "Symbol mapping removal failed.";
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
new file mode 100644
index 00000000000..38b60ea7fcd
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
@@ -0,0 +1,48 @@
+//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(IndirectionUtilsTest, MakeStub) {
+ ModuleBuilder MB(getGlobalContext(), "x86_64-apple-macosx10.10", "");
+ Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>("");
+ SmallVector<AttributeSet, 4> Attrs;
+ Attrs.push_back(
+ AttributeSet::get(MB.getModule()->getContext(), 1U,
+ AttrBuilder().addAttribute(Attribute::StructRet)));
+ Attrs.push_back(
+ AttributeSet::get(MB.getModule()->getContext(), 2U,
+ AttrBuilder().addAttribute(Attribute::ByVal)));
+ Attrs.push_back(
+ AttributeSet::get(MB.getModule()->getContext(), ~0U,
+ AttrBuilder().addAttribute(Attribute::NoUnwind)));
+ F->setAttributes(AttributeSet::get(MB.getModule()->getContext(), Attrs));
+
+ auto ImplPtr = orc::createImplPointer(*F->getType(), *MB.getModule(), "", nullptr);
+ orc::makeStub(*F, *ImplPtr);
+
+ auto II = F->getEntryBlock().begin();
+ EXPECT_TRUE(isa<LoadInst>(*II)) << "First instruction of stub should be a load.";
+ auto *Call = dyn_cast<CallInst>(std::next(II));
+ EXPECT_TRUE(Call != nullptr) << "Second instruction of stub should be a call.";
+ EXPECT_TRUE(Call->isTailCall()) << "Indirect call from stub should be tail call.";
+ EXPECT_TRUE(Call->hasStructRetAttr())
+ << "makeStub should propagate sret attr on 1st argument.";
+ EXPECT_TRUE(Call->paramHasAttr(2U, Attribute::ByVal))
+ << "makeStub should propagate byval attr on 2nd argument.";
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp
new file mode 100644
index 00000000000..a495766db91
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/LazyEmittingLayerTest.cpp
@@ -0,0 +1,32 @@
+//===- LazyEmittingLayerTest.cpp - Unit tests for the lazy emitting layer -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
+#include "gtest/gtest.h"
+
+namespace {
+
+struct MockBaseLayer {
+ typedef int ModuleSetHandleT;
+ ModuleSetHandleT addModuleSet(
+ std::list<std::unique_ptr<llvm::Module>>,
+ std::unique_ptr<llvm::RuntimeDyld::MemoryManager> MemMgr,
+ std::unique_ptr<llvm::RuntimeDyld::SymbolResolver> Resolver) {
+ EXPECT_FALSE(MemMgr);
+ return 42;
+ }
+};
+
+TEST(LazyEmittingLayerTest, Empty) {
+ MockBaseLayer M;
+ llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M);
+ L.addModuleSet(std::list<std::unique_ptr<llvm::Module>>(), nullptr, nullptr);
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile b/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile
new file mode 100644
index 00000000000..c899728e507
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/Makefile
@@ -0,0 +1,16 @@
+##===- unittests/ExecutionEngine/Orc/Makefile --------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = OrcJIT
+LINK_COMPONENTS := core ipo mcjit orcjit native support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
new file mode 100644
index 00000000000..59ee01f3601
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
@@ -0,0 +1,176 @@
+//===-- ObjectLinkingLayerTest.cpp - Unit tests for object linking layer --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+
+namespace {
+
+class ObjectLinkingLayerExecutionTest : public testing::Test,
+ public OrcExecutionTest {
+};
+
+class SectionMemoryManagerWrapper : public SectionMemoryManager {
+public:
+ int FinalizationCount = 0;
+ bool finalizeMemory(std::string *ErrMsg = 0) override {
+ ++FinalizationCount;
+ return SectionMemoryManager::finalizeMemory(ErrMsg);
+ }
+};
+
+TEST(ObjectLinkingLayerTest, TestSetProcessAllSections) {
+
+ class SectionMemoryManagerWrapper : public SectionMemoryManager {
+ public:
+ SectionMemoryManagerWrapper(bool &DebugSeen) : DebugSeen(DebugSeen) {}
+ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName,
+ bool IsReadOnly) override {
+ if (SectionName == ".debug_str")
+ DebugSeen = true;
+ return SectionMemoryManager::allocateDataSection(Size, Alignment,
+ SectionID,
+ SectionName,
+ IsReadOnly);
+ }
+ private:
+ bool DebugSeen;
+ };
+
+ ObjectLinkingLayer<> ObjLayer;
+
+ auto M = llvm::make_unique<Module>("", getGlobalContext());
+ M->setTargetTriple("x86_64-unknown-linux-gnu");
+ Type *Int32Ty = IntegerType::get(getGlobalContext(), 32);
+ GlobalVariable *GV =
+ new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage,
+ ConstantInt::get(Int32Ty, 42), "foo");
+
+ GV->setSection(".debug_str");
+
+ std::unique_ptr<TargetMachine> TM(
+ EngineBuilder().selectTarget(Triple(M->getTargetTriple()), "", "",
+ SmallVector<std::string, 1>()));
+ if (!TM)
+ return;
+
+ auto OwningObj = SimpleCompiler(*TM)(*M);
+ std::vector<object::ObjectFile*> Objs;
+ Objs.push_back(OwningObj.getBinary());
+
+ bool DebugSectionSeen = false;
+ SectionMemoryManagerWrapper SMMW(DebugSectionSeen);
+ auto Resolver =
+ createLambdaResolver(
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+
+ {
+ // Test with ProcessAllSections = false (the default).
+ auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
+ EXPECT_EQ(DebugSectionSeen, false)
+ << "Unexpected debug info section";
+ ObjLayer.removeObjectSet(H);
+ }
+
+ {
+ // Test with ProcessAllSections = true.
+ ObjLayer.setProcessAllSections(true);
+ auto H = ObjLayer.addObjectSet(Objs, &SMMW, &*Resolver);
+ EXPECT_EQ(DebugSectionSeen, true)
+ << "Expected debug info section not seen";
+ ObjLayer.removeObjectSet(H);
+ }
+}
+
+
+TEST_F(ObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
+
+ if (!TM)
+ return;
+
+ ObjectLinkingLayer<> ObjLayer;
+ SimpleCompiler Compile(*TM);
+
+ // Create a pair of modules that will trigger recursive finalization:
+ // Module 1:
+ // int bar() { return 42; }
+ // Module 2:
+ // int bar();
+ // int foo() { return bar(); }
+
+ ModuleBuilder MB1(getGlobalContext(), "", "dummy");
+ {
+ MB1.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("bar");
+ BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
+ Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
+ Builder.CreateRet(FourtyTwo);
+ }
+
+ auto Obj1 = Compile(*MB1.getModule());
+ std::vector<object::ObjectFile*> Obj1Set;
+ Obj1Set.push_back(Obj1.getBinary());
+
+ ModuleBuilder MB2(getGlobalContext(), "", "dummy");
+ {
+ MB2.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarDecl = MB2.createFunctionDecl<int32_t(void)>("bar");
+ Function *FooImpl = MB2.createFunctionDecl<int32_t(void)>("foo");
+ BasicBlock *FooEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ FooImpl);
+ IRBuilder<> Builder(FooEntry);
+ Builder.CreateRet(Builder.CreateCall(BarDecl));
+ }
+ auto Obj2 = Compile(*MB2.getModule());
+ std::vector<object::ObjectFile*> Obj2Set;
+ Obj2Set.push_back(Obj2.getBinary());
+
+ auto Resolver =
+ createLambdaResolver(
+ [&](const std::string &Name) {
+ if (auto Sym = ObjLayer.findSymbol(Name, true))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(), Sym.getFlags());
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ });
+
+ SectionMemoryManagerWrapper SMMW;
+ ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &*Resolver);
+ auto H = ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &*Resolver);
+ ObjLayer.emitAndFinalize(H);
+
+ // Finalization of module 2 should trigger finalization of module 1.
+ // Verify that finalize on SMMW is only called once.
+ EXPECT_EQ(SMMW.FinalizationCount, 1)
+ << "Extra call to finalize";
+}
+
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
new file mode 100644
index 00000000000..c88c94f17b1
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/ObjectTransformLayerTest.cpp
@@ -0,0 +1,275 @@
+//===- ObjectTransformLayerTest.cpp - Unit tests for ObjectTransformLayer -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm::orc;
+
+namespace {
+
+// Stand-in for RuntimeDyld::MemoryManager
+typedef int MockMemoryManager;
+
+// Stand-in for RuntimeDyld::SymbolResolver
+typedef int MockSymbolResolver;
+
+// stand-in for object::ObjectFile
+typedef int MockObjectFile;
+
+// stand-in for llvm::MemoryBuffer set
+typedef int MockMemoryBufferSet;
+
+// Mock transform that operates on unique pointers to object files, and
+// allocates new object files rather than mutating the given ones.
+struct AllocatingTransform {
+ std::unique_ptr<MockObjectFile>
+ operator()(std::unique_ptr<MockObjectFile> Obj) const {
+ return llvm::make_unique<MockObjectFile>(*Obj + 1);
+ }
+};
+
+// Mock base layer for verifying behavior of transform layer.
+// Each method "T foo(args)" is accompanied by two auxiliary methods:
+// - "void expectFoo(args)", to be called before calling foo on the transform
+// layer; saves values of args, which mock layer foo then verifies against.
+// - "void verifyFoo(T)", to be called after foo, which verifies that the
+// transform layer called the base layer and forwarded any return value.
+class MockBaseLayer {
+public:
+ typedef int ObjSetHandleT;
+
+ MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }
+
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ObjSetHandleT addObjectSet(ObjSetT &Objects, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ EXPECT_EQ(MockManager, *MemMgr) << "MM should pass through";
+ EXPECT_EQ(MockResolver, *Resolver) << "Resolver should pass through";
+ size_t I = 0;
+ for (auto &ObjPtr : Objects) {
+ EXPECT_EQ(MockObjects[I++] + 1, *ObjPtr) << "Transform should be applied";
+ }
+ EXPECT_EQ(MockObjects.size(), I) << "Number of objects should match";
+ LastCalled = "addObjectSet";
+ MockObjSetHandle = 111;
+ return MockObjSetHandle;
+ }
+ template <typename ObjSetT>
+ void expectAddObjectSet(ObjSetT &Objects, MockMemoryManager *MemMgr,
+ MockSymbolResolver *Resolver) {
+ MockManager = *MemMgr;
+ MockResolver = *Resolver;
+ for (auto &ObjPtr : Objects) {
+ MockObjects.push_back(*ObjPtr);
+ }
+ }
+ void verifyAddObjectSet(ObjSetHandleT Returned) {
+ EXPECT_EQ("addObjectSet", LastCalled);
+ EXPECT_EQ(MockObjSetHandle, Returned) << "Return should pass through";
+ resetExpectations();
+ }
+
+ void removeObjectSet(ObjSetHandleT H) {
+ EXPECT_EQ(MockObjSetHandle, H);
+ LastCalled = "removeObjectSet";
+ }
+ void expectRemoveObjectSet(ObjSetHandleT H) { MockObjSetHandle = H; }
+ void verifyRemoveObjectSet() {
+ EXPECT_EQ("removeObjectSet", LastCalled);
+ resetExpectations();
+ }
+
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ EXPECT_EQ(MockName, Name) << "Name should pass through";
+ EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
+ LastCalled = "findSymbol";
+ MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
+ return MockSymbol;
+ }
+ void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ MockName = Name;
+ MockBool = ExportedSymbolsOnly;
+ }
+ void verifyFindSymbol(llvm::orc::JITSymbol Returned) {
+ EXPECT_EQ("findSymbol", LastCalled);
+ EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
+ << "Return should pass through";
+ resetExpectations();
+ }
+
+ JITSymbol findSymbolIn(ObjSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
+ EXPECT_EQ(MockName, Name) << "Name should pass through";
+ EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
+ LastCalled = "findSymbolIn";
+ MockSymbol = JITSymbol(122, llvm::JITSymbolFlags::None);
+ return MockSymbol;
+ }
+ void expectFindSymbolIn(ObjSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ MockObjSetHandle = H;
+ MockName = Name;
+ MockBool = ExportedSymbolsOnly;
+ }
+ void verifyFindSymbolIn(llvm::orc::JITSymbol Returned) {
+ EXPECT_EQ("findSymbolIn", LastCalled);
+ EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
+ << "Return should pass through";
+ resetExpectations();
+ }
+
+ void emitAndFinalize(ObjSetHandleT H) {
+ EXPECT_EQ(MockObjSetHandle, H) << "Handle should pass through";
+ LastCalled = "emitAndFinalize";
+ }
+ void expectEmitAndFinalize(ObjSetHandleT H) { MockObjSetHandle = H; }
+ void verifyEmitAndFinalize() {
+ EXPECT_EQ("emitAndFinalize", LastCalled);
+ resetExpectations();
+ }
+
+ void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+ TargetAddress TargetAddr) {
+ EXPECT_EQ(MockObjSetHandle, H);
+ EXPECT_EQ(MockLocalAddress, LocalAddress);
+ EXPECT_EQ(MockTargetAddress, TargetAddr);
+ LastCalled = "mapSectionAddress";
+ }
+ void expectMapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
+ TargetAddress TargetAddr) {
+ MockObjSetHandle = H;
+ MockLocalAddress = LocalAddress;
+ MockTargetAddress = TargetAddr;
+ }
+ void verifyMapSectionAddress() {
+ EXPECT_EQ("mapSectionAddress", LastCalled);
+ resetExpectations();
+ }
+
+private:
+ // Backing fields for remembering parameter/return values
+ std::string LastCalled;
+ MockMemoryManager MockManager;
+ MockSymbolResolver MockResolver;
+ std::vector<MockObjectFile> MockObjects;
+ ObjSetHandleT MockObjSetHandle;
+ std::string MockName;
+ bool MockBool;
+ JITSymbol MockSymbol;
+ const void *MockLocalAddress;
+ TargetAddress MockTargetAddress;
+ MockMemoryBufferSet MockBufferSet;
+
+ // Clear remembered parameters between calls
+ void resetExpectations() {
+ LastCalled = "nothing";
+ MockManager = 0;
+ MockResolver = 0;
+ MockObjects.clear();
+ MockObjSetHandle = 0;
+ MockName = "bogus";
+ MockSymbol = JITSymbol(nullptr);
+ MockLocalAddress = nullptr;
+ MockTargetAddress = 0;
+ MockBufferSet = 0;
+ }
+};
+
+// Test each operation on ObjectTransformLayer.
+TEST(ObjectTransformLayerTest, Main) {
+ MockBaseLayer M;
+
+ // Create one object transform layer using a transform (as a functor)
+ // that allocates new objects, and deals in unique pointers.
+ ObjectTransformLayer<MockBaseLayer, AllocatingTransform> T1(M);
+
+ // Create a second object transform layer using a transform (as a lambda)
+ // that mutates objects in place, and deals in naked pointers
+ ObjectTransformLayer<MockBaseLayer,
+ std::function<MockObjectFile *(MockObjectFile *)>>
+ T2(M, [](MockObjectFile *Obj) {
+ ++(*Obj);
+ return Obj;
+ });
+
+ // Instantiate some mock objects to use below
+ MockObjectFile MockObject1 = 211;
+ MockObjectFile MockObject2 = 222;
+ MockMemoryManager MockManager = 233;
+ MockSymbolResolver MockResolver = 244;
+
+ // Test addObjectSet with T1 (allocating, unique pointers)
+ std::vector<std::unique_ptr<MockObjectFile>> Objs1;
+ Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject1));
+ Objs1.push_back(llvm::make_unique<MockObjectFile>(MockObject2));
+ auto MM = llvm::make_unique<MockMemoryManager>(MockManager);
+ auto SR = llvm::make_unique<MockSymbolResolver>(MockResolver);
+ M.expectAddObjectSet(Objs1, MM.get(), SR.get());
+ auto H = T1.addObjectSet(Objs1, std::move(MM), std::move(SR));
+ M.verifyAddObjectSet(H);
+
+ // Test addObjectSet with T2 (mutating, naked pointers)
+ llvm::SmallVector<MockObjectFile *, 2> Objs2;
+ Objs2.push_back(&MockObject1);
+ Objs2.push_back(&MockObject2);
+ M.expectAddObjectSet(Objs2, &MockManager, &MockResolver);
+ H = T2.addObjectSet(Objs2, &MockManager, &MockResolver);
+ M.verifyAddObjectSet(H);
+ EXPECT_EQ(212, MockObject1) << "Expected mutation";
+ EXPECT_EQ(223, MockObject2) << "Expected mutation";
+
+ // Test removeObjectSet
+ M.expectRemoveObjectSet(H);
+ T1.removeObjectSet(H);
+ M.verifyRemoveObjectSet();
+
+ // Test findSymbol
+ std::string Name = "foo";
+ bool ExportedOnly = true;
+ M.expectFindSymbol(Name, ExportedOnly);
+ JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly);
+ M.verifyFindSymbol(Symbol);
+
+ // Test findSymbolIn
+ Name = "bar";
+ ExportedOnly = false;
+ M.expectFindSymbolIn(H, Name, ExportedOnly);
+ Symbol = T1.findSymbolIn(H, Name, ExportedOnly);
+ M.verifyFindSymbolIn(Symbol);
+
+ // Test emitAndFinalize
+ M.expectEmitAndFinalize(H);
+ T2.emitAndFinalize(H);
+ M.verifyEmitAndFinalize();
+
+ // Test mapSectionAddress
+ char Buffer[24];
+ TargetAddress MockAddress = 255;
+ M.expectMapSectionAddress(H, Buffer, MockAddress);
+ T1.mapSectionAddress(H, Buffer, MockAddress);
+ M.verifyMapSectionAddress();
+
+ // Verify transform getter (non-const)
+ MockObjectFile Mutatee = 277;
+ MockObjectFile *Out = T2.getTransform()(&Mutatee);
+ EXPECT_EQ(&Mutatee, Out) << "Expected in-place transform";
+ EXPECT_EQ(278, Mutatee) << "Expected incrementing transform";
+
+ // Verify transform getter (const)
+ auto OwnedObj = llvm::make_unique<MockObjectFile>(288);
+ const auto &T1C = T1;
+ OwnedObj = T1C.getTransform()(std::move(OwnedObj));
+ EXPECT_EQ(289, *OwnedObj) << "Expected incrementing transform";
+}
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
new file mode 100644
index 00000000000..776d26970a3
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -0,0 +1,160 @@
+//===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "gtest/gtest.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/OrcBindings.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/TargetMachine.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace llvm {
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
+
+class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
+protected:
+ std::unique_ptr<Module> createTestModule(const Triple &TT) {
+ ModuleBuilder MB(getGlobalContext(), TT.str(), "");
+ Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
+ Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
+
+ Main->getBasicBlockList().push_back(BasicBlock::Create(getGlobalContext()));
+ IRBuilder<> B(&Main->back());
+ Value* Result = B.CreateCall(TestFunc);
+ B.CreateRet(Result);
+
+ return MB.takeModule();
+ }
+
+ typedef int (*MainFnTy)();
+
+ static int myTestFuncImpl() {
+ return 42;
+ }
+
+ static char *testFuncName;
+
+ static uint64_t myResolver(const char *Name, void *Ctx) {
+ if (!strncmp(Name, testFuncName, 8))
+ return (uint64_t)&myTestFuncImpl;
+ return 0;
+ }
+
+ struct CompileContext {
+ CompileContext() : Compiled(false) { }
+
+ OrcCAPIExecutionTest* APIExecTest;
+ std::unique_ptr<Module> M;
+ LLVMOrcModuleHandle H;
+ bool Compiled;
+ };
+
+ static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
+ void *Ctx) {
+ CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
+ auto *ET = CCtx->APIExecTest;
+ CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
+ CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, wrap(CCtx->M.get()),
+ myResolver, nullptr);
+ CCtx->Compiled = true;
+ LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main");
+ LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
+ return MainAddr;
+ }
+};
+
+char *OrcCAPIExecutionTest::testFuncName = nullptr;
+
+TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
+ if (!TM)
+ return;
+
+ LLVMOrcJITStackRef JIT =
+ LLVMOrcCreateInstance(wrap(TM.get()));
+
+ std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ LLVMOrcModuleHandle H =
+ LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
+ MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
+ int Result = MainFn();
+ EXPECT_EQ(Result, 42)
+ << "Eagerly JIT'd code did not return expected result";
+
+ LLVMOrcRemoveModule(JIT, H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
+TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
+ if (!TM)
+ return;
+
+ LLVMOrcJITStackRef JIT =
+ LLVMOrcCreateInstance(wrap(TM.get()));
+
+ std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ LLVMOrcModuleHandle H =
+ LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
+ MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
+ int Result = MainFn();
+ EXPECT_EQ(Result, 42)
+ << "Lazily JIT'd code did not return expected result";
+
+ LLVMOrcRemoveModule(JIT, H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
+TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
+ if (!TM)
+ return;
+
+ LLVMOrcJITStackRef JIT =
+ LLVMOrcCreateInstance(wrap(TM.get()));
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ CompileContext C;
+ C.APIExecTest = this;
+ LLVMOrcCreateIndirectStub(JIT, "foo",
+ LLVMOrcCreateLazyCompileCallback(JIT,
+ myCompileCallback,
+ &C));
+ MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo");
+ int Result = FooFn();
+ EXPECT_TRUE(C.Compiled)
+ << "Function wasn't lazily compiled";
+ EXPECT_EQ(Result, 42)
+ << "Direct-callback JIT'd code did not return expected result";
+
+ C.Compiled = false;
+ FooFn();
+ EXPECT_FALSE(C.Compiled)
+ << "Direct-callback JIT'd code was JIT'd twice";
+
+ LLVMOrcRemoveModule(JIT, C.H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
+} // namespace llvm
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
new file mode 100644
index 00000000000..17d1e9c9276
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
@@ -0,0 +1,25 @@
+//===--------- OrcTestCommon.cpp - Utilities for Orc Unit Tests -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common utilities for Orc unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+
+using namespace llvm;
+
+bool OrcExecutionTest::NativeTargetInitialized = false;
+
+ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple,
+ StringRef Name)
+ : M(new Module(Name, Context)) {
+ if (Triple != "")
+ M->setTargetTriple(Triple);
+}
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
new file mode 100644
index 00000000000..f480e0789ae
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
@@ -0,0 +1,179 @@
+//===------ OrcTestCommon.h - Utilities for Orc Unit Tests ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Common utilities for the Orc unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
+#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
+
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/TypeBuilder.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/JITSymbol.h"
+#include "llvm/Support/TargetSelect.h"
+#include <memory>
+
+namespace llvm {
+
+// Base class for Orc tests that will execute code.
+class OrcExecutionTest {
+public:
+
+ OrcExecutionTest() {
+ if (!NativeTargetInitialized) {
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmParser();
+ InitializeNativeTargetAsmPrinter();
+ NativeTargetInitialized = true;
+ }
+
+ // Try to select a TargetMachine for the host.
+ TM.reset(EngineBuilder().selectTarget());
+
+ if (TM) {
+ // If we found a TargetMachine, check that it's one that Orc supports.
+ const Triple& TT = TM->getTargetTriple();
+ if (TT.getArch() != Triple::x86_64 || !TT.isOSDarwin())
+ TM = nullptr;
+ }
+ };
+
+protected:
+ std::unique_ptr<TargetMachine> TM;
+private:
+ static bool NativeTargetInitialized;
+};
+
+class ModuleBuilder {
+public:
+ ModuleBuilder(LLVMContext &Context, StringRef Triple,
+ StringRef Name);
+
+ template <typename FuncType>
+ Function* createFunctionDecl(StringRef Name) {
+ return Function::Create(
+ TypeBuilder<FuncType, false>::get(M->getContext()),
+ GlobalValue::ExternalLinkage, Name, M.get());
+ }
+
+ Module* getModule() { return M.get(); }
+ const Module* getModule() const { return M.get(); }
+ std::unique_ptr<Module> takeModule() { return std::move(M); }
+
+private:
+ std::unique_ptr<Module> M;
+};
+
+// Dummy struct type.
+struct DummyStruct {
+ int X[256];
+};
+
+// TypeBuilder specialization for DummyStruct.
+template <bool XCompile>
+class TypeBuilder<DummyStruct, XCompile> {
+public:
+ static StructType *get(LLVMContext &Context) {
+ return StructType::get(
+ TypeBuilder<types::i<32>[256], XCompile>::get(Context), nullptr);
+ }
+};
+
+template <typename HandleT,
+ typename AddModuleSetFtor,
+ typename RemoveModuleSetFtor,
+ typename FindSymbolFtor,
+ typename FindSymbolInFtor>
+class MockBaseLayer {
+public:
+
+ typedef HandleT ModuleSetHandleT;
+
+ MockBaseLayer(AddModuleSetFtor &&AddModuleSet,
+ RemoveModuleSetFtor &&RemoveModuleSet,
+ FindSymbolFtor &&FindSymbol,
+ FindSymbolInFtor &&FindSymbolIn)
+ : AddModuleSet(AddModuleSet), RemoveModuleSet(RemoveModuleSet),
+ FindSymbol(FindSymbol), FindSymbolIn(FindSymbolIn)
+ {}
+
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ return AddModuleSet(std::move(Ms), std::move(MemMgr), std::move(Resolver));
+ }
+
+ void removeModuleSet(ModuleSetHandleT H) {
+ RemoveModuleSet(H);
+ }
+
+ orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ return FindSymbol(Name, ExportedSymbolsOnly);
+ }
+
+ orc::JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return FindSymbolIn(H, Name, ExportedSymbolsOnly);
+ }
+
+private:
+ AddModuleSetFtor AddModuleSet;
+ RemoveModuleSetFtor RemoveModuleSet;
+ FindSymbolFtor FindSymbol;
+ FindSymbolInFtor FindSymbolIn;
+};
+
+template <typename ModuleSetHandleT,
+ typename AddModuleSetFtor,
+ typename RemoveModuleSetFtor,
+ typename FindSymbolFtor,
+ typename FindSymbolInFtor>
+MockBaseLayer<ModuleSetHandleT, AddModuleSetFtor, RemoveModuleSetFtor,
+ FindSymbolFtor, FindSymbolInFtor>
+createMockBaseLayer(AddModuleSetFtor &&AddModuleSet,
+ RemoveModuleSetFtor &&RemoveModuleSet,
+ FindSymbolFtor &&FindSymbol,
+ FindSymbolInFtor &&FindSymbolIn) {
+ return MockBaseLayer<ModuleSetHandleT, AddModuleSetFtor, RemoveModuleSetFtor,
+ FindSymbolFtor, FindSymbolInFtor>(
+ std::forward<AddModuleSetFtor>(AddModuleSet),
+ std::forward<RemoveModuleSetFtor>(RemoveModuleSet),
+ std::forward<FindSymbolFtor>(FindSymbol),
+ std::forward<FindSymbolInFtor>(FindSymbolIn));
+}
+
+template <typename ReturnT>
+class DoNothingAndReturn {
+public:
+ DoNothingAndReturn(ReturnT Val) : Val(Val) {}
+
+ template <typename... Args>
+ ReturnT operator()(Args...) const { return Val; }
+private:
+ ReturnT Val;
+};
+
+template <>
+class DoNothingAndReturn<void> {
+public:
+ template <typename... Args>
+ void operator()(Args...) const { }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp b/gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
new file mode 100644
index 00000000000..8215144a514
--- /dev/null
+++ b/gnu/llvm/unittests/ExecutionEngine/Orc/RPCUtilsTest.cpp
@@ -0,0 +1,147 @@
+//===----------- RPCUtilsTest.cpp - Unit tests the Orc RPC utils ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/RPCChannel.h"
+#include "llvm/ExecutionEngine/Orc/RPCUtils.h"
+#include "gtest/gtest.h"
+
+#include <queue>
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::remote;
+
+class QueueChannel : public RPCChannel {
+public:
+ QueueChannel(std::queue<char> &Queue) : Queue(Queue) {}
+
+ std::error_code readBytes(char *Dst, unsigned Size) override {
+ while (Size--) {
+ *Dst++ = Queue.front();
+ Queue.pop();
+ }
+ return std::error_code();
+ }
+
+ std::error_code appendBytes(const char *Src, unsigned Size) override {
+ while (Size--)
+ Queue.push(*Src++);
+ return std::error_code();
+ }
+
+ std::error_code send() override { return std::error_code(); }
+
+private:
+ std::queue<char> &Queue;
+};
+
+class DummyRPC : public testing::Test,
+ public RPC<QueueChannel> {
+public:
+ typedef Procedure<1, bool> Proc1;
+ typedef Procedure<2, int8_t,
+ uint8_t,
+ int16_t,
+ uint16_t,
+ int32_t,
+ uint32_t,
+ int64_t,
+ uint64_t,
+ bool,
+ std::string,
+ std::vector<int>> AllTheTypes;
+};
+
+
+TEST_F(DummyRPC, TestBasic) {
+ std::queue<char> Queue;
+ QueueChannel C(Queue);
+
+ {
+ // Make a call to Proc1.
+ auto EC = call<Proc1>(C, true);
+ EXPECT_FALSE(EC) << "Simple call over queue failed";
+ }
+
+ {
+ // Expect a call to Proc1.
+ auto EC = expect<Proc1>(C,
+ [&](bool &B) {
+ EXPECT_EQ(B, true)
+ << "Bool serialization broken";
+ return std::error_code();
+ });
+ EXPECT_FALSE(EC) << "Simple expect over queue failed";
+ }
+}
+
+TEST_F(DummyRPC, TestSerialization) {
+ std::queue<char> Queue;
+ QueueChannel C(Queue);
+
+ {
+ // Make a call to Proc1.
+ std::vector<int> v({42, 7});
+ auto EC = call<AllTheTypes>(C,
+ -101,
+ 250,
+ -10000,
+ 10000,
+ -1000000000,
+ 1000000000,
+ -10000000000,
+ 10000000000,
+ true,
+ "foo",
+ v);
+ EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
+ }
+
+ {
+ // Expect a call to Proc1.
+ auto EC = expect<AllTheTypes>(C,
+ [&](int8_t &s8,
+ uint8_t &u8,
+ int16_t &s16,
+ uint16_t &u16,
+ int32_t &s32,
+ uint32_t &u32,
+ int64_t &s64,
+ uint64_t &u64,
+ bool &b,
+ std::string &s,
+ std::vector<int> &v) {
+
+ EXPECT_EQ(s8, -101)
+ << "int8_t serialization broken";
+ EXPECT_EQ(u8, 250)
+ << "uint8_t serialization broken";
+ EXPECT_EQ(s16, -10000)
+ << "int16_t serialization broken";
+ EXPECT_EQ(u16, 10000)
+ << "uint16_t serialization broken";
+ EXPECT_EQ(s32, -1000000000)
+ << "int32_t serialization broken";
+ EXPECT_EQ(u32, 1000000000ULL)
+ << "uint32_t serialization broken";
+ EXPECT_EQ(s64, -10000000000)
+ << "int64_t serialization broken";
+ EXPECT_EQ(u64, 10000000000ULL)
+ << "uint64_t serialization broken";
+ EXPECT_EQ(b, true)
+ << "bool serialization broken";
+ EXPECT_EQ(s, "foo")
+ << "std::string serialization broken";
+ EXPECT_EQ(v, std::vector<int>({42, 7}))
+ << "std::vector serialization broken";
+ return std::error_code();
+ });
+ EXPECT_FALSE(EC) << "Big (serialization test) call over queue failed";
+ }
+}
diff --git a/gnu/llvm/unittests/IR/AsmWriterTest.cpp b/gnu/llvm/unittests/IR/AsmWriterTest.cpp
new file mode 100644
index 00000000000..c7e7bb5c9f0
--- /dev/null
+++ b/gnu/llvm/unittests/IR/AsmWriterTest.cpp
@@ -0,0 +1,37 @@
+//===- llvm/unittest/IR/AsmWriter.cpp - AsmWriter tests -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(AsmWriterTest, DebugPrintDetachedInstruction) {
+
+ // PR24852: Ensure that an instruction can be printed even when it
+ // has metadata attached but no parent.
+ LLVMContext Ctx;
+ auto Ty = Type::getInt32Ty(Ctx);
+ auto Undef = UndefValue::get(Ty);
+ std::unique_ptr<BinaryOperator> Add(BinaryOperator::CreateAdd(Undef, Undef));
+ Add->setMetadata(
+ "", MDNode::get(Ctx, {ConstantAsMetadata::get(ConstantInt::get(Ty, 1))}));
+ std::string S;
+ raw_string_ostream OS(S);
+ Add->print(OS);
+ std::size_t r = OS.str().find("<badref> = add i32 undef, undef, !<empty");
+ EXPECT_TRUE(r != std::string::npos);
+}
+
+}
diff --git a/gnu/llvm/unittests/IR/AttributesTest.cpp b/gnu/llvm/unittests/IR/AttributesTest.cpp
new file mode 100644
index 00000000000..ebcb772bc37
--- /dev/null
+++ b/gnu/llvm/unittests/IR/AttributesTest.cpp
@@ -0,0 +1,47 @@
+//===- llvm/unittest/IR/AttributesTest.cpp - Attributes 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/IR/Attributes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(Attributes, Uniquing) {
+ LLVMContext C;
+
+ Attribute AttrA = Attribute::get(C, Attribute::AlwaysInline);
+ Attribute AttrB = Attribute::get(C, Attribute::AlwaysInline);
+ EXPECT_EQ(AttrA, AttrB);
+
+ AttributeSet ASs[] = {
+ AttributeSet::get(C, 1, Attribute::ZExt),
+ AttributeSet::get(C, 2, Attribute::SExt)
+ };
+
+ AttributeSet SetA = AttributeSet::get(C, ASs);
+ AttributeSet SetB = AttributeSet::get(C, ASs);
+ EXPECT_EQ(SetA, SetB);
+}
+
+TEST(Attributes, Ordering) {
+ LLVMContext C;
+
+ AttributeSet ASs[] = {
+ AttributeSet::get(C, 2, Attribute::ZExt),
+ AttributeSet::get(C, 1, Attribute::SExt)
+ };
+
+ AttributeSet SetA = AttributeSet::get(C, ASs);
+ AttributeSet SetB = SetA.removeAttributes(C, 1, ASs[1]);
+ EXPECT_NE(SetA, SetB);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/IR/CMakeLists.txt b/gnu/llvm/unittests/IR/CMakeLists.txt
new file mode 100644
index 00000000000..5aad8edc913
--- /dev/null
+++ b/gnu/llvm/unittests/IR/CMakeLists.txt
@@ -0,0 +1,41 @@
+set(LLVM_LINK_COMPONENTS
+ Analysis
+ AsmParser
+ Core
+ Support
+ )
+
+set(IRSources
+ AsmWriterTest.cpp
+ AttributesTest.cpp
+ ConstantRangeTest.cpp
+ ConstantsTest.cpp
+ DebugInfoTest.cpp
+ DominatorTreeTest.cpp
+ IRBuilderTest.cpp
+ InstructionsTest.cpp
+ LegacyPassManagerTest.cpp
+ MDBuilderTest.cpp
+ MetadataTest.cpp
+ PassManagerTest.cpp
+ PatternMatch.cpp
+ TypeBuilderTest.cpp
+ TypesTest.cpp
+ UseTest.cpp
+ UserTest.cpp
+ ValueHandleTest.cpp
+ ValueMapTest.cpp
+ ValueTest.cpp
+ VerifierTest.cpp
+ WaymarkTest.cpp
+ )
+
+# HACK: Declare a couple of source files as optionally compiled to satisfy the
+# missing-file-checker in LLVM's weird CMake build.
+set(LLVM_OPTIONAL_SOURCES
+ ValueMapTest.cpp
+ )
+
+add_llvm_unittest(IRTests
+ ${IRSources}
+ )
diff --git a/gnu/llvm/unittests/IR/ConstantRangeTest.cpp b/gnu/llvm/unittests/IR/ConstantRangeTest.cpp
new file mode 100644
index 00000000000..1f32eea3e43
--- /dev/null
+++ b/gnu/llvm/unittests/IR/ConstantRangeTest.cpp
@@ -0,0 +1,623 @@
+//===- ConstantRangeTest.cpp - ConstantRange tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/ConstantRange.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Operator.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class ConstantRangeTest : public ::testing::Test {
+protected:
+ static ConstantRange Full;
+ static ConstantRange Empty;
+ static ConstantRange One;
+ static ConstantRange Some;
+ static ConstantRange Wrap;
+};
+
+ConstantRange ConstantRangeTest::Full(16);
+ConstantRange ConstantRangeTest::Empty(16, false);
+ConstantRange ConstantRangeTest::One(APInt(16, 0xa));
+ConstantRange ConstantRangeTest::Some(APInt(16, 0xa), APInt(16, 0xaaa));
+ConstantRange ConstantRangeTest::Wrap(APInt(16, 0xaaa), APInt(16, 0xa));
+
+TEST_F(ConstantRangeTest, Basics) {
+ EXPECT_TRUE(Full.isFullSet());
+ EXPECT_FALSE(Full.isEmptySet());
+ EXPECT_TRUE(Full.inverse().isEmptySet());
+ EXPECT_FALSE(Full.isWrappedSet());
+ EXPECT_TRUE(Full.contains(APInt(16, 0x0)));
+ EXPECT_TRUE(Full.contains(APInt(16, 0x9)));
+ EXPECT_TRUE(Full.contains(APInt(16, 0xa)));
+ EXPECT_TRUE(Full.contains(APInt(16, 0xaa9)));
+ EXPECT_TRUE(Full.contains(APInt(16, 0xaaa)));
+
+ EXPECT_FALSE(Empty.isFullSet());
+ EXPECT_TRUE(Empty.isEmptySet());
+ EXPECT_TRUE(Empty.inverse().isFullSet());
+ EXPECT_FALSE(Empty.isWrappedSet());
+ EXPECT_FALSE(Empty.contains(APInt(16, 0x0)));
+ EXPECT_FALSE(Empty.contains(APInt(16, 0x9)));
+ EXPECT_FALSE(Empty.contains(APInt(16, 0xa)));
+ EXPECT_FALSE(Empty.contains(APInt(16, 0xaa9)));
+ EXPECT_FALSE(Empty.contains(APInt(16, 0xaaa)));
+
+ EXPECT_FALSE(One.isFullSet());
+ EXPECT_FALSE(One.isEmptySet());
+ EXPECT_FALSE(One.isWrappedSet());
+ EXPECT_FALSE(One.contains(APInt(16, 0x0)));
+ EXPECT_FALSE(One.contains(APInt(16, 0x9)));
+ EXPECT_TRUE(One.contains(APInt(16, 0xa)));
+ EXPECT_FALSE(One.contains(APInt(16, 0xaa9)));
+ EXPECT_FALSE(One.contains(APInt(16, 0xaaa)));
+ EXPECT_FALSE(One.inverse().contains(APInt(16, 0xa)));
+
+ EXPECT_FALSE(Some.isFullSet());
+ EXPECT_FALSE(Some.isEmptySet());
+ EXPECT_FALSE(Some.isWrappedSet());
+ EXPECT_FALSE(Some.contains(APInt(16, 0x0)));
+ EXPECT_FALSE(Some.contains(APInt(16, 0x9)));
+ EXPECT_TRUE(Some.contains(APInt(16, 0xa)));
+ EXPECT_TRUE(Some.contains(APInt(16, 0xaa9)));
+ EXPECT_FALSE(Some.contains(APInt(16, 0xaaa)));
+
+ EXPECT_FALSE(Wrap.isFullSet());
+ EXPECT_FALSE(Wrap.isEmptySet());
+ EXPECT_TRUE(Wrap.isWrappedSet());
+ EXPECT_TRUE(Wrap.contains(APInt(16, 0x0)));
+ EXPECT_TRUE(Wrap.contains(APInt(16, 0x9)));
+ EXPECT_FALSE(Wrap.contains(APInt(16, 0xa)));
+ EXPECT_FALSE(Wrap.contains(APInt(16, 0xaa9)));
+ EXPECT_TRUE(Wrap.contains(APInt(16, 0xaaa)));
+}
+
+TEST_F(ConstantRangeTest, Equality) {
+ EXPECT_EQ(Full, Full);
+ EXPECT_EQ(Empty, Empty);
+ EXPECT_EQ(One, One);
+ EXPECT_EQ(Some, Some);
+ EXPECT_EQ(Wrap, Wrap);
+ EXPECT_NE(Full, Empty);
+ EXPECT_NE(Full, One);
+ EXPECT_NE(Full, Some);
+ EXPECT_NE(Full, Wrap);
+ EXPECT_NE(Empty, One);
+ EXPECT_NE(Empty, Some);
+ EXPECT_NE(Empty, Wrap);
+ EXPECT_NE(One, Some);
+ EXPECT_NE(One, Wrap);
+ EXPECT_NE(Some, Wrap);
+}
+
+TEST_F(ConstantRangeTest, SingleElement) {
+ EXPECT_EQ(Full.getSingleElement(), static_cast<APInt *>(nullptr));
+ EXPECT_EQ(Empty.getSingleElement(), static_cast<APInt *>(nullptr));
+ EXPECT_EQ(*One.getSingleElement(), APInt(16, 0xa));
+ EXPECT_EQ(Some.getSingleElement(), static_cast<APInt *>(nullptr));
+ EXPECT_EQ(Wrap.getSingleElement(), static_cast<APInt *>(nullptr));
+
+ EXPECT_FALSE(Full.isSingleElement());
+ EXPECT_FALSE(Empty.isSingleElement());
+ EXPECT_TRUE(One.isSingleElement());
+ EXPECT_FALSE(Some.isSingleElement());
+ EXPECT_FALSE(Wrap.isSingleElement());
+}
+
+TEST_F(ConstantRangeTest, GetSetSize) {
+ EXPECT_EQ(Full.getSetSize(), APInt(17, 65536));
+ EXPECT_EQ(Empty.getSetSize(), APInt(17, 0));
+ EXPECT_EQ(One.getSetSize(), APInt(17, 1));
+ EXPECT_EQ(Some.getSetSize(), APInt(17, 0xaa0));
+
+ ConstantRange Wrap(APInt(4, 7), APInt(4, 3));
+ ConstantRange Wrap2(APInt(4, 8), APInt(4, 7));
+ EXPECT_EQ(Wrap.getSetSize(), APInt(5, 12));
+ EXPECT_EQ(Wrap2.getSetSize(), APInt(5, 15));
+}
+
+TEST_F(ConstantRangeTest, GetMinsAndMaxes) {
+ EXPECT_EQ(Full.getUnsignedMax(), APInt(16, UINT16_MAX));
+ EXPECT_EQ(One.getUnsignedMax(), APInt(16, 0xa));
+ EXPECT_EQ(Some.getUnsignedMax(), APInt(16, 0xaa9));
+ EXPECT_EQ(Wrap.getUnsignedMax(), APInt(16, UINT16_MAX));
+
+ EXPECT_EQ(Full.getUnsignedMin(), APInt(16, 0));
+ EXPECT_EQ(One.getUnsignedMin(), APInt(16, 0xa));
+ EXPECT_EQ(Some.getUnsignedMin(), APInt(16, 0xa));
+ EXPECT_EQ(Wrap.getUnsignedMin(), APInt(16, 0));
+
+ EXPECT_EQ(Full.getSignedMax(), APInt(16, INT16_MAX));
+ EXPECT_EQ(One.getSignedMax(), APInt(16, 0xa));
+ EXPECT_EQ(Some.getSignedMax(), APInt(16, 0xaa9));
+ EXPECT_EQ(Wrap.getSignedMax(), APInt(16, INT16_MAX));
+
+ EXPECT_EQ(Full.getSignedMin(), APInt(16, (uint64_t)INT16_MIN));
+ EXPECT_EQ(One.getSignedMin(), APInt(16, 0xa));
+ EXPECT_EQ(Some.getSignedMin(), APInt(16, 0xa));
+ EXPECT_EQ(Wrap.getSignedMin(), APInt(16, (uint64_t)INT16_MIN));
+
+ // Found by Klee
+ EXPECT_EQ(ConstantRange(APInt(4, 7), APInt(4, 0)).getSignedMax(),
+ APInt(4, 7));
+}
+
+TEST_F(ConstantRangeTest, SignWrapped) {
+ EXPECT_TRUE(Full.isSignWrappedSet());
+ EXPECT_FALSE(Empty.isSignWrappedSet());
+ EXPECT_FALSE(One.isSignWrappedSet());
+ EXPECT_FALSE(Some.isSignWrappedSet());
+ EXPECT_TRUE(Wrap.isSignWrappedSet());
+
+ EXPECT_FALSE(ConstantRange(APInt(8, 127), APInt(8, 128)).isSignWrappedSet());
+ EXPECT_TRUE(ConstantRange(APInt(8, 127), APInt(8, 129)).isSignWrappedSet());
+ EXPECT_FALSE(ConstantRange(APInt(8, 128), APInt(8, 129)).isSignWrappedSet());
+ EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 9)).isSignWrappedSet());
+ EXPECT_TRUE(ConstantRange(APInt(8, 10), APInt(8, 250)).isSignWrappedSet());
+ EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 10)).isSignWrappedSet());
+ EXPECT_FALSE(ConstantRange(APInt(8, 250), APInt(8, 251)).isSignWrappedSet());
+}
+
+TEST_F(ConstantRangeTest, Trunc) {
+ ConstantRange TFull = Full.truncate(10);
+ ConstantRange TEmpty = Empty.truncate(10);
+ ConstantRange TOne = One.truncate(10);
+ ConstantRange TSome = Some.truncate(10);
+ ConstantRange TWrap = Wrap.truncate(10);
+ EXPECT_TRUE(TFull.isFullSet());
+ EXPECT_TRUE(TEmpty.isEmptySet());
+ EXPECT_EQ(TOne, ConstantRange(One.getLower().trunc(10),
+ One.getUpper().trunc(10)));
+ EXPECT_TRUE(TSome.isFullSet());
+}
+
+TEST_F(ConstantRangeTest, ZExt) {
+ ConstantRange ZFull = Full.zeroExtend(20);
+ ConstantRange ZEmpty = Empty.zeroExtend(20);
+ ConstantRange ZOne = One.zeroExtend(20);
+ ConstantRange ZSome = Some.zeroExtend(20);
+ ConstantRange ZWrap = Wrap.zeroExtend(20);
+ EXPECT_EQ(ZFull, ConstantRange(APInt(20, 0), APInt(20, 0x10000)));
+ EXPECT_TRUE(ZEmpty.isEmptySet());
+ EXPECT_EQ(ZOne, ConstantRange(One.getLower().zext(20),
+ One.getUpper().zext(20)));
+ EXPECT_EQ(ZSome, ConstantRange(Some.getLower().zext(20),
+ Some.getUpper().zext(20)));
+ EXPECT_EQ(ZWrap, ConstantRange(APInt(20, 0), APInt(20, 0x10000)));
+
+ // zext([5, 0), 3->7) = [5, 8)
+ ConstantRange FiveZero(APInt(3, 5), APInt(3, 0));
+ EXPECT_EQ(FiveZero.zeroExtend(7), ConstantRange(APInt(7, 5), APInt(7, 8)));
+}
+
+TEST_F(ConstantRangeTest, SExt) {
+ ConstantRange SFull = Full.signExtend(20);
+ ConstantRange SEmpty = Empty.signExtend(20);
+ ConstantRange SOne = One.signExtend(20);
+ ConstantRange SSome = Some.signExtend(20);
+ ConstantRange SWrap = Wrap.signExtend(20);
+ EXPECT_EQ(SFull, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true),
+ APInt(20, INT16_MAX + 1, true)));
+ EXPECT_TRUE(SEmpty.isEmptySet());
+ EXPECT_EQ(SOne, ConstantRange(One.getLower().sext(20),
+ One.getUpper().sext(20)));
+ EXPECT_EQ(SSome, ConstantRange(Some.getLower().sext(20),
+ Some.getUpper().sext(20)));
+ EXPECT_EQ(SWrap, ConstantRange(APInt(20, (uint64_t)INT16_MIN, true),
+ APInt(20, INT16_MAX + 1, true)));
+
+ EXPECT_EQ(ConstantRange(APInt(8, 120), APInt(8, 140)).signExtend(16),
+ ConstantRange(APInt(16, -128), APInt(16, 128)));
+
+ EXPECT_EQ(ConstantRange(APInt(16, 0x0200), APInt(16, 0x8000)).signExtend(19),
+ ConstantRange(APInt(19, 0x0200), APInt(19, 0x8000)));
+}
+
+TEST_F(ConstantRangeTest, IntersectWith) {
+ EXPECT_EQ(Empty.intersectWith(Full), Empty);
+ EXPECT_EQ(Empty.intersectWith(Empty), Empty);
+ EXPECT_EQ(Empty.intersectWith(One), Empty);
+ EXPECT_EQ(Empty.intersectWith(Some), Empty);
+ EXPECT_EQ(Empty.intersectWith(Wrap), Empty);
+ EXPECT_EQ(Full.intersectWith(Full), Full);
+ EXPECT_EQ(Some.intersectWith(Some), Some);
+ EXPECT_EQ(Some.intersectWith(One), One);
+ EXPECT_EQ(Full.intersectWith(One), One);
+ EXPECT_EQ(Full.intersectWith(Some), Some);
+ EXPECT_EQ(Some.intersectWith(Wrap), Empty);
+ EXPECT_EQ(One.intersectWith(Wrap), Empty);
+ EXPECT_EQ(One.intersectWith(Wrap), Wrap.intersectWith(One));
+
+ // Klee generated testcase from PR4545.
+ // The intersection of i16 [4, 2) and [6, 5) is disjoint, looking like
+ // 01..4.6789ABCDEF where the dots represent values not in the intersection.
+ ConstantRange LHS(APInt(16, 4), APInt(16, 2));
+ ConstantRange RHS(APInt(16, 6), APInt(16, 5));
+ EXPECT_TRUE(LHS.intersectWith(RHS) == LHS);
+
+ // previous bug: intersection of [min, 3) and [2, max) should be 2
+ LHS = ConstantRange(APInt(32, -2147483646), APInt(32, 3));
+ RHS = ConstantRange(APInt(32, 2), APInt(32, 2147483646));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2)));
+
+ // [2, 0) /\ [4, 3) = [2, 0)
+ LHS = ConstantRange(APInt(32, 2), APInt(32, 0));
+ RHS = ConstantRange(APInt(32, 4), APInt(32, 3));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 2), APInt(32, 0)));
+
+ // [2, 0) /\ [4, 2) = [4, 0)
+ LHS = ConstantRange(APInt(32, 2), APInt(32, 0));
+ RHS = ConstantRange(APInt(32, 4), APInt(32, 2));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 0)));
+
+ // [4, 2) /\ [5, 1) = [5, 1)
+ LHS = ConstantRange(APInt(32, 4), APInt(32, 2));
+ RHS = ConstantRange(APInt(32, 5), APInt(32, 1));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 5), APInt(32, 1)));
+
+ // [2, 0) /\ [7, 4) = [7, 4)
+ LHS = ConstantRange(APInt(32, 2), APInt(32, 0));
+ RHS = ConstantRange(APInt(32, 7), APInt(32, 4));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 7), APInt(32, 4)));
+
+ // [4, 2) /\ [1, 0) = [1, 0)
+ LHS = ConstantRange(APInt(32, 4), APInt(32, 2));
+ RHS = ConstantRange(APInt(32, 1), APInt(32, 0));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 4), APInt(32, 2)));
+
+ // [15, 0) /\ [7, 6) = [15, 0)
+ LHS = ConstantRange(APInt(32, 15), APInt(32, 0));
+ RHS = ConstantRange(APInt(32, 7), APInt(32, 6));
+ EXPECT_EQ(LHS.intersectWith(RHS), ConstantRange(APInt(32, 15), APInt(32, 0)));
+}
+
+TEST_F(ConstantRangeTest, UnionWith) {
+ EXPECT_EQ(Wrap.unionWith(One),
+ ConstantRange(APInt(16, 0xaaa), APInt(16, 0xb)));
+ EXPECT_EQ(One.unionWith(Wrap), Wrap.unionWith(One));
+ EXPECT_EQ(Empty.unionWith(Empty), Empty);
+ EXPECT_EQ(Full.unionWith(Full), Full);
+ EXPECT_EQ(Some.unionWith(Wrap), Full);
+
+ // PR4545
+ EXPECT_EQ(ConstantRange(APInt(16, 14), APInt(16, 1)).unionWith(
+ ConstantRange(APInt(16, 0), APInt(16, 8))),
+ ConstantRange(APInt(16, 14), APInt(16, 8)));
+ EXPECT_EQ(ConstantRange(APInt(16, 6), APInt(16, 4)).unionWith(
+ ConstantRange(APInt(16, 4), APInt(16, 0))),
+ ConstantRange(16));
+ EXPECT_EQ(ConstantRange(APInt(16, 1), APInt(16, 0)).unionWith(
+ ConstantRange(APInt(16, 2), APInt(16, 1))),
+ ConstantRange(16));
+}
+
+TEST_F(ConstantRangeTest, SetDifference) {
+ EXPECT_EQ(Full.difference(Empty), Full);
+ EXPECT_EQ(Full.difference(Full), Empty);
+ EXPECT_EQ(Empty.difference(Empty), Empty);
+ EXPECT_EQ(Empty.difference(Full), Empty);
+
+ ConstantRange A(APInt(16, 3), APInt(16, 7));
+ ConstantRange B(APInt(16, 5), APInt(16, 9));
+ ConstantRange C(APInt(16, 3), APInt(16, 5));
+ ConstantRange D(APInt(16, 7), APInt(16, 9));
+ ConstantRange E(APInt(16, 5), APInt(16, 4));
+ ConstantRange F(APInt(16, 7), APInt(16, 3));
+ EXPECT_EQ(A.difference(B), C);
+ EXPECT_EQ(B.difference(A), D);
+ EXPECT_EQ(E.difference(A), F);
+}
+
+TEST_F(ConstantRangeTest, SubtractAPInt) {
+ EXPECT_EQ(Full.subtract(APInt(16, 4)), Full);
+ EXPECT_EQ(Empty.subtract(APInt(16, 4)), Empty);
+ EXPECT_EQ(Some.subtract(APInt(16, 4)),
+ ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6)));
+ EXPECT_EQ(Wrap.subtract(APInt(16, 4)),
+ ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6)));
+ EXPECT_EQ(One.subtract(APInt(16, 4)),
+ ConstantRange(APInt(16, 0x6)));
+}
+
+TEST_F(ConstantRangeTest, Add) {
+ EXPECT_EQ(Full.add(APInt(16, 4)), Full);
+ EXPECT_EQ(Full.add(Full), Full);
+ EXPECT_EQ(Full.add(Empty), Empty);
+ EXPECT_EQ(Full.add(One), Full);
+ EXPECT_EQ(Full.add(Some), Full);
+ EXPECT_EQ(Full.add(Wrap), Full);
+ EXPECT_EQ(Empty.add(Empty), Empty);
+ EXPECT_EQ(Empty.add(One), Empty);
+ EXPECT_EQ(Empty.add(Some), Empty);
+ EXPECT_EQ(Empty.add(Wrap), Empty);
+ EXPECT_EQ(Empty.add(APInt(16, 4)), Empty);
+ EXPECT_EQ(Some.add(APInt(16, 4)),
+ ConstantRange(APInt(16, 0xe), APInt(16, 0xaae)));
+ EXPECT_EQ(Wrap.add(APInt(16, 4)),
+ ConstantRange(APInt(16, 0xaae), APInt(16, 0xe)));
+ EXPECT_EQ(One.add(APInt(16, 4)),
+ ConstantRange(APInt(16, 0xe)));
+}
+
+TEST_F(ConstantRangeTest, Sub) {
+ EXPECT_EQ(Full.sub(APInt(16, 4)), Full);
+ EXPECT_EQ(Full.sub(Full), Full);
+ EXPECT_EQ(Full.sub(Empty), Empty);
+ EXPECT_EQ(Full.sub(One), Full);
+ EXPECT_EQ(Full.sub(Some), Full);
+ EXPECT_EQ(Full.sub(Wrap), Full);
+ EXPECT_EQ(Empty.sub(Empty), Empty);
+ EXPECT_EQ(Empty.sub(One), Empty);
+ EXPECT_EQ(Empty.sub(Some), Empty);
+ EXPECT_EQ(Empty.sub(Wrap), Empty);
+ EXPECT_EQ(Empty.sub(APInt(16, 4)), Empty);
+ EXPECT_EQ(Some.sub(APInt(16, 4)),
+ ConstantRange(APInt(16, 0x6), APInt(16, 0xaa6)));
+ EXPECT_EQ(Some.sub(Some),
+ ConstantRange(APInt(16, 0xf561), APInt(16, 0xaa0)));
+ EXPECT_EQ(Wrap.sub(APInt(16, 4)),
+ ConstantRange(APInt(16, 0xaa6), APInt(16, 0x6)));
+ EXPECT_EQ(One.sub(APInt(16, 4)),
+ ConstantRange(APInt(16, 0x6)));
+}
+
+TEST_F(ConstantRangeTest, Multiply) {
+ EXPECT_EQ(Full.multiply(Full), Full);
+ EXPECT_EQ(Full.multiply(Empty), Empty);
+ EXPECT_EQ(Full.multiply(One), Full);
+ EXPECT_EQ(Full.multiply(Some), Full);
+ EXPECT_EQ(Full.multiply(Wrap), Full);
+ EXPECT_EQ(Empty.multiply(Empty), Empty);
+ EXPECT_EQ(Empty.multiply(One), Empty);
+ EXPECT_EQ(Empty.multiply(Some), Empty);
+ EXPECT_EQ(Empty.multiply(Wrap), Empty);
+ EXPECT_EQ(One.multiply(One), ConstantRange(APInt(16, 0xa*0xa),
+ APInt(16, 0xa*0xa + 1)));
+ EXPECT_EQ(One.multiply(Some), ConstantRange(APInt(16, 0xa*0xa),
+ APInt(16, 0xa*0xaa9 + 1)));
+ EXPECT_EQ(One.multiply(Wrap), Full);
+ EXPECT_EQ(Some.multiply(Some), Full);
+ EXPECT_EQ(Some.multiply(Wrap), Full);
+ EXPECT_EQ(Wrap.multiply(Wrap), Full);
+
+ ConstantRange Zero(APInt(16, 0));
+ EXPECT_EQ(Zero.multiply(Full), Zero);
+ EXPECT_EQ(Zero.multiply(Some), Zero);
+ EXPECT_EQ(Zero.multiply(Wrap), Zero);
+ EXPECT_EQ(Full.multiply(Zero), Zero);
+ EXPECT_EQ(Some.multiply(Zero), Zero);
+ EXPECT_EQ(Wrap.multiply(Zero), Zero);
+
+ // http://llvm.org/PR4545
+ EXPECT_EQ(ConstantRange(APInt(4, 1), APInt(4, 6)).multiply(
+ ConstantRange(APInt(4, 6), APInt(4, 2))),
+ ConstantRange(4, /*isFullSet=*/true));
+
+ EXPECT_EQ(ConstantRange(APInt(8, 254), APInt(8, 0)).multiply(
+ ConstantRange(APInt(8, 252), APInt(8, 4))),
+ ConstantRange(APInt(8, 250), APInt(8, 9)));
+ EXPECT_EQ(ConstantRange(APInt(8, 254), APInt(8, 255)).multiply(
+ ConstantRange(APInt(8, 2), APInt(8, 4))),
+ ConstantRange(APInt(8, 250), APInt(8, 253)));
+}
+
+TEST_F(ConstantRangeTest, UMax) {
+ EXPECT_EQ(Full.umax(Full), Full);
+ EXPECT_EQ(Full.umax(Empty), Empty);
+ EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+ EXPECT_EQ(Full.umax(Wrap), Full);
+ EXPECT_EQ(Full.umax(Some), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+ EXPECT_EQ(Empty.umax(Empty), Empty);
+ EXPECT_EQ(Empty.umax(Some), Empty);
+ EXPECT_EQ(Empty.umax(Wrap), Empty);
+ EXPECT_EQ(Empty.umax(One), Empty);
+ EXPECT_EQ(Some.umax(Some), Some);
+ EXPECT_EQ(Some.umax(Wrap), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+ EXPECT_EQ(Some.umax(One), Some);
+ // TODO: ConstantRange is currently over-conservative here.
+ EXPECT_EQ(Wrap.umax(Wrap), Full);
+ EXPECT_EQ(Wrap.umax(One), ConstantRange(APInt(16, 0xa), APInt(16, 0)));
+ EXPECT_EQ(One.umax(One), One);
+}
+
+TEST_F(ConstantRangeTest, SMax) {
+ EXPECT_EQ(Full.smax(Full), Full);
+ EXPECT_EQ(Full.smax(Empty), Empty);
+ EXPECT_EQ(Full.smax(Some), ConstantRange(APInt(16, 0xa),
+ APInt::getSignedMinValue(16)));
+ EXPECT_EQ(Full.smax(Wrap), Full);
+ EXPECT_EQ(Full.smax(One), ConstantRange(APInt(16, 0xa),
+ APInt::getSignedMinValue(16)));
+ EXPECT_EQ(Empty.smax(Empty), Empty);
+ EXPECT_EQ(Empty.smax(Some), Empty);
+ EXPECT_EQ(Empty.smax(Wrap), Empty);
+ EXPECT_EQ(Empty.smax(One), Empty);
+ EXPECT_EQ(Some.smax(Some), Some);
+ EXPECT_EQ(Some.smax(Wrap), ConstantRange(APInt(16, 0xa),
+ APInt(16, (uint64_t)INT16_MIN)));
+ EXPECT_EQ(Some.smax(One), Some);
+ EXPECT_EQ(Wrap.smax(One), ConstantRange(APInt(16, 0xa),
+ APInt(16, (uint64_t)INT16_MIN)));
+ EXPECT_EQ(One.smax(One), One);
+}
+
+TEST_F(ConstantRangeTest, UDiv) {
+ EXPECT_EQ(Full.udiv(Full), Full);
+ EXPECT_EQ(Full.udiv(Empty), Empty);
+ EXPECT_EQ(Full.udiv(One), ConstantRange(APInt(16, 0),
+ APInt(16, 0xffff / 0xa + 1)));
+ EXPECT_EQ(Full.udiv(Some), ConstantRange(APInt(16, 0),
+ APInt(16, 0xffff / 0xa + 1)));
+ EXPECT_EQ(Full.udiv(Wrap), Full);
+ EXPECT_EQ(Empty.udiv(Empty), Empty);
+ EXPECT_EQ(Empty.udiv(One), Empty);
+ EXPECT_EQ(Empty.udiv(Some), Empty);
+ EXPECT_EQ(Empty.udiv(Wrap), Empty);
+ EXPECT_EQ(One.udiv(One), ConstantRange(APInt(16, 1)));
+ EXPECT_EQ(One.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 2)));
+ EXPECT_EQ(One.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb)));
+ EXPECT_EQ(Some.udiv(Some), ConstantRange(APInt(16, 0), APInt(16, 0x111)));
+ EXPECT_EQ(Some.udiv(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa)));
+ EXPECT_EQ(Wrap.udiv(Wrap), Full);
+}
+
+TEST_F(ConstantRangeTest, Shl) {
+ EXPECT_EQ(Full.shl(Full), Full);
+ EXPECT_EQ(Full.shl(Empty), Empty);
+ EXPECT_EQ(Full.shl(One), Full); // TODO: [0, (-1 << 0xa) + 1)
+ EXPECT_EQ(Full.shl(Some), Full); // TODO: [0, (-1 << 0xa) + 1)
+ EXPECT_EQ(Full.shl(Wrap), Full);
+ EXPECT_EQ(Empty.shl(Empty), Empty);
+ EXPECT_EQ(Empty.shl(One), Empty);
+ EXPECT_EQ(Empty.shl(Some), Empty);
+ EXPECT_EQ(Empty.shl(Wrap), Empty);
+ EXPECT_EQ(One.shl(One), ConstantRange(APInt(16, 0xa << 0xa),
+ APInt(16, (0xa << 0xa) + 1)));
+ EXPECT_EQ(One.shl(Some), Full); // TODO: [0xa << 0xa, 0)
+ EXPECT_EQ(One.shl(Wrap), Full); // TODO: [0xa, 0xa << 14 + 1)
+ EXPECT_EQ(Some.shl(Some), Full); // TODO: [0xa << 0xa, 0xfc01)
+ EXPECT_EQ(Some.shl(Wrap), Full); // TODO: [0xa, 0x7ff << 0x5 + 1)
+ EXPECT_EQ(Wrap.shl(Wrap), Full);
+}
+
+TEST_F(ConstantRangeTest, Lshr) {
+ EXPECT_EQ(Full.lshr(Full), Full);
+ EXPECT_EQ(Full.lshr(Empty), Empty);
+ EXPECT_EQ(Full.lshr(One), ConstantRange(APInt(16, 0),
+ APInt(16, (0xffff >> 0xa) + 1)));
+ EXPECT_EQ(Full.lshr(Some), ConstantRange(APInt(16, 0),
+ APInt(16, (0xffff >> 0xa) + 1)));
+ EXPECT_EQ(Full.lshr(Wrap), Full);
+ EXPECT_EQ(Empty.lshr(Empty), Empty);
+ EXPECT_EQ(Empty.lshr(One), Empty);
+ EXPECT_EQ(Empty.lshr(Some), Empty);
+ EXPECT_EQ(Empty.lshr(Wrap), Empty);
+ EXPECT_EQ(One.lshr(One), ConstantRange(APInt(16, 0)));
+ EXPECT_EQ(One.lshr(Some), ConstantRange(APInt(16, 0)));
+ EXPECT_EQ(One.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xb)));
+ EXPECT_EQ(Some.lshr(Some), ConstantRange(APInt(16, 0),
+ APInt(16, (0xaaa >> 0xa) + 1)));
+ EXPECT_EQ(Some.lshr(Wrap), ConstantRange(APInt(16, 0), APInt(16, 0xaaa)));
+ EXPECT_EQ(Wrap.lshr(Wrap), Full);
+}
+
+TEST(ConstantRange, MakeAllowedICmpRegion) {
+ // PR8250
+ ConstantRange SMax = ConstantRange(APInt::getSignedMaxValue(32));
+ EXPECT_TRUE(ConstantRange::makeAllowedICmpRegion(ICmpInst::ICMP_SGT, SMax)
+ .isEmptySet());
+}
+
+TEST(ConstantRange, MakeSatisfyingICmpRegion) {
+ ConstantRange LowHalf(APInt(8, 0), APInt(8, 128));
+ ConstantRange HighHalf(APInt(8, 128), APInt(8, 0));
+ ConstantRange EmptySet(8, /* isFullSet = */ false);
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_NE, LowHalf),
+ HighHalf);
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_NE, HighHalf),
+ LowHalf);
+
+ EXPECT_TRUE(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_EQ,
+ HighHalf).isEmptySet());
+
+ ConstantRange UnsignedSample(APInt(8, 5), APInt(8, 200));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_ULT,
+ UnsignedSample),
+ ConstantRange(APInt(8, 0), APInt(8, 5)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_ULE,
+ UnsignedSample),
+ ConstantRange(APInt(8, 0), APInt(8, 6)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_UGT,
+ UnsignedSample),
+ ConstantRange(APInt(8, 200), APInt(8, 0)));
+
+ EXPECT_EQ(ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_UGE,
+ UnsignedSample),
+ ConstantRange(APInt(8, 199), APInt(8, 0)));
+
+ ConstantRange SignedSample(APInt(8, -5), APInt(8, 5));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SLT, SignedSample),
+ ConstantRange(APInt(8, -128), APInt(8, -5)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SLE, SignedSample),
+ ConstantRange(APInt(8, -128), APInt(8, -4)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SGT, SignedSample),
+ ConstantRange(APInt(8, 5), APInt(8, -128)));
+
+ EXPECT_EQ(
+ ConstantRange::makeSatisfyingICmpRegion(ICmpInst::ICMP_SGE, SignedSample),
+ ConstantRange(APInt(8, 4), APInt(8, -128)));
+}
+
+TEST(ConstantRange, MakeOverflowingRegion) {
+ const int IntMin4Bits = 8;
+ const int IntMax4Bits = 7;
+ typedef OverflowingBinaryOperator OBO;
+
+ for (int Const : {0, -1, -2, 1, 2, IntMin4Bits, IntMax4Bits}) {
+ APInt C(4, Const, true /* = isSigned */);
+
+ auto NUWRegion =
+ ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoUnsignedWrap);
+
+ EXPECT_FALSE(NUWRegion.isEmptySet());
+
+ auto NSWRegion =
+ ConstantRange::makeNoWrapRegion(Instruction::Add, C, OBO::NoSignedWrap);
+
+ EXPECT_FALSE(NSWRegion.isEmptySet());
+
+ auto NoWrapRegion = ConstantRange::makeNoWrapRegion(
+ Instruction::Add, C, OBO::NoSignedWrap | OBO::NoUnsignedWrap);
+
+ EXPECT_FALSE(NoWrapRegion.isEmptySet());
+ EXPECT_TRUE(NUWRegion.intersectWith(NSWRegion).contains(NoWrapRegion));
+
+ for (APInt I = NUWRegion.getLower(), E = NUWRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+ I.uadd_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+
+ for (APInt I = NSWRegion.getLower(), E = NSWRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+ I.sadd_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+
+ for (APInt I = NoWrapRegion.getLower(), E = NoWrapRegion.getUpper(); I != E;
+ ++I) {
+ bool Overflow = false;
+
+ I.sadd_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+
+ I.uadd_ov(C, Overflow);
+ EXPECT_FALSE(Overflow);
+ }
+ }
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/IR/ConstantsTest.cpp b/gnu/llvm/unittests/IR/ConstantsTest.cpp
new file mode 100644
index 00000000000..7471584097d
--- /dev/null
+++ b/gnu/llvm/unittests/IR/ConstantsTest.cpp
@@ -0,0 +1,455 @@
+//===- llvm/unittest/IR/ConstantsTest.cpp - Constants 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/AsmParser/Parser.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm-c/Core.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+TEST(ConstantsTest, Integer_i1) {
+ IntegerType* Int1 = IntegerType::get(getGlobalContext(), 1);
+ Constant* One = ConstantInt::get(Int1, 1, true);
+ Constant* Zero = ConstantInt::get(Int1, 0);
+ Constant* NegOne = ConstantInt::get(Int1, static_cast<uint64_t>(-1), true);
+ EXPECT_EQ(NegOne, ConstantInt::getSigned(Int1, -1));
+ Constant* Undef = UndefValue::get(Int1);
+
+ // Input: @b = constant i1 add(i1 1 , i1 1)
+ // Output: @b = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getAdd(One, One));
+
+ // @c = constant i1 add(i1 -1, i1 1)
+ // @c = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, One));
+
+ // @d = constant i1 add(i1 -1, i1 -1)
+ // @d = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getAdd(NegOne, NegOne));
+
+ // @e = constant i1 sub(i1 -1, i1 1)
+ // @e = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getSub(NegOne, One));
+
+ // @f = constant i1 sub(i1 1 , i1 -1)
+ // @f = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getSub(One, NegOne));
+
+ // @g = constant i1 sub(i1 1 , i1 1)
+ // @g = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getSub(One, One));
+
+ // @h = constant i1 shl(i1 1 , i1 1) ; undefined
+ // @h = constant i1 undef
+ EXPECT_EQ(Undef, ConstantExpr::getShl(One, One));
+
+ // @i = constant i1 shl(i1 1 , i1 0)
+ // @i = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getShl(One, Zero));
+
+ // @j = constant i1 lshr(i1 1, i1 1) ; undefined
+ // @j = constant i1 undef
+ EXPECT_EQ(Undef, ConstantExpr::getLShr(One, One));
+
+ // @m = constant i1 ashr(i1 1, i1 1) ; undefined
+ // @m = constant i1 undef
+ EXPECT_EQ(Undef, ConstantExpr::getAShr(One, One));
+
+ // @n = constant i1 mul(i1 -1, i1 1)
+ // @n = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getMul(NegOne, One));
+
+ // @o = constant i1 sdiv(i1 -1, i1 1) ; overflow
+ // @o = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getSDiv(NegOne, One));
+
+ // @p = constant i1 sdiv(i1 1 , i1 -1); overflow
+ // @p = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getSDiv(One, NegOne));
+
+ // @q = constant i1 udiv(i1 -1, i1 1)
+ // @q = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getUDiv(NegOne, One));
+
+ // @r = constant i1 udiv(i1 1, i1 -1)
+ // @r = constant i1 true
+ EXPECT_EQ(One, ConstantExpr::getUDiv(One, NegOne));
+
+ // @s = constant i1 srem(i1 -1, i1 1) ; overflow
+ // @s = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getSRem(NegOne, One));
+
+ // @t = constant i1 urem(i1 -1, i1 1)
+ // @t = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getURem(NegOne, One));
+
+ // @u = constant i1 srem(i1 1, i1 -1) ; overflow
+ // @u = constant i1 false
+ EXPECT_EQ(Zero, ConstantExpr::getSRem(One, NegOne));
+}
+
+TEST(ConstantsTest, IntSigns) {
+ IntegerType* Int8Ty = Type::getInt8Ty(getGlobalContext());
+ EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, false)->getSExtValue());
+ EXPECT_EQ(100, ConstantInt::get(Int8Ty, 100, true)->getSExtValue());
+ EXPECT_EQ(100, ConstantInt::getSigned(Int8Ty, 100)->getSExtValue());
+ EXPECT_EQ(-50, ConstantInt::get(Int8Ty, 206)->getSExtValue());
+ EXPECT_EQ(-50, ConstantInt::getSigned(Int8Ty, -50)->getSExtValue());
+ EXPECT_EQ(206U, ConstantInt::getSigned(Int8Ty, -50)->getZExtValue());
+
+ // Overflow is handled by truncation.
+ EXPECT_EQ(0x3b, ConstantInt::get(Int8Ty, 0x13b)->getSExtValue());
+}
+
+TEST(ConstantsTest, FP128Test) {
+ Type *FP128Ty = Type::getFP128Ty(getGlobalContext());
+
+ IntegerType *Int128Ty = Type::getIntNTy(getGlobalContext(), 128);
+ Constant *Zero128 = Constant::getNullValue(Int128Ty);
+ Constant *X = ConstantExpr::getUIToFP(Zero128, FP128Ty);
+ EXPECT_TRUE(isa<ConstantFP>(X));
+}
+
+TEST(ConstantsTest, PointerCast) {
+ LLVMContext &C(getGlobalContext());
+ Type *Int8PtrTy = Type::getInt8PtrTy(C);
+ Type *Int32PtrTy = Type::getInt32PtrTy(C);
+ Type *Int64Ty = Type::getInt64Ty(C);
+ VectorType *Int8PtrVecTy = VectorType::get(Int8PtrTy, 4);
+ VectorType *Int32PtrVecTy = VectorType::get(Int32PtrTy, 4);
+ VectorType *Int64VecTy = VectorType::get(Int64Ty, 4);
+
+ // ptrtoint i8* to i64
+ EXPECT_EQ(Constant::getNullValue(Int64Ty),
+ ConstantExpr::getPointerCast(
+ Constant::getNullValue(Int8PtrTy), Int64Ty));
+
+ // bitcast i8* to i32*
+ EXPECT_EQ(Constant::getNullValue(Int32PtrTy),
+ ConstantExpr::getPointerCast(
+ Constant::getNullValue(Int8PtrTy), Int32PtrTy));
+
+ // ptrtoint <4 x i8*> to <4 x i64>
+ EXPECT_EQ(Constant::getNullValue(Int64VecTy),
+ ConstantExpr::getPointerCast(
+ Constant::getNullValue(Int8PtrVecTy), Int64VecTy));
+
+ // bitcast <4 x i8*> to <4 x i32*>
+ EXPECT_EQ(Constant::getNullValue(Int32PtrVecTy),
+ ConstantExpr::getPointerCast(
+ Constant::getNullValue(Int8PtrVecTy), Int32PtrVecTy));
+}
+
+#define CHECK(x, y) { \
+ std::string __s; \
+ raw_string_ostream __o(__s); \
+ Instruction *__I = cast<ConstantExpr>(x)->getAsInstruction(); \
+ __I->print(__o); \
+ delete __I; \
+ __o.flush(); \
+ EXPECT_EQ(std::string(" <badref> = " y), __s); \
+ }
+
+TEST(ConstantsTest, AsInstructionsTest) {
+ std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext()));
+
+ Type *Int64Ty = Type::getInt64Ty(getGlobalContext());
+ Type *Int32Ty = Type::getInt32Ty(getGlobalContext());
+ Type *Int16Ty = Type::getInt16Ty(getGlobalContext());
+ Type *Int1Ty = Type::getInt1Ty(getGlobalContext());
+ Type *FloatTy = Type::getFloatTy(getGlobalContext());
+ Type *DoubleTy = Type::getDoubleTy(getGlobalContext());
+
+ Constant *Global = M->getOrInsertGlobal("dummy",
+ PointerType::getUnqual(Int32Ty));
+ Constant *Global2 = M->getOrInsertGlobal("dummy2",
+ PointerType::getUnqual(Int32Ty));
+
+ Constant *P0 = ConstantExpr::getPtrToInt(Global, Int32Ty);
+ Constant *P1 = ConstantExpr::getUIToFP(P0, FloatTy);
+ Constant *P2 = ConstantExpr::getUIToFP(P0, DoubleTy);
+ Constant *P3 = ConstantExpr::getTrunc(P0, Int1Ty);
+ Constant *P4 = ConstantExpr::getPtrToInt(Global2, Int32Ty);
+ Constant *P5 = ConstantExpr::getUIToFP(P4, FloatTy);
+ Constant *P6 = ConstantExpr::getBitCast(P4, VectorType::get(Int16Ty, 2));
+
+ Constant *One = ConstantInt::get(Int32Ty, 1);
+ Constant *Two = ConstantInt::get(Int64Ty, 2);
+ Constant *Big = ConstantInt::get(getGlobalContext(),
+ APInt{256, uint64_t(-1), true});
+ Constant *Elt = ConstantInt::get(Int16Ty, 2015);
+ Constant *Undef16 = UndefValue::get(Int16Ty);
+ Constant *Undef64 = UndefValue::get(Int64Ty);
+ Constant *UndefV16 = UndefValue::get(P6->getType());
+
+ #define P0STR "ptrtoint (i32** @dummy to i32)"
+ #define P1STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to float)"
+ #define P2STR "uitofp (i32 ptrtoint (i32** @dummy to i32) to double)"
+ #define P3STR "ptrtoint (i32** @dummy to i1)"
+ #define P4STR "ptrtoint (i32** @dummy2 to i32)"
+ #define P5STR "uitofp (i32 ptrtoint (i32** @dummy2 to i32) to float)"
+ #define P6STR "bitcast (i32 ptrtoint (i32** @dummy2 to i32) to <2 x i16>)"
+
+ CHECK(ConstantExpr::getNeg(P0), "sub i32 0, " P0STR);
+ CHECK(ConstantExpr::getFNeg(P1), "fsub float -0.000000e+00, " P1STR);
+ CHECK(ConstantExpr::getNot(P0), "xor i32 " P0STR ", -1");
+ CHECK(ConstantExpr::getAdd(P0, P0), "add i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getAdd(P0, P0, false, true), "add nsw i32 " P0STR ", "
+ P0STR);
+ CHECK(ConstantExpr::getAdd(P0, P0, true, true), "add nuw nsw i32 " P0STR ", "
+ P0STR);
+ CHECK(ConstantExpr::getFAdd(P1, P1), "fadd float " P1STR ", " P1STR);
+ CHECK(ConstantExpr::getSub(P0, P0), "sub i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getFSub(P1, P1), "fsub float " P1STR ", " P1STR);
+ CHECK(ConstantExpr::getMul(P0, P0), "mul i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getFMul(P1, P1), "fmul float " P1STR ", " P1STR);
+ CHECK(ConstantExpr::getUDiv(P0, P0), "udiv i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getSDiv(P0, P0), "sdiv i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getFDiv(P1, P1), "fdiv float " P1STR ", " P1STR);
+ CHECK(ConstantExpr::getURem(P0, P0), "urem i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getSRem(P0, P0), "srem i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getFRem(P1, P1), "frem float " P1STR ", " P1STR);
+ CHECK(ConstantExpr::getAnd(P0, P0), "and i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getOr(P0, P0), "or i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getXor(P0, P0), "xor i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getShl(P0, P0), "shl i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getShl(P0, P0, true), "shl nuw i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getShl(P0, P0, false, true), "shl nsw i32 " P0STR ", "
+ P0STR);
+ CHECK(ConstantExpr::getLShr(P0, P0, false), "lshr i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getLShr(P0, P0, true), "lshr exact i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getAShr(P0, P0, false), "ashr i32 " P0STR ", " P0STR);
+ CHECK(ConstantExpr::getAShr(P0, P0, true), "ashr exact i32 " P0STR ", " P0STR);
+
+ CHECK(ConstantExpr::getSExt(P0, Int64Ty), "sext i32 " P0STR " to i64");
+ CHECK(ConstantExpr::getZExt(P0, Int64Ty), "zext i32 " P0STR " to i64");
+ CHECK(ConstantExpr::getFPTrunc(P2, FloatTy), "fptrunc double " P2STR
+ " to float");
+ CHECK(ConstantExpr::getFPExtend(P1, DoubleTy), "fpext float " P1STR
+ " to double");
+
+ CHECK(ConstantExpr::getExactUDiv(P0, P0), "udiv exact i32 " P0STR ", " P0STR);
+
+ CHECK(ConstantExpr::getSelect(P3, P0, P4), "select i1 " P3STR ", i32 " P0STR
+ ", i32 " P4STR);
+ CHECK(ConstantExpr::getICmp(CmpInst::ICMP_EQ, P0, P4), "icmp eq i32 " P0STR
+ ", " P4STR);
+ CHECK(ConstantExpr::getFCmp(CmpInst::FCMP_ULT, P1, P5), "fcmp ult float "
+ P1STR ", " P5STR);
+
+ std::vector<Constant*> V;
+ V.push_back(One);
+ // FIXME: getGetElementPtr() actually creates an inbounds ConstantGEP,
+ // not a normal one!
+ //CHECK(ConstantExpr::getGetElementPtr(Global, V, false),
+ // "getelementptr i32*, i32** @dummy, i32 1");
+ CHECK(ConstantExpr::getInBoundsGetElementPtr(PointerType::getUnqual(Int32Ty),
+ Global, V),
+ "getelementptr inbounds i32*, i32** @dummy, i32 1");
+
+ CHECK(ConstantExpr::getExtractElement(P6, One), "extractelement <2 x i16> "
+ P6STR ", i32 1");
+
+ EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Two));
+ EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Big));
+ EXPECT_EQ(Undef16, ConstantExpr::getExtractElement(P6, Undef64));
+
+ EXPECT_EQ(Elt, ConstantExpr::getExtractElement(
+ ConstantExpr::getInsertElement(P6, Elt, One), One));
+ EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Two));
+ EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Big));
+ EXPECT_EQ(UndefV16, ConstantExpr::getInsertElement(P6, Elt, Undef64));
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(ConstantsTest, ReplaceWithConstantTest) {
+ std::unique_ptr<Module> M(new Module("MyModule", getGlobalContext()));
+
+ Type *Int32Ty = Type::getInt32Ty(getGlobalContext());
+ Constant *One = ConstantInt::get(Int32Ty, 1);
+
+ Constant *Global =
+ M->getOrInsertGlobal("dummy", PointerType::getUnqual(Int32Ty));
+ Constant *GEP = ConstantExpr::getGetElementPtr(
+ PointerType::getUnqual(Int32Ty), Global, One);
+ EXPECT_DEATH(Global->replaceAllUsesWith(GEP),
+ "this->replaceAllUsesWith\\(expr\\(this\\)\\) is NOT valid!");
+}
+
+#endif
+#endif
+
+#undef CHECK
+
+TEST(ConstantsTest, ConstantArrayReplaceWithConstant) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ Type *IntTy = Type::getInt8Ty(Context);
+ ArrayType *ArrayTy = ArrayType::get(IntTy, 2);
+ Constant *A01Vals[2] = {ConstantInt::get(IntTy, 0),
+ ConstantInt::get(IntTy, 1)};
+ Constant *A01 = ConstantArray::get(ArrayTy, A01Vals);
+
+ Constant *Global = new GlobalVariable(*M, IntTy, false,
+ GlobalValue::ExternalLinkage, nullptr);
+ Constant *GlobalInt = ConstantExpr::getPtrToInt(Global, IntTy);
+ Constant *A0GVals[2] = {ConstantInt::get(IntTy, 0), GlobalInt};
+ Constant *A0G = ConstantArray::get(ArrayTy, A0GVals);
+ ASSERT_NE(A01, A0G);
+
+ GlobalVariable *RefArray =
+ new GlobalVariable(*M, ArrayTy, false, GlobalValue::ExternalLinkage, A0G);
+ ASSERT_EQ(A0G, RefArray->getInitializer());
+
+ GlobalInt->replaceAllUsesWith(ConstantInt::get(IntTy, 1));
+ ASSERT_EQ(A01, RefArray->getInitializer());
+}
+
+TEST(ConstantsTest, ConstantExprReplaceWithConstant) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ Type *IntTy = Type::getInt8Ty(Context);
+ Constant *G1 = new GlobalVariable(*M, IntTy, false,
+ GlobalValue::ExternalLinkage, nullptr);
+ Constant *G2 = new GlobalVariable(*M, IntTy, false,
+ GlobalValue::ExternalLinkage, nullptr);
+ ASSERT_NE(G1, G2);
+
+ Constant *Int1 = ConstantExpr::getPtrToInt(G1, IntTy);
+ Constant *Int2 = ConstantExpr::getPtrToInt(G2, IntTy);
+ ASSERT_NE(Int1, Int2);
+
+ GlobalVariable *Ref =
+ new GlobalVariable(*M, IntTy, false, GlobalValue::ExternalLinkage, Int1);
+ ASSERT_EQ(Int1, Ref->getInitializer());
+
+ G1->replaceAllUsesWith(G2);
+ ASSERT_EQ(Int2, Ref->getInitializer());
+}
+
+TEST(ConstantsTest, GEPReplaceWithConstant) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ Type *IntTy = Type::getInt32Ty(Context);
+ Type *PtrTy = PointerType::get(IntTy, 0);
+ auto *C1 = ConstantInt::get(IntTy, 1);
+ auto *Placeholder = new GlobalVariable(
+ *M, IntTy, false, GlobalValue::ExternalWeakLinkage, nullptr);
+ auto *GEP = ConstantExpr::getGetElementPtr(IntTy, Placeholder, C1);
+ ASSERT_EQ(GEP->getOperand(0), Placeholder);
+
+ auto *Ref =
+ new GlobalVariable(*M, PtrTy, false, GlobalValue::ExternalLinkage, GEP);
+ ASSERT_EQ(GEP, Ref->getInitializer());
+
+ auto *Global = new GlobalVariable(*M, PtrTy, false,
+ GlobalValue::ExternalLinkage, nullptr);
+ auto *Alias = GlobalAlias::create(IntTy, 0, GlobalValue::ExternalLinkage,
+ "alias", Global, M.get());
+ Placeholder->replaceAllUsesWith(Alias);
+ ASSERT_EQ(GEP, Ref->getInitializer());
+ ASSERT_EQ(GEP->getOperand(0), Alias);
+}
+
+TEST(ConstantsTest, AliasCAPI) {
+ LLVMContext Context;
+ SMDiagnostic Error;
+ std::unique_ptr<Module> M =
+ parseAssemblyString("@g = global i32 42", Error, Context);
+ GlobalVariable *G = M->getGlobalVariable("g");
+ Type *I16Ty = Type::getInt16Ty(Context);
+ Type *I16PTy = PointerType::get(I16Ty, 0);
+ Constant *Aliasee = ConstantExpr::getBitCast(G, I16PTy);
+ LLVMValueRef AliasRef =
+ LLVMAddAlias(wrap(M.get()), wrap(I16PTy), wrap(Aliasee), "a");
+ ASSERT_EQ(unwrap<GlobalAlias>(AliasRef)->getAliasee(), Aliasee);
+}
+
+static std::string getNameOfType(Type *T) {
+ std::string S;
+ raw_string_ostream RSOS(S);
+ T->print(RSOS);
+ return S;
+}
+
+TEST(ConstantsTest, BuildConstantDataArrays) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ for (Type *T : {Type::getInt8Ty(Context), Type::getInt16Ty(Context),
+ Type::getInt32Ty(Context), Type::getInt64Ty(Context)}) {
+ ArrayType *ArrayTy = ArrayType::get(T, 2);
+ Constant *Vals[] = {ConstantInt::get(T, 0), ConstantInt::get(T, 1)};
+ Constant *CDV = ConstantArray::get(ArrayTy, Vals);
+ ASSERT_TRUE(dyn_cast<ConstantDataArray>(CDV) != nullptr)
+ << " T = " << getNameOfType(T);
+ }
+
+ for (Type *T : {Type::getHalfTy(Context), Type::getFloatTy(Context),
+ Type::getDoubleTy(Context)}) {
+ ArrayType *ArrayTy = ArrayType::get(T, 2);
+ Constant *Vals[] = {ConstantFP::get(T, 0), ConstantFP::get(T, 1)};
+ Constant *CDV = ConstantArray::get(ArrayTy, Vals);
+ ASSERT_TRUE(dyn_cast<ConstantDataArray>(CDV) != nullptr)
+ << " T = " << getNameOfType(T);
+ }
+}
+
+TEST(ConstantsTest, BuildConstantDataVectors) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ for (Type *T : {Type::getInt8Ty(Context), Type::getInt16Ty(Context),
+ Type::getInt32Ty(Context), Type::getInt64Ty(Context)}) {
+ Constant *Vals[] = {ConstantInt::get(T, 0), ConstantInt::get(T, 1)};
+ Constant *CDV = ConstantVector::get(Vals);
+ ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
+ << " T = " << getNameOfType(T);
+ }
+
+ for (Type *T : {Type::getHalfTy(Context), Type::getFloatTy(Context),
+ Type::getDoubleTy(Context)}) {
+ Constant *Vals[] = {ConstantFP::get(T, 0), ConstantFP::get(T, 1)};
+ Constant *CDV = ConstantVector::get(Vals);
+ ASSERT_TRUE(dyn_cast<ConstantDataVector>(CDV) != nullptr)
+ << " T = " << getNameOfType(T);
+ }
+}
+
+TEST(ConstantsTest, BitcastToGEP) {
+ LLVMContext Context;
+ std::unique_ptr<Module> M(new Module("MyModule", Context));
+
+ auto *i32 = Type::getInt32Ty(Context);
+ auto *U = StructType::create(Context, "Unsized");
+ Type *EltTys[] = {i32, U};
+ auto *S = StructType::create(EltTys);
+
+ auto *G = new GlobalVariable(*M, S, false,
+ GlobalValue::ExternalLinkage, nullptr);
+ auto *PtrTy = PointerType::get(i32, 0);
+ auto *C = ConstantExpr::getBitCast(G, PtrTy);
+ ASSERT_EQ(dyn_cast<ConstantExpr>(C)->getOpcode(),
+ Instruction::BitCast);
+}
+
+} // end anonymous namespace
+} // end namespace llvm
diff --git a/gnu/llvm/unittests/IR/DebugInfoTest.cpp b/gnu/llvm/unittests/IR/DebugInfoTest.cpp
new file mode 100644
index 00000000000..f633782b379
--- /dev/null
+++ b/gnu/llvm/unittests/IR/DebugInfoTest.cpp
@@ -0,0 +1,81 @@
+//===- llvm/unittest/IR/DebugInfo.cpp - DebugInfo tests -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(DINodeTest, getFlag) {
+ // Some valid flags.
+ EXPECT_EQ(DINode::FlagPublic, DINode::getFlag("DIFlagPublic"));
+ EXPECT_EQ(DINode::FlagProtected, DINode::getFlag("DIFlagProtected"));
+ EXPECT_EQ(DINode::FlagPrivate, DINode::getFlag("DIFlagPrivate"));
+ EXPECT_EQ(DINode::FlagVector, DINode::getFlag("DIFlagVector"));
+ EXPECT_EQ(DINode::FlagRValueReference,
+ DINode::getFlag("DIFlagRValueReference"));
+
+ // FlagAccessibility shouldn't work.
+ EXPECT_EQ(0u, DINode::getFlag("DIFlagAccessibility"));
+
+ // Some other invalid strings.
+ EXPECT_EQ(0u, DINode::getFlag("FlagVector"));
+ EXPECT_EQ(0u, DINode::getFlag("Vector"));
+ EXPECT_EQ(0u, DINode::getFlag("other things"));
+ EXPECT_EQ(0u, DINode::getFlag("DIFlagOther"));
+}
+
+TEST(DINodeTest, getFlagString) {
+ // Some valid flags.
+ EXPECT_EQ(StringRef("DIFlagPublic"),
+ DINode::getFlagString(DINode::FlagPublic));
+ EXPECT_EQ(StringRef("DIFlagProtected"),
+ DINode::getFlagString(DINode::FlagProtected));
+ EXPECT_EQ(StringRef("DIFlagPrivate"),
+ DINode::getFlagString(DINode::FlagPrivate));
+ EXPECT_EQ(StringRef("DIFlagVector"),
+ DINode::getFlagString(DINode::FlagVector));
+ EXPECT_EQ(StringRef("DIFlagRValueReference"),
+ DINode::getFlagString(DINode::FlagRValueReference));
+
+ // FlagAccessibility actually equals FlagPublic.
+ EXPECT_EQ(StringRef("DIFlagPublic"),
+ DINode::getFlagString(DINode::FlagAccessibility));
+
+ // Some other invalid flags.
+ EXPECT_EQ(StringRef(),
+ DINode::getFlagString(DINode::FlagPublic | DINode::FlagVector));
+ EXPECT_EQ(StringRef(), DINode::getFlagString(DINode::FlagFwdDecl |
+ DINode::FlagArtificial));
+ EXPECT_EQ(StringRef(), DINode::getFlagString(0xffff));
+}
+
+TEST(DINodeTest, splitFlags) {
+// Some valid flags.
+#define CHECK_SPLIT(FLAGS, VECTOR, REMAINDER) \
+ { \
+ SmallVector<unsigned, 8> V; \
+ EXPECT_EQ(REMAINDER, DINode::splitFlags(FLAGS, V)); \
+ EXPECT_TRUE(makeArrayRef(V).equals(VECTOR)); \
+ }
+ CHECK_SPLIT(DINode::FlagPublic, {DINode::FlagPublic}, 0u);
+ CHECK_SPLIT(DINode::FlagProtected, {DINode::FlagProtected}, 0u);
+ CHECK_SPLIT(DINode::FlagPrivate, {DINode::FlagPrivate}, 0u);
+ CHECK_SPLIT(DINode::FlagVector, {DINode::FlagVector}, 0u);
+ CHECK_SPLIT(DINode::FlagRValueReference, {DINode::FlagRValueReference}, 0u);
+ unsigned Flags[] = {DINode::FlagFwdDecl, DINode::FlagVector};
+ CHECK_SPLIT(DINode::FlagFwdDecl | DINode::FlagVector, Flags, 0u);
+ CHECK_SPLIT(0x100000u, {}, 0x100000u);
+ CHECK_SPLIT(0x100000u | DINode::FlagVector, {DINode::FlagVector}, 0x100000u);
+#undef CHECK_SPLIT
+}
+
+} // end namespace
diff --git a/gnu/llvm/unittests/IR/DominatorTreeTest.cpp b/gnu/llvm/unittests/IR/DominatorTreeTest.cpp
new file mode 100644
index 00000000000..3aef4d64cbc
--- /dev/null
+++ b/gnu/llvm/unittests/IR/DominatorTreeTest.cpp
@@ -0,0 +1,259 @@
+//===- llvm/unittests/IR/DominatorTreeTest.cpp - Constants 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/IR/Dominators.h"
+#include "llvm/Analysis/PostDominators.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+ void initializeDPassPass(PassRegistry&);
+
+ namespace {
+ struct DPass : public FunctionPass {
+ static char ID;
+ bool runOnFunction(Function &F) override {
+ DominatorTree *DT =
+ &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
+ PostDominatorTree *PDT = &getAnalysis<PostDominatorTree>();
+ Function::iterator FI = F.begin();
+
+ BasicBlock *BB0 = &*FI++;
+ BasicBlock::iterator BBI = BB0->begin();
+ Instruction *Y1 = &*BBI++;
+ Instruction *Y2 = &*BBI++;
+ Instruction *Y3 = &*BBI++;
+
+ BasicBlock *BB1 = &*FI++;
+ BBI = BB1->begin();
+ Instruction *Y4 = &*BBI++;
+
+ BasicBlock *BB2 = &*FI++;
+ BBI = BB2->begin();
+ Instruction *Y5 = &*BBI++;
+
+ BasicBlock *BB3 = &*FI++;
+ BBI = BB3->begin();
+ Instruction *Y6 = &*BBI++;
+ Instruction *Y7 = &*BBI++;
+
+ BasicBlock *BB4 = &*FI++;
+ BBI = BB4->begin();
+ Instruction *Y8 = &*BBI++;
+ Instruction *Y9 = &*BBI++;
+
+ // Reachability
+ EXPECT_TRUE(DT->isReachableFromEntry(BB0));
+ EXPECT_TRUE(DT->isReachableFromEntry(BB1));
+ EXPECT_TRUE(DT->isReachableFromEntry(BB2));
+ EXPECT_FALSE(DT->isReachableFromEntry(BB3));
+ EXPECT_TRUE(DT->isReachableFromEntry(BB4));
+
+ // BB dominance
+ EXPECT_TRUE(DT->dominates(BB0, BB0));
+ EXPECT_TRUE(DT->dominates(BB0, BB1));
+ EXPECT_TRUE(DT->dominates(BB0, BB2));
+ EXPECT_TRUE(DT->dominates(BB0, BB3));
+ EXPECT_TRUE(DT->dominates(BB0, BB4));
+
+ EXPECT_FALSE(DT->dominates(BB1, BB0));
+ EXPECT_TRUE(DT->dominates(BB1, BB1));
+ EXPECT_FALSE(DT->dominates(BB1, BB2));
+ EXPECT_TRUE(DT->dominates(BB1, BB3));
+ EXPECT_FALSE(DT->dominates(BB1, BB4));
+
+ EXPECT_FALSE(DT->dominates(BB2, BB0));
+ EXPECT_FALSE(DT->dominates(BB2, BB1));
+ EXPECT_TRUE(DT->dominates(BB2, BB2));
+ EXPECT_TRUE(DT->dominates(BB2, BB3));
+ EXPECT_FALSE(DT->dominates(BB2, BB4));
+
+ EXPECT_FALSE(DT->dominates(BB3, BB0));
+ EXPECT_FALSE(DT->dominates(BB3, BB1));
+ EXPECT_FALSE(DT->dominates(BB3, BB2));
+ EXPECT_TRUE(DT->dominates(BB3, BB3));
+ EXPECT_FALSE(DT->dominates(BB3, BB4));
+
+ // BB proper dominance
+ EXPECT_FALSE(DT->properlyDominates(BB0, BB0));
+ EXPECT_TRUE(DT->properlyDominates(BB0, BB1));
+ EXPECT_TRUE(DT->properlyDominates(BB0, BB2));
+ EXPECT_TRUE(DT->properlyDominates(BB0, BB3));
+
+ EXPECT_FALSE(DT->properlyDominates(BB1, BB0));
+ EXPECT_FALSE(DT->properlyDominates(BB1, BB1));
+ EXPECT_FALSE(DT->properlyDominates(BB1, BB2));
+ EXPECT_TRUE(DT->properlyDominates(BB1, BB3));
+
+ EXPECT_FALSE(DT->properlyDominates(BB2, BB0));
+ EXPECT_FALSE(DT->properlyDominates(BB2, BB1));
+ EXPECT_FALSE(DT->properlyDominates(BB2, BB2));
+ EXPECT_TRUE(DT->properlyDominates(BB2, BB3));
+
+ EXPECT_FALSE(DT->properlyDominates(BB3, BB0));
+ EXPECT_FALSE(DT->properlyDominates(BB3, BB1));
+ EXPECT_FALSE(DT->properlyDominates(BB3, BB2));
+ EXPECT_FALSE(DT->properlyDominates(BB3, BB3));
+
+ // Instruction dominance in the same reachable BB
+ EXPECT_FALSE(DT->dominates(Y1, Y1));
+ EXPECT_TRUE(DT->dominates(Y1, Y2));
+ EXPECT_FALSE(DT->dominates(Y2, Y1));
+ EXPECT_FALSE(DT->dominates(Y2, Y2));
+
+ // Instruction dominance in the same unreachable BB
+ EXPECT_TRUE(DT->dominates(Y6, Y6));
+ EXPECT_TRUE(DT->dominates(Y6, Y7));
+ EXPECT_TRUE(DT->dominates(Y7, Y6));
+ EXPECT_TRUE(DT->dominates(Y7, Y7));
+
+ // Invoke
+ EXPECT_TRUE(DT->dominates(Y3, Y4));
+ EXPECT_FALSE(DT->dominates(Y3, Y5));
+
+ // Phi
+ EXPECT_TRUE(DT->dominates(Y2, Y9));
+ EXPECT_FALSE(DT->dominates(Y3, Y9));
+ EXPECT_FALSE(DT->dominates(Y8, Y9));
+
+ // Anything dominates unreachable
+ EXPECT_TRUE(DT->dominates(Y1, Y6));
+ EXPECT_TRUE(DT->dominates(Y3, Y6));
+
+ // Unreachable doesn't dominate reachable
+ EXPECT_FALSE(DT->dominates(Y6, Y1));
+
+ // Instruction, BB dominance
+ EXPECT_FALSE(DT->dominates(Y1, BB0));
+ EXPECT_TRUE(DT->dominates(Y1, BB1));
+ EXPECT_TRUE(DT->dominates(Y1, BB2));
+ EXPECT_TRUE(DT->dominates(Y1, BB3));
+ EXPECT_TRUE(DT->dominates(Y1, BB4));
+
+ EXPECT_FALSE(DT->dominates(Y3, BB0));
+ EXPECT_TRUE(DT->dominates(Y3, BB1));
+ EXPECT_FALSE(DT->dominates(Y3, BB2));
+ EXPECT_TRUE(DT->dominates(Y3, BB3));
+ EXPECT_FALSE(DT->dominates(Y3, BB4));
+
+ EXPECT_TRUE(DT->dominates(Y6, BB3));
+
+ // Post dominance.
+ EXPECT_TRUE(PDT->dominates(BB0, BB0));
+ EXPECT_FALSE(PDT->dominates(BB1, BB0));
+ EXPECT_FALSE(PDT->dominates(BB2, BB0));
+ EXPECT_FALSE(PDT->dominates(BB3, BB0));
+ EXPECT_TRUE(PDT->dominates(BB4, BB1));
+
+ // Dominance descendants.
+ SmallVector<BasicBlock *, 8> DominatedBBs, PostDominatedBBs;
+
+ DT->getDescendants(BB0, DominatedBBs);
+ PDT->getDescendants(BB0, PostDominatedBBs);
+ EXPECT_EQ(DominatedBBs.size(), 4UL);
+ EXPECT_EQ(PostDominatedBBs.size(), 1UL);
+
+ // BB3 is unreachable. It should have no dominators nor postdominators.
+ DominatedBBs.clear();
+ PostDominatedBBs.clear();
+ DT->getDescendants(BB3, DominatedBBs);
+ DT->getDescendants(BB3, PostDominatedBBs);
+ EXPECT_EQ(DominatedBBs.size(), 0UL);
+ EXPECT_EQ(PostDominatedBBs.size(), 0UL);
+
+ // Check DFS Numbers before
+ EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
+ EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 7UL);
+ EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
+ EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 2UL);
+ EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 5UL);
+ EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 6UL);
+ EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 3UL);
+ EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 4UL);
+
+ // Reattach block 3 to block 1 and recalculate
+ BB1->getTerminator()->eraseFromParent();
+ BranchInst::Create(BB4, BB3, ConstantInt::getTrue(F.getContext()), BB1);
+ DT->recalculate(F);
+
+ // Check DFS Numbers after
+ EXPECT_EQ(DT->getNode(BB0)->getDFSNumIn(), 0UL);
+ EXPECT_EQ(DT->getNode(BB0)->getDFSNumOut(), 9UL);
+ EXPECT_EQ(DT->getNode(BB1)->getDFSNumIn(), 1UL);
+ EXPECT_EQ(DT->getNode(BB1)->getDFSNumOut(), 4UL);
+ EXPECT_EQ(DT->getNode(BB2)->getDFSNumIn(), 7UL);
+ EXPECT_EQ(DT->getNode(BB2)->getDFSNumOut(), 8UL);
+ EXPECT_EQ(DT->getNode(BB3)->getDFSNumIn(), 2UL);
+ EXPECT_EQ(DT->getNode(BB3)->getDFSNumOut(), 3UL);
+ EXPECT_EQ(DT->getNode(BB4)->getDFSNumIn(), 5UL);
+ EXPECT_EQ(DT->getNode(BB4)->getDFSNumOut(), 6UL);
+
+ return false;
+ }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<DominatorTreeWrapperPass>();
+ AU.addRequired<PostDominatorTree>();
+ }
+ DPass() : FunctionPass(ID) {
+ initializeDPassPass(*PassRegistry::getPassRegistry());
+ }
+ };
+ char DPass::ID = 0;
+
+ std::unique_ptr<Module> makeLLVMModule(DPass *P) {
+ const char *ModuleStrig =
+ "declare i32 @g()\n" \
+ "define void @f(i32 %x) personality i32 ()* @g {\n" \
+ "bb0:\n" \
+ " %y1 = add i32 %x, 1\n" \
+ " %y2 = add i32 %x, 1\n" \
+ " %y3 = invoke i32 @g() to label %bb1 unwind label %bb2\n" \
+ "bb1:\n" \
+ " %y4 = add i32 %x, 1\n" \
+ " br label %bb4\n" \
+ "bb2:\n" \
+ " %y5 = landingpad i32\n" \
+ " cleanup\n" \
+ " br label %bb4\n" \
+ "bb3:\n" \
+ " %y6 = add i32 %x, 1\n" \
+ " %y7 = add i32 %x, 1\n" \
+ " ret void\n" \
+ "bb4:\n" \
+ " %y8 = phi i32 [0, %bb2], [%y4, %bb1]\n"
+ " %y9 = phi i32 [0, %bb2], [%y4, %bb1]\n"
+ " ret void\n" \
+ "}\n";
+ LLVMContext &C = getGlobalContext();
+ SMDiagnostic Err;
+ return parseAssemblyString(ModuleStrig, Err, C);
+ }
+
+ TEST(DominatorTree, Unreachable) {
+ DPass *P = new DPass();
+ std::unique_ptr<Module> M = makeLLVMModule(P);
+ legacy::PassManager Passes;
+ Passes.add(P);
+ Passes.run(*M);
+ }
+ }
+}
+
+INITIALIZE_PASS_BEGIN(DPass, "dpass", "dpass", false, false)
+INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
+INITIALIZE_PASS_DEPENDENCY(PostDominatorTree)
+INITIALIZE_PASS_END(DPass, "dpass", "dpass", false, false)
diff --git a/gnu/llvm/unittests/IR/IRBuilderTest.cpp b/gnu/llvm/unittests/IR/IRBuilderTest.cpp
new file mode 100644
index 00000000000..bd0eae0399a
--- /dev/null
+++ b/gnu/llvm/unittests/IR/IRBuilderTest.cpp
@@ -0,0 +1,421 @@
+//===- llvm/unittest/IR/IRBuilderTest.cpp - IRBuilder tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/NoFolder.h"
+#include "llvm/IR/Verifier.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class IRBuilderTest : public testing::Test {
+protected:
+ void SetUp() override {
+ M.reset(new Module("MyModule", Ctx));
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
+ /*isVarArg=*/false);
+ F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
+ BB = BasicBlock::Create(Ctx, "", F);
+ GV = new GlobalVariable(*M, Type::getFloatTy(Ctx), true,
+ GlobalValue::ExternalLinkage, nullptr);
+ }
+
+ void TearDown() override {
+ BB = nullptr;
+ M.reset();
+ }
+
+ LLVMContext Ctx;
+ std::unique_ptr<Module> M;
+ Function *F;
+ BasicBlock *BB;
+ GlobalVariable *GV;
+};
+
+TEST_F(IRBuilderTest, Lifetime) {
+ IRBuilder<> Builder(BB);
+ AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty());
+ AllocaInst *Var2 = Builder.CreateAlloca(Builder.getInt32Ty());
+ AllocaInst *Var3 = Builder.CreateAlloca(Builder.getInt8Ty(),
+ Builder.getInt32(123));
+
+ CallInst *Start1 = Builder.CreateLifetimeStart(Var1);
+ CallInst *Start2 = Builder.CreateLifetimeStart(Var2);
+ CallInst *Start3 = Builder.CreateLifetimeStart(Var3, Builder.getInt64(100));
+
+ EXPECT_EQ(Start1->getArgOperand(0), Builder.getInt64(-1));
+ EXPECT_EQ(Start2->getArgOperand(0), Builder.getInt64(-1));
+ EXPECT_EQ(Start3->getArgOperand(0), Builder.getInt64(100));
+
+ EXPECT_EQ(Start1->getArgOperand(1), Var1);
+ EXPECT_NE(Start2->getArgOperand(1), Var2);
+ EXPECT_EQ(Start3->getArgOperand(1), Var3);
+
+ Value *End1 = Builder.CreateLifetimeEnd(Var1);
+ Builder.CreateLifetimeEnd(Var2);
+ Builder.CreateLifetimeEnd(Var3);
+
+ IntrinsicInst *II_Start1 = dyn_cast<IntrinsicInst>(Start1);
+ IntrinsicInst *II_End1 = dyn_cast<IntrinsicInst>(End1);
+ ASSERT_TRUE(II_Start1 != nullptr);
+ EXPECT_EQ(II_Start1->getIntrinsicID(), Intrinsic::lifetime_start);
+ ASSERT_TRUE(II_End1 != nullptr);
+ EXPECT_EQ(II_End1->getIntrinsicID(), Intrinsic::lifetime_end);
+}
+
+TEST_F(IRBuilderTest, CreateCondBr) {
+ IRBuilder<> Builder(BB);
+ BasicBlock *TBB = BasicBlock::Create(Ctx, "", F);
+ BasicBlock *FBB = BasicBlock::Create(Ctx, "", F);
+
+ BranchInst *BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB);
+ TerminatorInst *TI = BB->getTerminator();
+ EXPECT_EQ(BI, TI);
+ EXPECT_EQ(2u, TI->getNumSuccessors());
+ EXPECT_EQ(TBB, TI->getSuccessor(0));
+ EXPECT_EQ(FBB, TI->getSuccessor(1));
+
+ BI->eraseFromParent();
+ MDNode *Weights = MDBuilder(Ctx).createBranchWeights(42, 13);
+ BI = Builder.CreateCondBr(Builder.getTrue(), TBB, FBB, Weights);
+ TI = BB->getTerminator();
+ EXPECT_EQ(BI, TI);
+ EXPECT_EQ(2u, TI->getNumSuccessors());
+ EXPECT_EQ(TBB, TI->getSuccessor(0));
+ EXPECT_EQ(FBB, TI->getSuccessor(1));
+ EXPECT_EQ(Weights, TI->getMetadata(LLVMContext::MD_prof));
+}
+
+TEST_F(IRBuilderTest, LandingPadName) {
+ IRBuilder<> Builder(BB);
+ LandingPadInst *LP = Builder.CreateLandingPad(Builder.getInt32Ty(), 0, "LP");
+ EXPECT_EQ(LP->getName(), "LP");
+}
+
+TEST_F(IRBuilderTest, DataLayout) {
+ std::unique_ptr<Module> M(new Module("test", Ctx));
+ M->setDataLayout("e-n32");
+ EXPECT_TRUE(M->getDataLayout().isLegalInteger(32));
+ M->setDataLayout("e");
+ EXPECT_FALSE(M->getDataLayout().isLegalInteger(32));
+}
+
+TEST_F(IRBuilderTest, GetIntTy) {
+ IRBuilder<> Builder(BB);
+ IntegerType *Ty1 = Builder.getInt1Ty();
+ EXPECT_EQ(Ty1, IntegerType::get(Ctx, 1));
+
+ DataLayout* DL = new DataLayout(M.get());
+ IntegerType *IntPtrTy = Builder.getIntPtrTy(*DL);
+ unsigned IntPtrBitSize = DL->getPointerSizeInBits(0);
+ EXPECT_EQ(IntPtrTy, IntegerType::get(Ctx, IntPtrBitSize));
+ delete DL;
+}
+
+TEST_F(IRBuilderTest, FastMathFlags) {
+ IRBuilder<> Builder(BB);
+ Value *F, *FC;
+ Instruction *FDiv, *FAdd, *FCmp, *FCall;
+
+ F = Builder.CreateLoad(GV);
+ F = Builder.CreateFAdd(F, F);
+
+ EXPECT_FALSE(Builder.getFastMathFlags().any());
+ ASSERT_TRUE(isa<Instruction>(F));
+ FAdd = cast<Instruction>(F);
+ EXPECT_FALSE(FAdd->hasNoNaNs());
+
+ FastMathFlags FMF;
+ Builder.setFastMathFlags(FMF);
+
+ F = Builder.CreateFAdd(F, F);
+ EXPECT_FALSE(Builder.getFastMathFlags().any());
+
+ FMF.setUnsafeAlgebra();
+ Builder.setFastMathFlags(FMF);
+
+ F = Builder.CreateFAdd(F, F);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ ASSERT_TRUE(isa<Instruction>(F));
+ FAdd = cast<Instruction>(F);
+ EXPECT_TRUE(FAdd->hasNoNaNs());
+
+ // Now, try it with CreateBinOp
+ F = Builder.CreateBinOp(Instruction::FAdd, F, F);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ ASSERT_TRUE(isa<Instruction>(F));
+ FAdd = cast<Instruction>(F);
+ EXPECT_TRUE(FAdd->hasNoNaNs());
+
+ F = Builder.CreateFDiv(F, F);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().UnsafeAlgebra);
+ ASSERT_TRUE(isa<Instruction>(F));
+ FDiv = cast<Instruction>(F);
+ EXPECT_TRUE(FDiv->hasAllowReciprocal());
+
+ Builder.clearFastMathFlags();
+
+ F = Builder.CreateFDiv(F, F);
+ ASSERT_TRUE(isa<Instruction>(F));
+ FDiv = cast<Instruction>(F);
+ EXPECT_FALSE(FDiv->hasAllowReciprocal());
+
+ FMF.clear();
+ FMF.setAllowReciprocal();
+ Builder.setFastMathFlags(FMF);
+
+ F = Builder.CreateFDiv(F, F);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().AllowReciprocal);
+ ASSERT_TRUE(isa<Instruction>(F));
+ FDiv = cast<Instruction>(F);
+ EXPECT_TRUE(FDiv->hasAllowReciprocal());
+
+ Builder.clearFastMathFlags();
+
+ FC = Builder.CreateFCmpOEQ(F, F);
+ ASSERT_TRUE(isa<Instruction>(FC));
+ FCmp = cast<Instruction>(FC);
+ EXPECT_FALSE(FCmp->hasAllowReciprocal());
+
+ FMF.clear();
+ FMF.setAllowReciprocal();
+ Builder.setFastMathFlags(FMF);
+
+ FC = Builder.CreateFCmpOEQ(F, F);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().AllowReciprocal);
+ ASSERT_TRUE(isa<Instruction>(FC));
+ FCmp = cast<Instruction>(FC);
+ EXPECT_TRUE(FCmp->hasAllowReciprocal());
+
+ Builder.clearFastMathFlags();
+
+ // Test a call with FMF.
+ auto CalleeTy = FunctionType::get(Type::getFloatTy(Ctx),
+ /*isVarArg=*/false);
+ auto Callee =
+ Function::Create(CalleeTy, Function::ExternalLinkage, "", M.get());
+
+ FCall = Builder.CreateCall(Callee, None);
+ EXPECT_FALSE(FCall->hasNoNaNs());
+
+ Value *V =
+ Function::Create(CalleeTy, Function::ExternalLinkage, "", M.get());
+ FCall = Builder.CreateCall(V, None);
+ EXPECT_FALSE(FCall->hasNoNaNs());
+
+ FMF.clear();
+ FMF.setNoNaNs();
+ Builder.setFastMathFlags(FMF);
+
+ FCall = Builder.CreateCall(Callee, None);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().NoNaNs);
+ EXPECT_TRUE(FCall->hasNoNaNs());
+
+ FCall = Builder.CreateCall(V, None);
+ EXPECT_TRUE(Builder.getFastMathFlags().any());
+ EXPECT_TRUE(Builder.getFastMathFlags().NoNaNs);
+ EXPECT_TRUE(FCall->hasNoNaNs());
+
+ Builder.clearFastMathFlags();
+
+ // To test a copy, make sure that a '0' and a '1' change state.
+ F = Builder.CreateFDiv(F, F);
+ ASSERT_TRUE(isa<Instruction>(F));
+ FDiv = cast<Instruction>(F);
+ EXPECT_FALSE(FDiv->getFastMathFlags().any());
+ FDiv->setHasAllowReciprocal(true);
+ FAdd->setHasAllowReciprocal(false);
+ FDiv->copyFastMathFlags(FAdd);
+ EXPECT_TRUE(FDiv->hasNoNaNs());
+ EXPECT_FALSE(FDiv->hasAllowReciprocal());
+
+}
+
+TEST_F(IRBuilderTest, WrapFlags) {
+ IRBuilder<true, NoFolder> Builder(BB);
+
+ // Test instructions.
+ GlobalVariable *G = new GlobalVariable(*M, Builder.getInt32Ty(), true,
+ GlobalValue::ExternalLinkage, nullptr);
+ Value *V = Builder.CreateLoad(G);
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNSWAdd(V, V))->hasNoSignedWrap());
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNSWMul(V, V))->hasNoSignedWrap());
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNSWSub(V, V))->hasNoSignedWrap());
+ EXPECT_TRUE(cast<BinaryOperator>(
+ Builder.CreateShl(V, V, "", /* NUW */ false, /* NSW */ true))
+ ->hasNoSignedWrap());
+
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNUWAdd(V, V))->hasNoUnsignedWrap());
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNUWMul(V, V))->hasNoUnsignedWrap());
+ EXPECT_TRUE(
+ cast<BinaryOperator>(Builder.CreateNUWSub(V, V))->hasNoUnsignedWrap());
+ EXPECT_TRUE(cast<BinaryOperator>(
+ Builder.CreateShl(V, V, "", /* NUW */ true, /* NSW */ false))
+ ->hasNoUnsignedWrap());
+
+ // Test operators created with constants.
+ Constant *C = Builder.getInt32(42);
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWAdd(C, C))
+ ->hasNoSignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWSub(C, C))
+ ->hasNoSignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNSWMul(C, C))
+ ->hasNoSignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(
+ Builder.CreateShl(C, C, "", /* NUW */ false, /* NSW */ true))
+ ->hasNoSignedWrap());
+
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWAdd(C, C))
+ ->hasNoUnsignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWSub(C, C))
+ ->hasNoUnsignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(Builder.CreateNUWMul(C, C))
+ ->hasNoUnsignedWrap());
+ EXPECT_TRUE(cast<OverflowingBinaryOperator>(
+ Builder.CreateShl(C, C, "", /* NUW */ true, /* NSW */ false))
+ ->hasNoUnsignedWrap());
+}
+
+TEST_F(IRBuilderTest, RAIIHelpersTest) {
+ IRBuilder<> Builder(BB);
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ MDBuilder MDB(M->getContext());
+
+ MDNode *FPMathA = MDB.createFPMath(0.01f);
+ MDNode *FPMathB = MDB.createFPMath(0.1f);
+
+ Builder.setDefaultFPMathTag(FPMathA);
+
+ {
+ IRBuilder<>::FastMathFlagGuard Guard(Builder);
+ FastMathFlags FMF;
+ FMF.setAllowReciprocal();
+ Builder.setFastMathFlags(FMF);
+ Builder.setDefaultFPMathTag(FPMathB);
+ EXPECT_TRUE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathB, Builder.getDefaultFPMathTag());
+ }
+
+ EXPECT_FALSE(Builder.getFastMathFlags().allowReciprocal());
+ EXPECT_EQ(FPMathA, Builder.getDefaultFPMathTag());
+
+ Value *F = Builder.CreateLoad(GV);
+
+ {
+ IRBuilder<>::InsertPointGuard Guard(Builder);
+ Builder.SetInsertPoint(cast<Instruction>(F));
+ EXPECT_EQ(F, &*Builder.GetInsertPoint());
+ }
+
+ EXPECT_EQ(BB->end(), Builder.GetInsertPoint());
+ EXPECT_EQ(BB, Builder.GetInsertBlock());
+}
+
+TEST_F(IRBuilderTest, DIBuilder) {
+ IRBuilder<> Builder(BB);
+ DIBuilder DIB(*M);
+ auto File = DIB.createFile("F.CBL", "/");
+ auto CU = DIB.createCompileUnit(dwarf::DW_LANG_Cobol74, "F.CBL", "/",
+ "llvm-cobol74", true, "", 0);
+ auto Type = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
+ auto SP =
+ DIB.createFunction(CU, "foo", "", File, 1, Type, false, true, 1, 0, true);
+ F->setSubprogram(SP);
+ AllocaInst *I = Builder.CreateAlloca(Builder.getInt8Ty());
+ auto BarSP =
+ DIB.createFunction(CU, "bar", "", File, 1, Type, false, true, 1, 0, true);
+ auto BadScope = DIB.createLexicalBlockFile(BarSP, File, 0);
+ I->setDebugLoc(DebugLoc::get(2, 0, BadScope));
+ DIB.finalize();
+ EXPECT_TRUE(verifyModule(*M));
+}
+
+TEST_F(IRBuilderTest, InsertExtractElement) {
+ IRBuilder<> Builder(BB);
+
+ auto VecTy = VectorType::get(Builder.getInt64Ty(), 4);
+ auto Elt1 = Builder.getInt64(-1);
+ auto Elt2 = Builder.getInt64(-2);
+ Value *Vec = UndefValue::get(VecTy);
+ Vec = Builder.CreateInsertElement(Vec, Elt1, Builder.getInt8(1));
+ Vec = Builder.CreateInsertElement(Vec, Elt2, 2);
+ auto X1 = Builder.CreateExtractElement(Vec, 1);
+ auto X2 = Builder.CreateExtractElement(Vec, Builder.getInt32(2));
+ EXPECT_EQ(Elt1, X1);
+ EXPECT_EQ(Elt2, X2);
+}
+
+TEST_F(IRBuilderTest, CreateGlobalStringPtr) {
+ IRBuilder<> Builder(BB);
+
+ auto String1a = Builder.CreateGlobalStringPtr("TestString", "String1a");
+ auto String1b = Builder.CreateGlobalStringPtr("TestString", "String1b", 0);
+ auto String2 = Builder.CreateGlobalStringPtr("TestString", "String2", 1);
+ auto String3 = Builder.CreateGlobalString("TestString", "String3", 2);
+
+ EXPECT_TRUE(String1a->getType()->getPointerAddressSpace() == 0);
+ EXPECT_TRUE(String1b->getType()->getPointerAddressSpace() == 0);
+ EXPECT_TRUE(String2->getType()->getPointerAddressSpace() == 1);
+ EXPECT_TRUE(String3->getType()->getPointerAddressSpace() == 2);
+}
+
+TEST_F(IRBuilderTest, DebugLoc) {
+ auto CalleeTy = FunctionType::get(Type::getVoidTy(Ctx),
+ /*isVarArg=*/false);
+ auto Callee =
+ Function::Create(CalleeTy, Function::ExternalLinkage, "", M.get());
+
+ DIBuilder DIB(*M);
+ auto File = DIB.createFile("tmp.cpp", "/");
+ auto CU = DIB.createCompileUnit(dwarf::DW_LANG_C_plus_plus_11, "tmp.cpp", "/",
+ "", true, "", 0);
+ auto SPType = DIB.createSubroutineType(DIB.getOrCreateTypeArray(None));
+ auto SP =
+ DIB.createFunction(CU, "foo", "foo", File, 1, SPType, false, true, 1);
+ DebugLoc DL1 = DILocation::get(Ctx, 2, 0, SP);
+ DebugLoc DL2 = DILocation::get(Ctx, 3, 0, SP);
+
+ auto BB2 = BasicBlock::Create(Ctx, "bb2", F);
+ auto Br = BranchInst::Create(BB2, BB);
+ Br->setDebugLoc(DL1);
+
+ IRBuilder<> Builder(Ctx);
+ Builder.SetInsertPoint(Br);
+ EXPECT_EQ(DL1, Builder.getCurrentDebugLocation());
+ auto Call1 = Builder.CreateCall(Callee, None);
+ EXPECT_EQ(DL1, Call1->getDebugLoc());
+
+ Call1->setDebugLoc(DL2);
+ Builder.SetInsertPoint(Call1->getParent(), Call1->getIterator());
+ EXPECT_EQ(DL2, Builder.getCurrentDebugLocation());
+ auto Call2 = Builder.CreateCall(Callee, None);
+ EXPECT_EQ(DL2, Call2->getDebugLoc());
+
+ DIB.finalize();
+}
+}
diff --git a/gnu/llvm/unittests/IR/InstructionsTest.cpp b/gnu/llvm/unittests/IR/InstructionsTest.cpp
new file mode 100644
index 00000000000..3ca3ad2b6e8
--- /dev/null
+++ b/gnu/llvm/unittests/IR/InstructionsTest.cpp
@@ -0,0 +1,524 @@
+//===- llvm/unittest/IR/InstructionsTest.cpp - Instructions 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/IR/Instructions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+namespace llvm {
+namespace {
+
+TEST(InstructionsTest, ReturnInst) {
+ LLVMContext &C(getGlobalContext());
+
+ // test for PR6589
+ const ReturnInst* r0 = ReturnInst::Create(C);
+ EXPECT_EQ(r0->getNumOperands(), 0U);
+ EXPECT_EQ(r0->op_begin(), r0->op_end());
+
+ IntegerType* Int1 = IntegerType::get(C, 1);
+ Constant* One = ConstantInt::get(Int1, 1, true);
+ const ReturnInst* r1 = ReturnInst::Create(C, One);
+ EXPECT_EQ(1U, r1->getNumOperands());
+ User::const_op_iterator b(r1->op_begin());
+ EXPECT_NE(r1->op_end(), b);
+ EXPECT_EQ(One, *b);
+ EXPECT_EQ(One, r1->getOperand(0));
+ ++b;
+ EXPECT_EQ(r1->op_end(), b);
+
+ // clean up
+ delete r0;
+ delete r1;
+}
+
+// Test fixture that provides a module and a single function within it. Useful
+// for tests that need to refer to the function in some way.
+class ModuleWithFunctionTest : public testing::Test {
+protected:
+ ModuleWithFunctionTest() : M(new Module("MyModule", Ctx)) {
+ FArgTypes.push_back(Type::getInt8Ty(Ctx));
+ FArgTypes.push_back(Type::getInt32Ty(Ctx));
+ FArgTypes.push_back(Type::getInt64Ty(Ctx));
+ FunctionType *FTy =
+ FunctionType::get(Type::getVoidTy(Ctx), FArgTypes, false);
+ F = Function::Create(FTy, Function::ExternalLinkage, "", M.get());
+ }
+
+ LLVMContext Ctx;
+ std::unique_ptr<Module> M;
+ SmallVector<Type *, 3> FArgTypes;
+ Function *F;
+};
+
+TEST_F(ModuleWithFunctionTest, CallInst) {
+ Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20),
+ ConstantInt::get(Type::getInt32Ty(Ctx), 9999),
+ ConstantInt::get(Type::getInt64Ty(Ctx), 42)};
+ std::unique_ptr<CallInst> Call(CallInst::Create(F, Args));
+
+ // Make sure iteration over a call's arguments works as expected.
+ unsigned Idx = 0;
+ for (Value *Arg : Call->arg_operands()) {
+ EXPECT_EQ(FArgTypes[Idx], Arg->getType());
+ EXPECT_EQ(Call->getArgOperand(Idx)->getType(), Arg->getType());
+ Idx++;
+ }
+}
+
+TEST_F(ModuleWithFunctionTest, InvokeInst) {
+ BasicBlock *BB1 = BasicBlock::Create(Ctx, "", F);
+ BasicBlock *BB2 = BasicBlock::Create(Ctx, "", F);
+
+ Value *Args[] = {ConstantInt::get(Type::getInt8Ty(Ctx), 20),
+ ConstantInt::get(Type::getInt32Ty(Ctx), 9999),
+ ConstantInt::get(Type::getInt64Ty(Ctx), 42)};
+ std::unique_ptr<InvokeInst> Invoke(InvokeInst::Create(F, BB1, BB2, Args));
+
+ // Make sure iteration over invoke's arguments works as expected.
+ unsigned Idx = 0;
+ for (Value *Arg : Invoke->arg_operands()) {
+ EXPECT_EQ(FArgTypes[Idx], Arg->getType());
+ EXPECT_EQ(Invoke->getArgOperand(Idx)->getType(), Arg->getType());
+ Idx++;
+ }
+}
+
+TEST(InstructionsTest, BranchInst) {
+ LLVMContext &C(getGlobalContext());
+
+ // Make a BasicBlocks
+ BasicBlock* bb0 = BasicBlock::Create(C);
+ BasicBlock* bb1 = BasicBlock::Create(C);
+
+ // Mandatory BranchInst
+ const BranchInst* b0 = BranchInst::Create(bb0);
+
+ EXPECT_TRUE(b0->isUnconditional());
+ EXPECT_FALSE(b0->isConditional());
+ EXPECT_EQ(1U, b0->getNumSuccessors());
+
+ // check num operands
+ EXPECT_EQ(1U, b0->getNumOperands());
+
+ EXPECT_NE(b0->op_begin(), b0->op_end());
+ EXPECT_EQ(b0->op_end(), std::next(b0->op_begin()));
+
+ EXPECT_EQ(b0->op_end(), std::next(b0->op_begin()));
+
+ IntegerType* Int1 = IntegerType::get(C, 1);
+ Constant* One = ConstantInt::get(Int1, 1, true);
+
+ // Conditional BranchInst
+ BranchInst* b1 = BranchInst::Create(bb0, bb1, One);
+
+ EXPECT_FALSE(b1->isUnconditional());
+ EXPECT_TRUE(b1->isConditional());
+ EXPECT_EQ(2U, b1->getNumSuccessors());
+
+ // check num operands
+ EXPECT_EQ(3U, b1->getNumOperands());
+
+ User::const_op_iterator b(b1->op_begin());
+
+ // check COND
+ EXPECT_NE(b, b1->op_end());
+ EXPECT_EQ(One, *b);
+ EXPECT_EQ(One, b1->getOperand(0));
+ EXPECT_EQ(One, b1->getCondition());
+ ++b;
+
+ // check ELSE
+ EXPECT_EQ(bb1, *b);
+ EXPECT_EQ(bb1, b1->getOperand(1));
+ EXPECT_EQ(bb1, b1->getSuccessor(1));
+ ++b;
+
+ // check THEN
+ EXPECT_EQ(bb0, *b);
+ EXPECT_EQ(bb0, b1->getOperand(2));
+ EXPECT_EQ(bb0, b1->getSuccessor(0));
+ ++b;
+
+ EXPECT_EQ(b1->op_end(), b);
+
+ // clean up
+ delete b0;
+ delete b1;
+
+ delete bb0;
+ delete bb1;
+}
+
+TEST(InstructionsTest, CastInst) {
+ LLVMContext &C(getGlobalContext());
+
+ Type *Int8Ty = Type::getInt8Ty(C);
+ Type *Int16Ty = Type::getInt16Ty(C);
+ Type *Int32Ty = Type::getInt32Ty(C);
+ Type *Int64Ty = Type::getInt64Ty(C);
+ Type *V8x8Ty = VectorType::get(Int8Ty, 8);
+ Type *V8x64Ty = VectorType::get(Int64Ty, 8);
+ Type *X86MMXTy = Type::getX86_MMXTy(C);
+
+ Type *HalfTy = Type::getHalfTy(C);
+ Type *FloatTy = Type::getFloatTy(C);
+ Type *DoubleTy = Type::getDoubleTy(C);
+
+ Type *V2Int32Ty = VectorType::get(Int32Ty, 2);
+ Type *V2Int64Ty = VectorType::get(Int64Ty, 2);
+ Type *V4Int16Ty = VectorType::get(Int16Ty, 4);
+
+ Type *Int32PtrTy = PointerType::get(Int32Ty, 0);
+ Type *Int64PtrTy = PointerType::get(Int64Ty, 0);
+
+ Type *Int32PtrAS1Ty = PointerType::get(Int32Ty, 1);
+ Type *Int64PtrAS1Ty = PointerType::get(Int64Ty, 1);
+
+ Type *V2Int32PtrAS1Ty = VectorType::get(Int32PtrAS1Ty, 2);
+ Type *V2Int64PtrAS1Ty = VectorType::get(Int64PtrAS1Ty, 2);
+ Type *V4Int32PtrAS1Ty = VectorType::get(Int32PtrAS1Ty, 4);
+ Type *V4Int64PtrAS1Ty = VectorType::get(Int64PtrAS1Ty, 4);
+
+ Type *V2Int64PtrTy = VectorType::get(Int64PtrTy, 2);
+ Type *V2Int32PtrTy = VectorType::get(Int32PtrTy, 2);
+ Type *V4Int32PtrTy = VectorType::get(Int32PtrTy, 4);
+
+ const Constant* c8 = Constant::getNullValue(V8x8Ty);
+ const Constant* c64 = Constant::getNullValue(V8x64Ty);
+
+ const Constant *v2ptr32 = Constant::getNullValue(V2Int32PtrTy);
+
+ EXPECT_TRUE(CastInst::isCastable(V8x8Ty, X86MMXTy));
+ EXPECT_TRUE(CastInst::isCastable(X86MMXTy, V8x8Ty));
+ EXPECT_FALSE(CastInst::isCastable(Int64Ty, X86MMXTy));
+ EXPECT_TRUE(CastInst::isCastable(V8x64Ty, V8x8Ty));
+ EXPECT_TRUE(CastInst::isCastable(V8x8Ty, V8x64Ty));
+ EXPECT_EQ(CastInst::Trunc, CastInst::getCastOpcode(c64, true, V8x8Ty, true));
+ EXPECT_EQ(CastInst::SExt, CastInst::getCastOpcode(c8, true, V8x64Ty, true));
+
+ EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, X86MMXTy));
+ EXPECT_FALSE(CastInst::isBitCastable(X86MMXTy, V8x8Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, X86MMXTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V8x64Ty, V8x8Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V8x8Ty, V8x64Ty));
+
+ // Check address space casts are rejected since we don't know the sizes here
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrAS1Ty, Int32PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, V2Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V2Int64PtrAS1Ty));
+ EXPECT_TRUE(CastInst::isCastable(V2Int32PtrAS1Ty, V2Int32PtrTy));
+ EXPECT_EQ(CastInst::AddrSpaceCast, CastInst::getCastOpcode(v2ptr32, true,
+ V2Int32PtrAS1Ty,
+ true));
+
+ // Test mismatched number of elements for pointers
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int64PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V4Int64PtrAS1Ty, V2Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrAS1Ty, V4Int32PtrAS1Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32PtrTy, V2Int32PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int32PtrTy));
+
+ EXPECT_TRUE(CastInst::isBitCastable(Int32PtrTy, Int64PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(DoubleTy, FloatTy));
+ EXPECT_FALSE(CastInst::isBitCastable(FloatTy, DoubleTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(FloatTy, Int32Ty));
+ EXPECT_TRUE(CastInst::isBitCastable(Int16Ty, HalfTy));
+ EXPECT_TRUE(CastInst::isBitCastable(Int32Ty, FloatTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, Int64Ty));
+
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32Ty, V4Int16Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int32Ty, Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, Int32Ty));
+
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32PtrTy, Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(Int64Ty, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int64PtrTy, V2Int32PtrTy));
+ EXPECT_TRUE(CastInst::isBitCastable(V2Int32PtrTy, V2Int64PtrTy));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int32Ty, V2Int64Ty));
+ EXPECT_FALSE(CastInst::isBitCastable(V2Int64Ty, V2Int32Ty));
+
+
+ EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast,
+ Constant::getNullValue(V4Int32PtrTy),
+ V2Int32PtrTy));
+ EXPECT_FALSE(CastInst::castIsValid(Instruction::BitCast,
+ Constant::getNullValue(V2Int32PtrTy),
+ V4Int32PtrTy));
+
+ EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast,
+ Constant::getNullValue(V4Int32PtrAS1Ty),
+ V2Int32PtrTy));
+ EXPECT_FALSE(CastInst::castIsValid(Instruction::AddrSpaceCast,
+ Constant::getNullValue(V2Int32PtrTy),
+ V4Int32PtrAS1Ty));
+
+
+ // Check that assertion is not hit when creating a cast with a vector of
+ // pointers
+ // First form
+ BasicBlock *BB = BasicBlock::Create(C);
+ Constant *NullV2I32Ptr = Constant::getNullValue(V2Int32PtrTy);
+ CastInst::CreatePointerCast(NullV2I32Ptr, V2Int32Ty, "foo", BB);
+
+ // Second form
+ CastInst::CreatePointerCast(NullV2I32Ptr, V2Int32Ty);
+}
+
+TEST(InstructionsTest, VectorGep) {
+ LLVMContext &C(getGlobalContext());
+
+ // Type Definitions
+ Type *I8Ty = IntegerType::get(C, 8);
+ Type *I32Ty = IntegerType::get(C, 32);
+ PointerType *Ptri8Ty = PointerType::get(I8Ty, 0);
+ PointerType *Ptri32Ty = PointerType::get(I32Ty, 0);
+
+ VectorType *V2xi8PTy = VectorType::get(Ptri8Ty, 2);
+ VectorType *V2xi32PTy = VectorType::get(Ptri32Ty, 2);
+
+ // Test different aspects of the vector-of-pointers type
+ // and GEPs which use this type.
+ ConstantInt *Ci32a = ConstantInt::get(C, APInt(32, 1492));
+ ConstantInt *Ci32b = ConstantInt::get(C, APInt(32, 1948));
+ std::vector<Constant*> ConstVa(2, Ci32a);
+ std::vector<Constant*> ConstVb(2, Ci32b);
+ Constant *C2xi32a = ConstantVector::get(ConstVa);
+ Constant *C2xi32b = ConstantVector::get(ConstVb);
+
+ CastInst *PtrVecA = new IntToPtrInst(C2xi32a, V2xi32PTy);
+ CastInst *PtrVecB = new IntToPtrInst(C2xi32b, V2xi32PTy);
+
+ ICmpInst *ICmp0 = new ICmpInst(ICmpInst::ICMP_SGT, PtrVecA, PtrVecB);
+ ICmpInst *ICmp1 = new ICmpInst(ICmpInst::ICMP_ULT, PtrVecA, PtrVecB);
+ EXPECT_NE(ICmp0, ICmp1); // suppress warning.
+
+ BasicBlock* BB0 = BasicBlock::Create(C);
+ // Test InsertAtEnd ICmpInst constructor.
+ ICmpInst *ICmp2 = new ICmpInst(*BB0, ICmpInst::ICMP_SGE, PtrVecA, PtrVecB);
+ EXPECT_NE(ICmp0, ICmp2); // suppress warning.
+
+ GetElementPtrInst *Gep0 = GetElementPtrInst::Create(I32Ty, PtrVecA, C2xi32a);
+ GetElementPtrInst *Gep1 = GetElementPtrInst::Create(I32Ty, PtrVecA, C2xi32b);
+ GetElementPtrInst *Gep2 = GetElementPtrInst::Create(I32Ty, PtrVecB, C2xi32a);
+ GetElementPtrInst *Gep3 = GetElementPtrInst::Create(I32Ty, PtrVecB, C2xi32b);
+
+ CastInst *BTC0 = new BitCastInst(Gep0, V2xi8PTy);
+ CastInst *BTC1 = new BitCastInst(Gep1, V2xi8PTy);
+ CastInst *BTC2 = new BitCastInst(Gep2, V2xi8PTy);
+ CastInst *BTC3 = new BitCastInst(Gep3, V2xi8PTy);
+
+ Value *S0 = BTC0->stripPointerCasts();
+ Value *S1 = BTC1->stripPointerCasts();
+ Value *S2 = BTC2->stripPointerCasts();
+ Value *S3 = BTC3->stripPointerCasts();
+
+ EXPECT_NE(S0, Gep0);
+ EXPECT_NE(S1, Gep1);
+ EXPECT_NE(S2, Gep2);
+ EXPECT_NE(S3, Gep3);
+
+ int64_t Offset;
+ DataLayout TD("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3"
+ "2:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-s:64:64-f80"
+ ":128:128-n8:16:32:64-S128");
+ // Make sure we don't crash
+ GetPointerBaseWithConstantOffset(Gep0, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep1, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep2, Offset, TD);
+ GetPointerBaseWithConstantOffset(Gep3, Offset, TD);
+
+ // Gep of Geps
+ GetElementPtrInst *GepII0 = GetElementPtrInst::Create(I32Ty, Gep0, C2xi32b);
+ GetElementPtrInst *GepII1 = GetElementPtrInst::Create(I32Ty, Gep1, C2xi32a);
+ GetElementPtrInst *GepII2 = GetElementPtrInst::Create(I32Ty, Gep2, C2xi32b);
+ GetElementPtrInst *GepII3 = GetElementPtrInst::Create(I32Ty, Gep3, C2xi32a);
+
+ EXPECT_EQ(GepII0->getNumIndices(), 1u);
+ EXPECT_EQ(GepII1->getNumIndices(), 1u);
+ EXPECT_EQ(GepII2->getNumIndices(), 1u);
+ EXPECT_EQ(GepII3->getNumIndices(), 1u);
+
+ EXPECT_FALSE(GepII0->hasAllZeroIndices());
+ EXPECT_FALSE(GepII1->hasAllZeroIndices());
+ EXPECT_FALSE(GepII2->hasAllZeroIndices());
+ EXPECT_FALSE(GepII3->hasAllZeroIndices());
+
+ delete GepII0;
+ delete GepII1;
+ delete GepII2;
+ delete GepII3;
+
+ delete BTC0;
+ delete BTC1;
+ delete BTC2;
+ delete BTC3;
+
+ delete Gep0;
+ delete Gep1;
+ delete Gep2;
+ delete Gep3;
+
+ ICmp2->eraseFromParent();
+ delete BB0;
+
+ delete ICmp0;
+ delete ICmp1;
+ delete PtrVecA;
+ delete PtrVecB;
+}
+
+TEST(InstructionsTest, FPMathOperator) {
+ LLVMContext &Context = getGlobalContext();
+ IRBuilder<> Builder(Context);
+ MDBuilder MDHelper(Context);
+ Instruction *I = Builder.CreatePHI(Builder.getDoubleTy(), 0);
+ MDNode *MD1 = MDHelper.createFPMath(1.0);
+ Value *V1 = Builder.CreateFAdd(I, I, "", MD1);
+ EXPECT_TRUE(isa<FPMathOperator>(V1));
+ FPMathOperator *O1 = cast<FPMathOperator>(V1);
+ EXPECT_EQ(O1->getFPAccuracy(), 1.0);
+ delete V1;
+ delete I;
+}
+
+
+TEST(InstructionsTest, isEliminableCastPair) {
+ LLVMContext &C(getGlobalContext());
+
+ Type* Int16Ty = Type::getInt16Ty(C);
+ Type* Int32Ty = Type::getInt32Ty(C);
+ Type* Int64Ty = Type::getInt64Ty(C);
+ Type* Int64PtrTy = Type::getInt64PtrTy(C);
+
+ // Source and destination pointers have same size -> bitcast.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
+ CastInst::IntToPtr,
+ Int64PtrTy, Int64Ty, Int64PtrTy,
+ Int32Ty, nullptr, Int32Ty),
+ CastInst::BitCast);
+
+ // Source and destination have unknown sizes, but the same address space and
+ // the intermediate int is the maximum pointer size -> bitcast
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
+ CastInst::IntToPtr,
+ Int64PtrTy, Int64Ty, Int64PtrTy,
+ nullptr, nullptr, nullptr),
+ CastInst::BitCast);
+
+ // Source and destination have unknown sizes, but the same address space and
+ // the intermediate int is not the maximum pointer size -> nothing
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::PtrToInt,
+ CastInst::IntToPtr,
+ Int64PtrTy, Int32Ty, Int64PtrTy,
+ nullptr, nullptr, nullptr),
+ 0U);
+
+ // Middle pointer big enough -> bitcast.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt,
+ Int64Ty, Int64PtrTy, Int64Ty,
+ nullptr, Int64Ty, nullptr),
+ CastInst::BitCast);
+
+ // Middle pointer too small -> fail.
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::PtrToInt,
+ Int64Ty, Int64PtrTy, Int64Ty,
+ nullptr, Int32Ty, nullptr),
+ 0U);
+
+ // Test that we don't eliminate bitcasts between different address spaces,
+ // or if we don't have available pointer size information.
+ DataLayout DL("e-p:32:32:32-p1:16:16:16-p2:64:64:64-i1:8:8-i8:8:8-i16:16:16"
+ "-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64"
+ "-v128:128:128-a:0:64-s:64:64-f80:128:128-n8:16:32:64-S128");
+
+ Type* Int64PtrTyAS1 = Type::getInt64PtrTy(C, 1);
+ Type* Int64PtrTyAS2 = Type::getInt64PtrTy(C, 2);
+
+ IntegerType *Int16SizePtr = DL.getIntPtrType(C, 1);
+ IntegerType *Int64SizePtr = DL.getIntPtrType(C, 2);
+
+ // Cannot simplify inttoptr, addrspacecast
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::AddrSpaceCast,
+ Int16Ty, Int64PtrTyAS1, Int64PtrTyAS2,
+ nullptr, Int16SizePtr, Int64SizePtr),
+ 0U);
+
+ // Cannot simplify addrspacecast, ptrtoint
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::AddrSpaceCast,
+ CastInst::PtrToInt,
+ Int64PtrTyAS1, Int64PtrTyAS2, Int16Ty,
+ Int64SizePtr, Int16SizePtr, nullptr),
+ 0U);
+
+ // Pass since the bitcast address spaces are the same
+ EXPECT_EQ(CastInst::isEliminableCastPair(CastInst::IntToPtr,
+ CastInst::BitCast,
+ Int16Ty, Int64PtrTyAS1, Int64PtrTyAS1,
+ nullptr, nullptr, nullptr),
+ CastInst::IntToPtr);
+
+}
+
+TEST(InstructionsTest, CloneCall) {
+ LLVMContext &C(getGlobalContext());
+ Type *Int32Ty = Type::getInt32Ty(C);
+ Type *ArgTys[] = {Int32Ty, Int32Ty, Int32Ty};
+ Type *FnTy = FunctionType::get(Int32Ty, ArgTys, /*isVarArg=*/false);
+ Value *Callee = Constant::getNullValue(FnTy->getPointerTo());
+ Value *Args[] = {
+ ConstantInt::get(Int32Ty, 1),
+ ConstantInt::get(Int32Ty, 2),
+ ConstantInt::get(Int32Ty, 3)
+ };
+ std::unique_ptr<CallInst> Call(CallInst::Create(Callee, Args, "result"));
+
+ // Test cloning the tail call kind.
+ CallInst::TailCallKind Kinds[] = {CallInst::TCK_None, CallInst::TCK_Tail,
+ CallInst::TCK_MustTail};
+ for (CallInst::TailCallKind TCK : Kinds) {
+ Call->setTailCallKind(TCK);
+ std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone()));
+ EXPECT_EQ(Call->getTailCallKind(), Clone->getTailCallKind());
+ }
+ Call->setTailCallKind(CallInst::TCK_None);
+
+ // Test cloning an attribute.
+ {
+ AttrBuilder AB;
+ AB.addAttribute(Attribute::ReadOnly);
+ Call->setAttributes(AttributeSet::get(C, AttributeSet::FunctionIndex, AB));
+ std::unique_ptr<CallInst> Clone(cast<CallInst>(Call->clone()));
+ EXPECT_TRUE(Clone->onlyReadsMemory());
+ }
+}
+
+} // end anonymous namespace
+} // end namespace llvm
+
+
diff --git a/gnu/llvm/unittests/IR/LegacyPassManagerTest.cpp b/gnu/llvm/unittests/IR/LegacyPassManagerTest.cpp
new file mode 100644
index 00000000000..1f88283dc0c
--- /dev/null
+++ b/gnu/llvm/unittests/IR/LegacyPassManagerTest.cpp
@@ -0,0 +1,548 @@
+//===- llvm/unittest/IR/LegacyPassManager.cpp - Legacy PassManager tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This unit test exercises the legacy pass manager infrastructure. We use the
+// old names as well to ensure that the source-level compatibility is preserved
+// where possible.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/CallGraphSCCPass.h"
+#include "llvm/Analysis/LoopInfo.h"
+#include "llvm/Analysis/LoopPass.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+ void initializeModuleNDMPass(PassRegistry&);
+ void initializeFPassPass(PassRegistry&);
+ void initializeCGPassPass(PassRegistry&);
+ void initializeLPassPass(PassRegistry&);
+ void initializeBPassPass(PassRegistry&);
+
+ namespace {
+ // ND = no deps
+ // NM = no modifications
+ struct ModuleNDNM: public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDNM() : ModulePass(ID) { }
+ bool runOnModule(Module &M) override {
+ run++;
+ return false;
+ }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleNDNM::ID=0;
+ char ModuleNDNM::run=0;
+
+ struct ModuleNDM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM() : ModulePass(ID) {}
+ bool runOnModule(Module &M) override {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM::ID=0;
+ char ModuleNDM::run=0;
+
+ struct ModuleNDM2 : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleNDM2() : ModulePass(ID) {}
+ bool runOnModule(Module &M) override {
+ run++;
+ return true;
+ }
+ };
+ char ModuleNDM2::ID=0;
+ char ModuleNDM2::run=0;
+
+ struct ModuleDNM : public ModulePass {
+ public:
+ static char run;
+ static char ID;
+ ModuleDNM() : ModulePass(ID) {
+ initializeModuleNDMPass(*PassRegistry::getPassRegistry());
+ }
+ bool runOnModule(Module &M) override {
+ run++;
+ return false;
+ }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<ModuleNDM>();
+ AU.setPreservesAll();
+ }
+ };
+ char ModuleDNM::ID=0;
+ char ModuleDNM::run=0;
+
+ template<typename P>
+ struct PassTestBase : public P {
+ protected:
+ static int runc;
+ static bool initialized;
+ static bool finalized;
+ int allocated;
+ void run() {
+ EXPECT_TRUE(initialized);
+ EXPECT_FALSE(finalized);
+ EXPECT_EQ(0, allocated);
+ allocated++;
+ runc++;
+ }
+ public:
+ static char ID;
+ static void finishedOK(int run) {
+ EXPECT_GT(runc, 0);
+ EXPECT_TRUE(initialized);
+ EXPECT_TRUE(finalized);
+ EXPECT_EQ(run, runc);
+ }
+ PassTestBase() : P(ID), allocated(0) {
+ initialized = false;
+ finalized = false;
+ runc = 0;
+ }
+
+ void releaseMemory() override {
+ EXPECT_GT(runc, 0);
+ EXPECT_GT(allocated, 0);
+ allocated--;
+ }
+ };
+ template<typename P> char PassTestBase<P>::ID;
+ template<typename P> int PassTestBase<P>::runc;
+ template<typename P> bool PassTestBase<P>::initialized;
+ template<typename P> bool PassTestBase<P>::finalized;
+
+ template<typename T, typename P>
+ struct PassTest : public PassTestBase<P> {
+ public:
+#ifndef _MSC_VER // MSVC complains that Pass is not base class.
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+#endif
+ bool doInitialization(T &t) override {
+ EXPECT_FALSE(PassTestBase<P>::initialized);
+ PassTestBase<P>::initialized = true;
+ return false;
+ }
+ bool doFinalization(T &t) override {
+ EXPECT_FALSE(PassTestBase<P>::finalized);
+ PassTestBase<P>::finalized = true;
+ EXPECT_EQ(0, PassTestBase<P>::allocated);
+ return false;
+ }
+ };
+
+ struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
+ public:
+ CGPass() {
+ initializeCGPassPass(*PassRegistry::getPassRegistry());
+ }
+ bool runOnSCC(CallGraphSCC &SCMM) override {
+ run();
+ return false;
+ }
+ };
+
+ struct FPass : public PassTest<Module, FunctionPass> {
+ public:
+ bool runOnFunction(Function &F) override {
+ // FIXME: PR4112
+ // EXPECT_TRUE(getAnalysisIfAvailable<DataLayout>());
+ run();
+ return false;
+ }
+ };
+
+ struct LPass : public PassTestBase<LoopPass> {
+ private:
+ static int initcount;
+ static int fincount;
+ public:
+ LPass() {
+ initializeLPassPass(*PassRegistry::getPassRegistry());
+ initcount = 0; fincount=0;
+ EXPECT_FALSE(initialized);
+ }
+ static void finishedOK(int run, int finalized) {
+ PassTestBase<LoopPass>::finishedOK(run);
+ EXPECT_EQ(run, initcount);
+ EXPECT_EQ(finalized, fincount);
+ }
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+ bool doInitialization(Loop* L, LPPassManager &LPM) override {
+ initialized = true;
+ initcount++;
+ return false;
+ }
+ bool runOnLoop(Loop *L, LPPassManager &LPM) override {
+ run();
+ return false;
+ }
+ bool doFinalization() override {
+ fincount++;
+ finalized = true;
+ return false;
+ }
+ };
+ int LPass::initcount=0;
+ int LPass::fincount=0;
+
+ struct BPass : public PassTestBase<BasicBlockPass> {
+ private:
+ static int inited;
+ static int fin;
+ public:
+ static void finishedOK(int run, int N) {
+ PassTestBase<BasicBlockPass>::finishedOK(run);
+ EXPECT_EQ(inited, N);
+ EXPECT_EQ(fin, N);
+ }
+ BPass() {
+ inited = 0;
+ fin = 0;
+ }
+ bool doInitialization(Module &M) override {
+ EXPECT_FALSE(initialized);
+ initialized = true;
+ return false;
+ }
+ bool doInitialization(Function &F) override {
+ inited++;
+ return false;
+ }
+ bool runOnBasicBlock(BasicBlock &BB) override {
+ run();
+ return false;
+ }
+ bool doFinalization(Function &F) override {
+ fin++;
+ return false;
+ }
+ bool doFinalization(Module &M) override {
+ EXPECT_FALSE(finalized);
+ finalized = true;
+ EXPECT_EQ(0, allocated);
+ return false;
+ }
+ };
+ int BPass::inited=0;
+ int BPass::fin=0;
+
+ struct OnTheFlyTest: public ModulePass {
+ public:
+ static char ID;
+ OnTheFlyTest() : ModulePass(ID) {
+ initializeFPassPass(*PassRegistry::getPassRegistry());
+ }
+ bool runOnModule(Module &M) override {
+ for (Module::iterator I=M.begin(),E=M.end(); I != E; ++I) {
+ Function &F = *I;
+ {
+ SCOPED_TRACE("Running on the fly function pass");
+ getAnalysis<FPass>(F);
+ }
+ }
+ return false;
+ }
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<FPass>();
+ }
+ };
+ char OnTheFlyTest::ID=0;
+
+ TEST(PassManager, RunOnce) {
+ Module M("test-once", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ legacy::PassManager Passes;
+ Passes.add(mNDM2);
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // each pass must be run exactly once, since nothing invalidates them
+ EXPECT_EQ(1, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ }
+
+ TEST(PassManager, ReRun) {
+ Module M("test-rerun", getGlobalContext());
+ struct ModuleNDNM *mNDNM = new ModuleNDNM();
+ struct ModuleDNM *mDNM = new ModuleDNM();
+ struct ModuleNDM *mNDM = new ModuleNDM();
+ struct ModuleNDM2 *mNDM2 = new ModuleNDM2();
+
+ mNDM->run = mNDNM->run = mDNM->run = mNDM2->run = 0;
+
+ legacy::PassManager Passes;
+ Passes.add(mNDM);
+ Passes.add(mNDNM);
+ Passes.add(mNDM2);// invalidates mNDM needed by mDNM
+ Passes.add(mDNM);
+
+ Passes.run(M);
+ // Some passes must be rerun because a pass that modified the
+ // module/function was run in between
+ EXPECT_EQ(2, mNDM->run);
+ EXPECT_EQ(1, mNDNM->run);
+ EXPECT_EQ(1, mNDM2->run);
+ EXPECT_EQ(1, mDNM->run);
+ }
+
+ Module* makeLLVMModule();
+
+ template<typename T>
+ void MemoryTestHelper(int run) {
+ std::unique_ptr<Module> M(makeLLVMModule());
+ T *P = new T();
+ legacy::PassManager Passes;
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run);
+ }
+
+ template<typename T>
+ void MemoryTestHelper(int run, int N) {
+ Module *M = makeLLVMModule();
+ T *P = new T();
+ legacy::PassManager Passes;
+ Passes.add(P);
+ Passes.run(*M);
+ T::finishedOK(run, N);
+ delete M;
+ }
+
+ TEST(PassManager, Memory) {
+ // SCC#1: test1->test2->test3->test1
+ // SCC#2: test4
+ // SCC#3: indirect call node
+ {
+ SCOPED_TRACE("Callgraph pass");
+ MemoryTestHelper<CGPass>(3);
+ }
+
+ {
+ SCOPED_TRACE("Function pass");
+ MemoryTestHelper<FPass>(4);// 4 functions
+ }
+
+ {
+ SCOPED_TRACE("Loop pass");
+ MemoryTestHelper<LPass>(2, 1); //2 loops, 1 function
+ }
+ {
+ SCOPED_TRACE("Basic block pass");
+ MemoryTestHelper<BPass>(7, 4); //9 basic blocks
+ }
+
+ }
+
+ TEST(PassManager, MemoryOnTheFly) {
+ Module *M = makeLLVMModule();
+ {
+ SCOPED_TRACE("Running OnTheFlyTest");
+ struct OnTheFlyTest *O = new OnTheFlyTest();
+ legacy::PassManager Passes;
+ Passes.add(O);
+ Passes.run(*M);
+
+ FPass::finishedOK(4);
+ }
+ delete M;
+ }
+
+ Module* makeLLVMModule() {
+ // Module Construction
+ Module* mod = new Module("test-mem", getGlobalContext());
+ mod->setDataLayout("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
+ "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
+ "a:0:64-s:64:64-f80:128:128");
+ mod->setTargetTriple("x86_64-unknown-linux-gnu");
+
+ // Type Definitions
+ std::vector<Type*>FuncTy_0_args;
+ FunctionType* FuncTy_0 = FunctionType::get(
+ /*Result=*/IntegerType::get(getGlobalContext(), 32),
+ /*Params=*/FuncTy_0_args,
+ /*isVarArg=*/false);
+
+ std::vector<Type*>FuncTy_2_args;
+ FuncTy_2_args.push_back(IntegerType::get(getGlobalContext(), 1));
+ FunctionType* FuncTy_2 = FunctionType::get(
+ /*Result=*/Type::getVoidTy(getGlobalContext()),
+ /*Params=*/FuncTy_2_args,
+ /*isVarArg=*/false);
+
+
+ // Function Declarations
+
+ Function* func_test1 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test1", mod);
+ func_test1->setCallingConv(CallingConv::C);
+ AttributeSet func_test1_PAL;
+ func_test1->setAttributes(func_test1_PAL);
+
+ Function* func_test2 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test2", mod);
+ func_test2->setCallingConv(CallingConv::C);
+ AttributeSet func_test2_PAL;
+ func_test2->setAttributes(func_test2_PAL);
+
+ Function* func_test3 = Function::Create(
+ /*Type=*/FuncTy_0,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test3", mod);
+ func_test3->setCallingConv(CallingConv::C);
+ AttributeSet func_test3_PAL;
+ func_test3->setAttributes(func_test3_PAL);
+
+ Function* func_test4 = Function::Create(
+ /*Type=*/FuncTy_2,
+ /*Linkage=*/GlobalValue::ExternalLinkage,
+ /*Name=*/"test4", mod);
+ func_test4->setCallingConv(CallingConv::C);
+ AttributeSet func_test4_PAL;
+ func_test4->setAttributes(func_test4_PAL);
+
+ // Global Variable Declarations
+
+
+ // Constant Definitions
+
+ // Global Variable Definitions
+
+ // Function Definitions
+
+ // Function: test1 (func_test1)
+ {
+
+ BasicBlock* label_entry = BasicBlock::Create(getGlobalContext(), "entry",func_test1,nullptr);
+
+ // Block entry (label_entry)
+ CallInst* int32_3 = CallInst::Create(func_test2, "", label_entry);
+ int32_3->setCallingConv(CallingConv::C);
+ int32_3->setTailCall(false);AttributeSet int32_3_PAL;
+ int32_3->setAttributes(int32_3_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_3, label_entry);
+
+ }
+
+ // Function: test2 (func_test2)
+ {
+
+ BasicBlock* label_entry_5 = BasicBlock::Create(getGlobalContext(), "entry",func_test2,nullptr);
+
+ // Block entry (label_entry_5)
+ CallInst* int32_6 = CallInst::Create(func_test3, "", label_entry_5);
+ int32_6->setCallingConv(CallingConv::C);
+ int32_6->setTailCall(false);AttributeSet int32_6_PAL;
+ int32_6->setAttributes(int32_6_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_6, label_entry_5);
+
+ }
+
+ // Function: test3 (func_test3)
+ {
+
+ BasicBlock* label_entry_8 = BasicBlock::Create(getGlobalContext(), "entry",func_test3,nullptr);
+
+ // Block entry (label_entry_8)
+ CallInst* int32_9 = CallInst::Create(func_test1, "", label_entry_8);
+ int32_9->setCallingConv(CallingConv::C);
+ int32_9->setTailCall(false);AttributeSet int32_9_PAL;
+ int32_9->setAttributes(int32_9_PAL);
+
+ ReturnInst::Create(getGlobalContext(), int32_9, label_entry_8);
+
+ }
+
+ // Function: test4 (func_test4)
+ {
+ Function::arg_iterator args = func_test4->arg_begin();
+ Value *int1_f = &*args++;
+ int1_f->setName("f");
+
+ BasicBlock* label_entry_11 = BasicBlock::Create(getGlobalContext(), "entry",func_test4,nullptr);
+ BasicBlock* label_bb = BasicBlock::Create(getGlobalContext(), "bb",func_test4,nullptr);
+ BasicBlock* label_bb1 = BasicBlock::Create(getGlobalContext(), "bb1",func_test4,nullptr);
+ BasicBlock* label_return = BasicBlock::Create(getGlobalContext(), "return",func_test4,nullptr);
+
+ // Block entry (label_entry_11)
+ BranchInst::Create(label_bb, label_entry_11);
+
+ // Block bb (label_bb)
+ BranchInst::Create(label_bb, label_bb1, int1_f, label_bb);
+
+ // Block bb1 (label_bb1)
+ BranchInst::Create(label_bb1, label_return, int1_f, label_bb1);
+
+ // Block return (label_return)
+ ReturnInst::Create(getGlobalContext(), label_return);
+
+ }
+ return mod;
+ }
+
+ }
+}
+
+INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
+INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
+INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
+INITIALIZE_PASS(FPass, "fp","fp", false, false)
+INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)
+INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
+INITIALIZE_PASS_END(LPass, "lp","lp", false, false)
+INITIALIZE_PASS(BPass, "bp","bp", false, false)
diff --git a/gnu/llvm/unittests/IR/MDBuilderTest.cpp b/gnu/llvm/unittests/IR/MDBuilderTest.cpp
new file mode 100644
index 00000000000..ab2d34e89db
--- /dev/null
+++ b/gnu/llvm/unittests/IR/MDBuilderTest.cpp
@@ -0,0 +1,108 @@
+//===- llvm/unittests/MDBuilderTest.cpp - MDBuilder 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/IR/MDBuilder.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Operator.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MDBuilderTest : public testing::Test {
+protected:
+ LLVMContext Context;
+};
+
+TEST_F(MDBuilderTest, createString) {
+ MDBuilder MDHelper(Context);
+ MDString *Str0 = MDHelper.createString("");
+ MDString *Str1 = MDHelper.createString("string");
+ EXPECT_EQ(Str0->getString(), StringRef(""));
+ EXPECT_EQ(Str1->getString(), StringRef("string"));
+}
+TEST_F(MDBuilderTest, createFPMath) {
+ MDBuilder MDHelper(Context);
+ MDNode *MD0 = MDHelper.createFPMath(0.0);
+ MDNode *MD1 = MDHelper.createFPMath(1.0);
+ EXPECT_EQ(MD0, (MDNode *)nullptr);
+ EXPECT_NE(MD1, (MDNode *)nullptr);
+ EXPECT_EQ(MD1->getNumOperands(), 1U);
+ Metadata *Op = MD1->getOperand(0);
+ EXPECT_TRUE(mdconst::hasa<ConstantFP>(Op));
+ ConstantFP *Val = mdconst::extract<ConstantFP>(Op);
+ EXPECT_TRUE(Val->getType()->isFloatingPointTy());
+ EXPECT_TRUE(Val->isExactlyValue(1.0));
+}
+TEST_F(MDBuilderTest, createRangeMetadata) {
+ MDBuilder MDHelper(Context);
+ APInt A(8, 1), B(8, 2);
+ MDNode *R0 = MDHelper.createRange(A, A);
+ MDNode *R1 = MDHelper.createRange(A, B);
+ EXPECT_EQ(R0, (MDNode *)nullptr);
+ EXPECT_NE(R1, (MDNode *)nullptr);
+ EXPECT_EQ(R1->getNumOperands(), 2U);
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(0)));
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(R1->getOperand(1)));
+ ConstantInt *C0 = mdconst::extract<ConstantInt>(R1->getOperand(0));
+ ConstantInt *C1 = mdconst::extract<ConstantInt>(R1->getOperand(1));
+ EXPECT_EQ(C0->getValue(), A);
+ EXPECT_EQ(C1->getValue(), B);
+}
+TEST_F(MDBuilderTest, createAnonymousTBAARoot) {
+ MDBuilder MDHelper(Context);
+ MDNode *R0 = MDHelper.createAnonymousTBAARoot();
+ MDNode *R1 = MDHelper.createAnonymousTBAARoot();
+ EXPECT_NE(R0, R1);
+ EXPECT_GE(R0->getNumOperands(), 1U);
+ EXPECT_GE(R1->getNumOperands(), 1U);
+ EXPECT_EQ(R0->getOperand(0), R0);
+ EXPECT_EQ(R1->getOperand(0), R1);
+ EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr);
+ EXPECT_TRUE(R1->getNumOperands() == 1 || R1->getOperand(1) == nullptr);
+}
+TEST_F(MDBuilderTest, createTBAARoot) {
+ MDBuilder MDHelper(Context);
+ MDNode *R0 = MDHelper.createTBAARoot("Root");
+ MDNode *R1 = MDHelper.createTBAARoot("Root");
+ EXPECT_EQ(R0, R1);
+ EXPECT_GE(R0->getNumOperands(), 1U);
+ EXPECT_TRUE(isa<MDString>(R0->getOperand(0)));
+ EXPECT_EQ(cast<MDString>(R0->getOperand(0))->getString(), "Root");
+ EXPECT_TRUE(R0->getNumOperands() == 1 || R0->getOperand(1) == nullptr);
+}
+TEST_F(MDBuilderTest, createTBAANode) {
+ MDBuilder MDHelper(Context);
+ MDNode *R = MDHelper.createTBAARoot("Root");
+ MDNode *N0 = MDHelper.createTBAANode("Node", R);
+ MDNode *N1 = MDHelper.createTBAANode("edoN", R);
+ MDNode *N2 = MDHelper.createTBAANode("Node", R, true);
+ MDNode *N3 = MDHelper.createTBAANode("Node", R);
+ EXPECT_EQ(N0, N3);
+ EXPECT_NE(N0, N1);
+ EXPECT_NE(N0, N2);
+ EXPECT_GE(N0->getNumOperands(), 2U);
+ EXPECT_GE(N1->getNumOperands(), 2U);
+ EXPECT_GE(N2->getNumOperands(), 3U);
+ EXPECT_TRUE(isa<MDString>(N0->getOperand(0)));
+ EXPECT_TRUE(isa<MDString>(N1->getOperand(0)));
+ EXPECT_TRUE(isa<MDString>(N2->getOperand(0)));
+ EXPECT_EQ(cast<MDString>(N0->getOperand(0))->getString(), "Node");
+ EXPECT_EQ(cast<MDString>(N1->getOperand(0))->getString(), "edoN");
+ EXPECT_EQ(cast<MDString>(N2->getOperand(0))->getString(), "Node");
+ EXPECT_EQ(N0->getOperand(1), R);
+ EXPECT_EQ(N1->getOperand(1), R);
+ EXPECT_EQ(N2->getOperand(1), R);
+ EXPECT_TRUE(mdconst::hasa<ConstantInt>(N2->getOperand(2)));
+ EXPECT_EQ(mdconst::extract<ConstantInt>(N2->getOperand(2))->getZExtValue(),
+ 1U);
+}
+}
diff --git a/gnu/llvm/unittests/IR/Makefile b/gnu/llvm/unittests/IR/Makefile
new file mode 100644
index 00000000000..45aa8d68082
--- /dev/null
+++ b/gnu/llvm/unittests/IR/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/IR/Makefile -------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = IR
+LINK_COMPONENTS := core analysis asmparser
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/IR/MetadataTest.cpp b/gnu/llvm/unittests/IR/MetadataTest.cpp
new file mode 100644
index 00000000000..a745b235a38
--- /dev/null
+++ b/gnu/llvm/unittests/IR/MetadataTest.cpp
@@ -0,0 +1,2304 @@
+//===- unittests/IR/MetadataTest.cpp - Metadata 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 "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugInfoMetadata.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(ContextAndReplaceableUsesTest, FromContext) {
+ LLVMContext Context;
+ ContextAndReplaceableUses CRU(Context);
+ EXPECT_EQ(&Context, &CRU.getContext());
+ EXPECT_FALSE(CRU.hasReplaceableUses());
+ EXPECT_FALSE(CRU.getReplaceableUses());
+}
+
+TEST(ContextAndReplaceableUsesTest, FromReplaceableUses) {
+ LLVMContext Context;
+ ContextAndReplaceableUses CRU(make_unique<ReplaceableMetadataImpl>(Context));
+ EXPECT_EQ(&Context, &CRU.getContext());
+ EXPECT_TRUE(CRU.hasReplaceableUses());
+ EXPECT_TRUE(CRU.getReplaceableUses());
+}
+
+TEST(ContextAndReplaceableUsesTest, makeReplaceable) {
+ LLVMContext Context;
+ ContextAndReplaceableUses CRU(Context);
+ CRU.makeReplaceable(make_unique<ReplaceableMetadataImpl>(Context));
+ EXPECT_EQ(&Context, &CRU.getContext());
+ EXPECT_TRUE(CRU.hasReplaceableUses());
+ EXPECT_TRUE(CRU.getReplaceableUses());
+}
+
+TEST(ContextAndReplaceableUsesTest, takeReplaceableUses) {
+ LLVMContext Context;
+ auto ReplaceableUses = make_unique<ReplaceableMetadataImpl>(Context);
+ auto *Ptr = ReplaceableUses.get();
+ ContextAndReplaceableUses CRU(std::move(ReplaceableUses));
+ ReplaceableUses = CRU.takeReplaceableUses();
+ EXPECT_EQ(&Context, &CRU.getContext());
+ EXPECT_FALSE(CRU.hasReplaceableUses());
+ EXPECT_FALSE(CRU.getReplaceableUses());
+ EXPECT_EQ(Ptr, ReplaceableUses.get());
+}
+
+class MetadataTest : public testing::Test {
+public:
+ MetadataTest() : M("test", Context), Counter(0) {}
+
+protected:
+ LLVMContext Context;
+ Module M;
+ int Counter;
+
+ MDNode *getNode() { return MDNode::get(Context, None); }
+ MDNode *getNode(Metadata *MD) { return MDNode::get(Context, MD); }
+ MDNode *getNode(Metadata *MD1, Metadata *MD2) {
+ Metadata *MDs[] = {MD1, MD2};
+ return MDNode::get(Context, MDs);
+ }
+
+ MDTuple *getTuple() { return MDTuple::getDistinct(Context, None); }
+ DISubroutineType *getSubroutineType() {
+ return DISubroutineType::getDistinct(Context, 0, getNode(nullptr));
+ }
+ DISubprogram *getSubprogram() {
+ return DISubprogram::getDistinct(Context, nullptr, "", "", nullptr, 0,
+ nullptr, false, false, 0, nullptr, 0, 0, 0,
+ 0);
+ }
+ DIScopeRef getSubprogramRef() { return getSubprogram()->getRef(); }
+ DIFile *getFile() {
+ return DIFile::getDistinct(Context, "file.c", "/path/to/dir");
+ }
+ DITypeRef getBasicType(StringRef Name) {
+ return DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, Name)
+ ->getRef();
+ }
+ DITypeRef getDerivedType() {
+ return DIDerivedType::getDistinct(Context, dwarf::DW_TAG_pointer_type, "",
+ nullptr, 0, nullptr,
+ getBasicType("basictype"), 1, 2, 0, 0)
+ ->getRef();
+ }
+ Constant *getConstant() {
+ return ConstantInt::get(Type::getInt32Ty(Context), Counter++);
+ }
+ ConstantAsMetadata *getConstantAsMetadata() {
+ return ConstantAsMetadata::get(getConstant());
+ }
+ DITypeRef getCompositeType() {
+ return DICompositeType::getDistinct(
+ Context, dwarf::DW_TAG_structure_type, "", nullptr, 0, nullptr,
+ nullptr, 32, 32, 0, 0, nullptr, 0, nullptr, nullptr, "")
+ ->getRef();
+ }
+ Function *getFunction(StringRef Name) {
+ return cast<Function>(M.getOrInsertFunction(
+ Name, FunctionType::get(Type::getVoidTy(Context), None, false)));
+ }
+};
+typedef MetadataTest MDStringTest;
+
+// Test that construction of MDString with different value produces different
+// MDString objects, even with the same string pointer and nulls in the string.
+TEST_F(MDStringTest, CreateDifferent) {
+ char x[3] = { 'f', 0, 'A' };
+ MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));
+ x[2] = 'B';
+ MDString *s2 = MDString::get(Context, StringRef(&x[0], 3));
+ EXPECT_NE(s1, s2);
+}
+
+// Test that creation of MDStrings with the same string contents produces the
+// same MDString object, even with different pointers.
+TEST_F(MDStringTest, CreateSame) {
+ char x[4] = { 'a', 'b', 'c', 'X' };
+ char y[4] = { 'a', 'b', 'c', 'Y' };
+
+ MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));
+ MDString *s2 = MDString::get(Context, StringRef(&y[0], 3));
+ EXPECT_EQ(s1, s2);
+}
+
+// Test that MDString prints out the string we fed it.
+TEST_F(MDStringTest, PrintingSimple) {
+ char *str = new char[13];
+ strncpy(str, "testing 1 2 3", 13);
+ MDString *s = MDString::get(Context, StringRef(str, 13));
+ strncpy(str, "aaaaaaaaaaaaa", 13);
+ delete[] str;
+
+ std::string Str;
+ raw_string_ostream oss(Str);
+ s->print(oss);
+ EXPECT_STREQ("!\"testing 1 2 3\"", oss.str().c_str());
+}
+
+// Test printing of MDString with non-printable characters.
+TEST_F(MDStringTest, PrintingComplex) {
+ char str[5] = {0, '\n', '"', '\\', (char)-1};
+ MDString *s = MDString::get(Context, StringRef(str+0, 5));
+ std::string Str;
+ raw_string_ostream oss(Str);
+ s->print(oss);
+ EXPECT_STREQ("!\"\\00\\0A\\22\\5C\\FF\"", oss.str().c_str());
+}
+
+typedef MetadataTest MDNodeTest;
+
+// Test the two constructors, and containing other Constants.
+TEST_F(MDNodeTest, Simple) {
+ char x[3] = { 'a', 'b', 'c' };
+ char y[3] = { '1', '2', '3' };
+
+ MDString *s1 = MDString::get(Context, StringRef(&x[0], 3));
+ MDString *s2 = MDString::get(Context, StringRef(&y[0], 3));
+ ConstantAsMetadata *CI = ConstantAsMetadata::get(
+ ConstantInt::get(getGlobalContext(), APInt(8, 0)));
+
+ std::vector<Metadata *> V;
+ V.push_back(s1);
+ V.push_back(CI);
+ V.push_back(s2);
+
+ MDNode *n1 = MDNode::get(Context, V);
+ Metadata *const c1 = n1;
+ MDNode *n2 = MDNode::get(Context, c1);
+ Metadata *const c2 = n2;
+ MDNode *n3 = MDNode::get(Context, V);
+ MDNode *n4 = MDNode::getIfExists(Context, V);
+ MDNode *n5 = MDNode::getIfExists(Context, c1);
+ MDNode *n6 = MDNode::getIfExists(Context, c2);
+ EXPECT_NE(n1, n2);
+ EXPECT_EQ(n1, n3);
+ EXPECT_EQ(n4, n1);
+ EXPECT_EQ(n5, n2);
+ EXPECT_EQ(n6, (Metadata *)nullptr);
+
+ EXPECT_EQ(3u, n1->getNumOperands());
+ EXPECT_EQ(s1, n1->getOperand(0));
+ EXPECT_EQ(CI, n1->getOperand(1));
+ EXPECT_EQ(s2, n1->getOperand(2));
+
+ EXPECT_EQ(1u, n2->getNumOperands());
+ EXPECT_EQ(n1, n2->getOperand(0));
+}
+
+TEST_F(MDNodeTest, Delete) {
+ Constant *C = ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 1);
+ Instruction *I = new BitCastInst(C, Type::getInt32Ty(getGlobalContext()));
+
+ Metadata *const V = LocalAsMetadata::get(I);
+ MDNode *n = MDNode::get(Context, V);
+ TrackingMDRef wvh(n);
+
+ EXPECT_EQ(n, wvh);
+
+ delete I;
+}
+
+TEST_F(MDNodeTest, SelfReference) {
+ // !0 = !{!0}
+ // !1 = !{!0}
+ {
+ auto Temp = MDNode::getTemporary(Context, None);
+ Metadata *Args[] = {Temp.get()};
+ MDNode *Self = MDNode::get(Context, Args);
+ Self->replaceOperandWith(0, Self);
+ ASSERT_EQ(Self, Self->getOperand(0));
+
+ // Self-references should be distinct, so MDNode::get() should grab a
+ // uniqued node that references Self, not Self.
+ Args[0] = Self;
+ MDNode *Ref1 = MDNode::get(Context, Args);
+ MDNode *Ref2 = MDNode::get(Context, Args);
+ EXPECT_NE(Self, Ref1);
+ EXPECT_EQ(Ref1, Ref2);
+ }
+
+ // !0 = !{!0, !{}}
+ // !1 = !{!0, !{}}
+ {
+ auto Temp = MDNode::getTemporary(Context, None);
+ Metadata *Args[] = {Temp.get(), MDNode::get(Context, None)};
+ MDNode *Self = MDNode::get(Context, Args);
+ Self->replaceOperandWith(0, Self);
+ ASSERT_EQ(Self, Self->getOperand(0));
+
+ // Self-references should be distinct, so MDNode::get() should grab a
+ // uniqued node that references Self, not Self itself.
+ Args[0] = Self;
+ MDNode *Ref1 = MDNode::get(Context, Args);
+ MDNode *Ref2 = MDNode::get(Context, Args);
+ EXPECT_NE(Self, Ref1);
+ EXPECT_EQ(Ref1, Ref2);
+ }
+}
+
+TEST_F(MDNodeTest, Print) {
+ Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7);
+ MDString *S = MDString::get(Context, "foo");
+ MDNode *N0 = getNode();
+ MDNode *N1 = getNode(N0);
+ MDNode *N2 = getNode(N0, N1);
+
+ Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};
+ MDNode *N = MDNode::get(Context, Args);
+
+ std::string Expected;
+ {
+ raw_string_ostream OS(Expected);
+ OS << "<" << (void *)N << "> = !{";
+ C->printAsOperand(OS);
+ OS << ", ";
+ S->printAsOperand(OS);
+ OS << ", null";
+ MDNode *Nodes[] = {N0, N1, N2};
+ for (auto *Node : Nodes)
+ OS << ", <" << (void *)Node << ">";
+ OS << "}";
+ }
+
+ std::string Actual;
+ {
+ raw_string_ostream OS(Actual);
+ N->print(OS);
+ }
+
+ EXPECT_EQ(Expected, Actual);
+}
+
+#define EXPECT_PRINTER_EQ(EXPECTED, PRINT) \
+ do { \
+ std::string Actual_; \
+ raw_string_ostream OS(Actual_); \
+ PRINT; \
+ OS.flush(); \
+ std::string Expected_(EXPECTED); \
+ EXPECT_EQ(Expected_, Actual_); \
+ } while (false)
+
+TEST_F(MDNodeTest, PrintTemporary) {
+ MDNode *Arg = getNode();
+ TempMDNode Temp = MDNode::getTemporary(Context, Arg);
+ MDNode *N = getNode(Temp.get());
+ Module M("test", Context);
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");
+ NMD->addOperand(N);
+
+ EXPECT_PRINTER_EQ("!0 = !{!1}", N->print(OS, &M));
+ EXPECT_PRINTER_EQ("!1 = <temporary!> !{!2}", Temp->print(OS, &M));
+ EXPECT_PRINTER_EQ("!2 = !{}", Arg->print(OS, &M));
+
+ // Cleanup.
+ Temp->replaceAllUsesWith(Arg);
+}
+
+TEST_F(MDNodeTest, PrintFromModule) {
+ Constant *C = ConstantInt::get(Type::getInt32Ty(Context), 7);
+ MDString *S = MDString::get(Context, "foo");
+ MDNode *N0 = getNode();
+ MDNode *N1 = getNode(N0);
+ MDNode *N2 = getNode(N0, N1);
+
+ Metadata *Args[] = {ConstantAsMetadata::get(C), S, nullptr, N0, N1, N2};
+ MDNode *N = MDNode::get(Context, Args);
+ Module M("test", Context);
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata("named");
+ NMD->addOperand(N);
+
+ std::string Expected;
+ {
+ raw_string_ostream OS(Expected);
+ OS << "!0 = !{";
+ C->printAsOperand(OS);
+ OS << ", ";
+ S->printAsOperand(OS);
+ OS << ", null, !1, !2, !3}";
+ }
+
+ EXPECT_PRINTER_EQ(Expected, N->print(OS, &M));
+}
+
+TEST_F(MDNodeTest, PrintFromFunction) {
+ Module M("test", Context);
+ auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);
+ auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);
+ auto *BB0 = BasicBlock::Create(Context, "entry", F0);
+ auto *BB1 = BasicBlock::Create(Context, "entry", F1);
+ auto *R0 = ReturnInst::Create(Context, BB0);
+ auto *R1 = ReturnInst::Create(Context, BB1);
+ auto *N0 = MDNode::getDistinct(Context, None);
+ auto *N1 = MDNode::getDistinct(Context, None);
+ R0->setMetadata("md", N0);
+ R1->setMetadata("md", N1);
+
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, &M));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, &M));
+
+ ModuleSlotTracker MST(&M);
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", N0->print(OS, MST));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", N1->print(OS, MST));
+}
+
+TEST_F(MDNodeTest, PrintFromMetadataAsValue) {
+ Module M("test", Context);
+
+ auto *Intrinsic =
+ Function::Create(FunctionType::get(Type::getVoidTy(Context),
+ Type::getMetadataTy(Context), false),
+ GlobalValue::ExternalLinkage, "llvm.intrinsic", &M);
+
+ auto *FTy = FunctionType::get(Type::getVoidTy(Context), false);
+ auto *F0 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F0", &M);
+ auto *F1 = Function::Create(FTy, GlobalValue::ExternalLinkage, "F1", &M);
+ auto *BB0 = BasicBlock::Create(Context, "entry", F0);
+ auto *BB1 = BasicBlock::Create(Context, "entry", F1);
+ auto *N0 = MDNode::getDistinct(Context, None);
+ auto *N1 = MDNode::getDistinct(Context, None);
+ auto *MAV0 = MetadataAsValue::get(Context, N0);
+ auto *MAV1 = MetadataAsValue::get(Context, N1);
+ CallInst::Create(Intrinsic, MAV0, "", BB0);
+ CallInst::Create(Intrinsic, MAV1, "", BB1);
+
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS));
+ EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false));
+ EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false));
+ EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true));
+ EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true));
+
+ ModuleSlotTracker MST(&M);
+ EXPECT_PRINTER_EQ("!0 = distinct !{}", MAV0->print(OS, MST));
+ EXPECT_PRINTER_EQ("!1 = distinct !{}", MAV1->print(OS, MST));
+ EXPECT_PRINTER_EQ("!0", MAV0->printAsOperand(OS, false, MST));
+ EXPECT_PRINTER_EQ("!1", MAV1->printAsOperand(OS, false, MST));
+ EXPECT_PRINTER_EQ("metadata !0", MAV0->printAsOperand(OS, true, MST));
+ EXPECT_PRINTER_EQ("metadata !1", MAV1->printAsOperand(OS, true, MST));
+}
+#undef EXPECT_PRINTER_EQ
+
+TEST_F(MDNodeTest, NullOperand) {
+ // metadata !{}
+ MDNode *Empty = MDNode::get(Context, None);
+
+ // metadata !{metadata !{}}
+ Metadata *Ops[] = {Empty};
+ MDNode *N = MDNode::get(Context, Ops);
+ ASSERT_EQ(Empty, N->getOperand(0));
+
+ // metadata !{metadata !{}} => metadata !{null}
+ N->replaceOperandWith(0, nullptr);
+ ASSERT_EQ(nullptr, N->getOperand(0));
+
+ // metadata !{null}
+ Ops[0] = nullptr;
+ MDNode *NullOp = MDNode::get(Context, Ops);
+ ASSERT_EQ(nullptr, NullOp->getOperand(0));
+ EXPECT_EQ(N, NullOp);
+}
+
+TEST_F(MDNodeTest, DistinctOnUniquingCollision) {
+ // !{}
+ MDNode *Empty = MDNode::get(Context, None);
+ ASSERT_TRUE(Empty->isResolved());
+ EXPECT_FALSE(Empty->isDistinct());
+
+ // !{!{}}
+ Metadata *Wrapped1Ops[] = {Empty};
+ MDNode *Wrapped1 = MDNode::get(Context, Wrapped1Ops);
+ ASSERT_EQ(Empty, Wrapped1->getOperand(0));
+ ASSERT_TRUE(Wrapped1->isResolved());
+ EXPECT_FALSE(Wrapped1->isDistinct());
+
+ // !{!{!{}}}
+ Metadata *Wrapped2Ops[] = {Wrapped1};
+ MDNode *Wrapped2 = MDNode::get(Context, Wrapped2Ops);
+ ASSERT_EQ(Wrapped1, Wrapped2->getOperand(0));
+ ASSERT_TRUE(Wrapped2->isResolved());
+ EXPECT_FALSE(Wrapped2->isDistinct());
+
+ // !{!{!{}}} => !{!{}}
+ Wrapped2->replaceOperandWith(0, Empty);
+ ASSERT_EQ(Empty, Wrapped2->getOperand(0));
+ EXPECT_TRUE(Wrapped2->isDistinct());
+ EXPECT_FALSE(Wrapped1->isDistinct());
+}
+
+TEST_F(MDNodeTest, getDistinct) {
+ // !{}
+ MDNode *Empty = MDNode::get(Context, None);
+ ASSERT_TRUE(Empty->isResolved());
+ ASSERT_FALSE(Empty->isDistinct());
+ ASSERT_EQ(Empty, MDNode::get(Context, None));
+
+ // distinct !{}
+ MDNode *Distinct1 = MDNode::getDistinct(Context, None);
+ MDNode *Distinct2 = MDNode::getDistinct(Context, None);
+ EXPECT_TRUE(Distinct1->isResolved());
+ EXPECT_TRUE(Distinct2->isDistinct());
+ EXPECT_NE(Empty, Distinct1);
+ EXPECT_NE(Empty, Distinct2);
+ EXPECT_NE(Distinct1, Distinct2);
+
+ // !{}
+ ASSERT_EQ(Empty, MDNode::get(Context, None));
+}
+
+TEST_F(MDNodeTest, isUniqued) {
+ MDNode *U = MDTuple::get(Context, None);
+ MDNode *D = MDTuple::getDistinct(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
+ EXPECT_TRUE(U->isUniqued());
+ EXPECT_FALSE(D->isUniqued());
+ EXPECT_FALSE(T->isUniqued());
+}
+
+TEST_F(MDNodeTest, isDistinct) {
+ MDNode *U = MDTuple::get(Context, None);
+ MDNode *D = MDTuple::getDistinct(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
+ EXPECT_FALSE(U->isDistinct());
+ EXPECT_TRUE(D->isDistinct());
+ EXPECT_FALSE(T->isDistinct());
+}
+
+TEST_F(MDNodeTest, isTemporary) {
+ MDNode *U = MDTuple::get(Context, None);
+ MDNode *D = MDTuple::getDistinct(Context, None);
+ auto T = MDTuple::getTemporary(Context, None);
+ EXPECT_FALSE(U->isTemporary());
+ EXPECT_FALSE(D->isTemporary());
+ EXPECT_TRUE(T->isTemporary());
+}
+
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
+
+TEST_F(MDNodeTest, deathOnNoReplaceTemporaryRAUW) {
+ auto Temp = MDNode::getTemporary(Context, None);
+ Temp->setCanReplace(false);
+ EXPECT_DEATH(Temp->replaceAllUsesWith(nullptr),
+ "Attempted to replace Metadata marked for no replacement");
+ Temp->setCanReplace(true);
+ // Remove the references to Temp; required for teardown.
+ Temp->replaceAllUsesWith(nullptr);
+}
+
+#endif
+
+TEST_F(MDNodeTest, getDistinctWithUnresolvedOperands) {
+ // temporary !{}
+ auto Temp = MDTuple::getTemporary(Context, None);
+ ASSERT_FALSE(Temp->isResolved());
+
+ // distinct !{temporary !{}}
+ Metadata *Ops[] = {Temp.get()};
+ MDNode *Distinct = MDNode::getDistinct(Context, Ops);
+ EXPECT_TRUE(Distinct->isResolved());
+ EXPECT_EQ(Temp.get(), Distinct->getOperand(0));
+
+ // temporary !{} => !{}
+ MDNode *Empty = MDNode::get(Context, None);
+ Temp->replaceAllUsesWith(Empty);
+ EXPECT_EQ(Empty, Distinct->getOperand(0));
+}
+
+TEST_F(MDNodeTest, handleChangedOperandRecursion) {
+ // !0 = !{}
+ MDNode *N0 = MDNode::get(Context, None);
+
+ // !1 = !{!3, null}
+ auto Temp3 = MDTuple::getTemporary(Context, None);
+ Metadata *Ops1[] = {Temp3.get(), nullptr};
+ MDNode *N1 = MDNode::get(Context, Ops1);
+
+ // !2 = !{!3, !0}
+ Metadata *Ops2[] = {Temp3.get(), N0};
+ MDNode *N2 = MDNode::get(Context, Ops2);
+
+ // !3 = !{!2}
+ Metadata *Ops3[] = {N2};
+ MDNode *N3 = MDNode::get(Context, Ops3);
+ Temp3->replaceAllUsesWith(N3);
+
+ // !4 = !{!1}
+ Metadata *Ops4[] = {N1};
+ MDNode *N4 = MDNode::get(Context, Ops4);
+
+ // Confirm that the cycle prevented RAUW from getting dropped.
+ EXPECT_TRUE(N0->isResolved());
+ EXPECT_FALSE(N1->isResolved());
+ EXPECT_FALSE(N2->isResolved());
+ EXPECT_FALSE(N3->isResolved());
+ EXPECT_FALSE(N4->isResolved());
+
+ // Create a couple of distinct nodes to observe what's going on.
+ //
+ // !5 = distinct !{!2}
+ // !6 = distinct !{!3}
+ Metadata *Ops5[] = {N2};
+ MDNode *N5 = MDNode::getDistinct(Context, Ops5);
+ Metadata *Ops6[] = {N3};
+ MDNode *N6 = MDNode::getDistinct(Context, Ops6);
+
+ // Mutate !2 to look like !1, causing a uniquing collision (and an RAUW).
+ // This will ripple up, with !3 colliding with !4, and RAUWing. Since !2
+ // references !3, this can cause a re-entry of handleChangedOperand() when !3
+ // is not ready for it.
+ //
+ // !2->replaceOperandWith(1, nullptr)
+ // !2: !{!3, !0} => !{!3, null}
+ // !2->replaceAllUsesWith(!1)
+ // !3: !{!2] => !{!1}
+ // !3->replaceAllUsesWith(!4)
+ N2->replaceOperandWith(1, nullptr);
+
+ // If all has gone well, N2 and N3 will have been RAUW'ed and deleted from
+ // under us. Just check that the other nodes are sane.
+ //
+ // !1 = !{!4, null}
+ // !4 = !{!1}
+ // !5 = distinct !{!1}
+ // !6 = distinct !{!4}
+ EXPECT_EQ(N4, N1->getOperand(0));
+ EXPECT_EQ(N1, N4->getOperand(0));
+ EXPECT_EQ(N1, N5->getOperand(0));
+ EXPECT_EQ(N4, N6->getOperand(0));
+}
+
+TEST_F(MDNodeTest, replaceResolvedOperand) {
+ // Check code for replacing one resolved operand with another. If doing this
+ // directly (via replaceOperandWith()) becomes illegal, change the operand to
+ // a global value that gets RAUW'ed.
+ //
+ // Use a temporary node to keep N from being resolved.
+ auto Temp = MDTuple::getTemporary(Context, None);
+ Metadata *Ops[] = {nullptr, Temp.get()};
+
+ MDNode *Empty = MDTuple::get(Context, ArrayRef<Metadata *>());
+ MDNode *N = MDTuple::get(Context, Ops);
+ EXPECT_EQ(nullptr, N->getOperand(0));
+ ASSERT_FALSE(N->isResolved());
+
+ // Check code for replacing resolved nodes.
+ N->replaceOperandWith(0, Empty);
+ EXPECT_EQ(Empty, N->getOperand(0));
+
+ // Check code for adding another unresolved operand.
+ N->replaceOperandWith(0, Temp.get());
+ EXPECT_EQ(Temp.get(), N->getOperand(0));
+
+ // Remove the references to Temp; required for teardown.
+ Temp->replaceAllUsesWith(nullptr);
+}
+
+TEST_F(MDNodeTest, replaceWithUniqued) {
+ auto *Empty = MDTuple::get(Context, None);
+ MDTuple *FirstUniqued;
+ {
+ Metadata *Ops[] = {Empty};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ EXPECT_TRUE(Temp->isTemporary());
+
+ // Don't expect a collision.
+ auto *Current = Temp.get();
+ FirstUniqued = MDNode::replaceWithUniqued(std::move(Temp));
+ EXPECT_TRUE(FirstUniqued->isUniqued());
+ EXPECT_TRUE(FirstUniqued->isResolved());
+ EXPECT_EQ(Current, FirstUniqued);
+ }
+ {
+ Metadata *Ops[] = {Empty};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ EXPECT_TRUE(Temp->isTemporary());
+
+ // Should collide with Uniqued above this time.
+ auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));
+ EXPECT_TRUE(Uniqued->isUniqued());
+ EXPECT_TRUE(Uniqued->isResolved());
+ EXPECT_EQ(FirstUniqued, Uniqued);
+ }
+ {
+ auto Unresolved = MDTuple::getTemporary(Context, None);
+ Metadata *Ops[] = {Unresolved.get()};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ EXPECT_TRUE(Temp->isTemporary());
+
+ // Shouldn't be resolved.
+ auto *Uniqued = MDNode::replaceWithUniqued(std::move(Temp));
+ EXPECT_TRUE(Uniqued->isUniqued());
+ EXPECT_FALSE(Uniqued->isResolved());
+
+ // Should be a different node.
+ EXPECT_NE(FirstUniqued, Uniqued);
+
+ // Should resolve when we update its node (note: be careful to avoid a
+ // collision with any other nodes above).
+ Uniqued->replaceOperandWith(0, nullptr);
+ EXPECT_TRUE(Uniqued->isResolved());
+ }
+}
+
+TEST_F(MDNodeTest, replaceWithUniquedResolvingOperand) {
+ // temp !{}
+ MDTuple *Op = MDTuple::getTemporary(Context, None).release();
+ EXPECT_FALSE(Op->isResolved());
+
+ // temp !{temp !{}}
+ Metadata *Ops[] = {Op};
+ MDTuple *N = MDTuple::getTemporary(Context, Ops).release();
+ EXPECT_FALSE(N->isResolved());
+
+ // temp !{temp !{}} => !{temp !{}}
+ ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
+ EXPECT_FALSE(N->isResolved());
+
+ // !{temp !{}} => !{!{}}
+ ASSERT_EQ(Op, MDNode::replaceWithUniqued(TempMDTuple(Op)));
+ EXPECT_TRUE(Op->isResolved());
+ EXPECT_TRUE(N->isResolved());
+}
+
+TEST_F(MDNodeTest, replaceWithUniquedChangingOperand) {
+ // i1* @GV
+ Type *Ty = Type::getInt1PtrTy(Context);
+ std::unique_ptr<GlobalVariable> GV(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ ConstantAsMetadata *Op = ConstantAsMetadata::get(GV.get());
+
+ // temp !{i1* @GV}
+ Metadata *Ops[] = {Op};
+ MDTuple *N = MDTuple::getTemporary(Context, Ops).release();
+
+ // temp !{i1* @GV} => !{i1* @GV}
+ ASSERT_EQ(N, MDNode::replaceWithUniqued(TempMDTuple(N)));
+ ASSERT_TRUE(N->isUniqued());
+
+ // !{i1* @GV} => !{null}
+ GV.reset();
+ ASSERT_TRUE(N->isUniqued());
+ Metadata *NullOps[] = {nullptr};
+ ASSERT_EQ(N, MDTuple::get(Context, NullOps));
+}
+
+TEST_F(MDNodeTest, replaceWithDistinct) {
+ {
+ auto *Empty = MDTuple::get(Context, None);
+ Metadata *Ops[] = {Empty};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ EXPECT_TRUE(Temp->isTemporary());
+
+ // Don't expect a collision.
+ auto *Current = Temp.get();
+ auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));
+ EXPECT_TRUE(Distinct->isDistinct());
+ EXPECT_TRUE(Distinct->isResolved());
+ EXPECT_EQ(Current, Distinct);
+ }
+ {
+ auto Unresolved = MDTuple::getTemporary(Context, None);
+ Metadata *Ops[] = {Unresolved.get()};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ EXPECT_TRUE(Temp->isTemporary());
+
+ // Don't expect a collision.
+ auto *Current = Temp.get();
+ auto *Distinct = MDNode::replaceWithDistinct(std::move(Temp));
+ EXPECT_TRUE(Distinct->isDistinct());
+ EXPECT_TRUE(Distinct->isResolved());
+ EXPECT_EQ(Current, Distinct);
+
+ // Cleanup; required for teardown.
+ Unresolved->replaceAllUsesWith(nullptr);
+ }
+}
+
+TEST_F(MDNodeTest, replaceWithPermanent) {
+ Metadata *Ops[] = {nullptr};
+ auto Temp = MDTuple::getTemporary(Context, Ops);
+ auto *T = Temp.get();
+
+ // U is a normal, uniqued node that references T.
+ auto *U = MDTuple::get(Context, T);
+ EXPECT_TRUE(U->isUniqued());
+
+ // Make Temp self-referencing.
+ Temp->replaceOperandWith(0, T);
+
+ // Try to uniquify Temp. This should, despite the name in the API, give a
+ // 'distinct' node, since self-references aren't allowed to be uniqued.
+ //
+ // Since it's distinct, N should have the same address as when it was a
+ // temporary (i.e., be equal to T not U).
+ auto *N = MDNode::replaceWithPermanent(std::move(Temp));
+ EXPECT_EQ(N, T);
+ EXPECT_TRUE(N->isDistinct());
+
+ // U should be the canonical unique node with N as the argument.
+ EXPECT_EQ(U, MDTuple::get(Context, N));
+ EXPECT_TRUE(U->isUniqued());
+
+ // This temporary should collide with U when replaced, but it should still be
+ // uniqued.
+ EXPECT_EQ(U, MDNode::replaceWithPermanent(MDTuple::getTemporary(Context, N)));
+ EXPECT_TRUE(U->isUniqued());
+
+ // This temporary should become a new uniqued node.
+ auto Temp2 = MDTuple::getTemporary(Context, U);
+ auto *V = Temp2.get();
+ EXPECT_EQ(V, MDNode::replaceWithPermanent(std::move(Temp2)));
+ EXPECT_TRUE(V->isUniqued());
+ EXPECT_EQ(U, V->getOperand(0));
+}
+
+TEST_F(MDNodeTest, deleteTemporaryWithTrackingRef) {
+ TrackingMDRef Ref;
+ EXPECT_EQ(nullptr, Ref.get());
+ {
+ auto Temp = MDTuple::getTemporary(Context, None);
+ Ref.reset(Temp.get());
+ EXPECT_EQ(Temp.get(), Ref.get());
+ }
+ EXPECT_EQ(nullptr, Ref.get());
+}
+
+typedef MetadataTest DILocationTest;
+
+TEST_F(DILocationTest, Overflow) {
+ DISubprogram *N = getSubprogram();
+ {
+ DILocation *L = DILocation::get(Context, 2, 7, N);
+ EXPECT_EQ(2u, L->getLine());
+ EXPECT_EQ(7u, L->getColumn());
+ }
+ unsigned U16 = 1u << 16;
+ {
+ DILocation *L = DILocation::get(Context, UINT32_MAX, U16 - 1, N);
+ EXPECT_EQ(UINT32_MAX, L->getLine());
+ EXPECT_EQ(U16 - 1, L->getColumn());
+ }
+ {
+ DILocation *L = DILocation::get(Context, UINT32_MAX, U16, N);
+ EXPECT_EQ(UINT32_MAX, L->getLine());
+ EXPECT_EQ(0u, L->getColumn());
+ }
+ {
+ DILocation *L = DILocation::get(Context, UINT32_MAX, U16 + 1, N);
+ EXPECT_EQ(UINT32_MAX, L->getLine());
+ EXPECT_EQ(0u, L->getColumn());
+ }
+}
+
+TEST_F(DILocationTest, getDistinct) {
+ MDNode *N = getSubprogram();
+ DILocation *L0 = DILocation::getDistinct(Context, 2, 7, N);
+ EXPECT_TRUE(L0->isDistinct());
+ DILocation *L1 = DILocation::get(Context, 2, 7, N);
+ EXPECT_FALSE(L1->isDistinct());
+ EXPECT_EQ(L1, DILocation::get(Context, 2, 7, N));
+}
+
+TEST_F(DILocationTest, getTemporary) {
+ MDNode *N = MDNode::get(Context, None);
+ auto L = DILocation::getTemporary(Context, 2, 7, N);
+ EXPECT_TRUE(L->isTemporary());
+ EXPECT_FALSE(L->isResolved());
+}
+
+TEST_F(DILocationTest, cloneTemporary) {
+ MDNode *N = MDNode::get(Context, None);
+ auto L = DILocation::getTemporary(Context, 2, 7, N);
+ EXPECT_TRUE(L->isTemporary());
+ auto L2 = L->clone();
+ EXPECT_TRUE(L2->isTemporary());
+}
+
+typedef MetadataTest GenericDINodeTest;
+
+TEST_F(GenericDINodeTest, get) {
+ StringRef Header = "header";
+ auto *Empty = MDNode::get(Context, None);
+ Metadata *Ops1[] = {Empty};
+ auto *N = GenericDINode::get(Context, 15, Header, Ops1);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(2u, N->getNumOperands());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(MDString::get(Context, Header), N->getOperand(0));
+ EXPECT_EQ(1u, N->getNumDwarfOperands());
+ EXPECT_EQ(Empty, N->getDwarfOperand(0));
+ EXPECT_EQ(Empty, N->getOperand(1));
+ ASSERT_TRUE(N->isUniqued());
+
+ EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));
+
+ N->replaceOperandWith(1, nullptr);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(nullptr, N->getDwarfOperand(0));
+ ASSERT_TRUE(N->isUniqued());
+
+ Metadata *Ops2[] = {nullptr};
+ EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops2));
+
+ N->replaceDwarfOperandWith(0, Empty);
+ EXPECT_EQ(15u, N->getTag());
+ EXPECT_EQ(Header, N->getHeader());
+ EXPECT_EQ(Empty, N->getDwarfOperand(0));
+ ASSERT_TRUE(N->isUniqued());
+ EXPECT_EQ(N, GenericDINode::get(Context, 15, Header, Ops1));
+
+ TempGenericDINode Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(GenericDINodeTest, getEmptyHeader) {
+ // Canonicalize !"" to null.
+ auto *N = GenericDINode::get(Context, 15, StringRef(), None);
+ EXPECT_EQ(StringRef(), N->getHeader());
+ EXPECT_EQ(nullptr, N->getOperand(0));
+}
+
+typedef MetadataTest DISubrangeTest;
+
+TEST_F(DISubrangeTest, get) {
+ auto *N = DISubrange::get(Context, 5, 7);
+ EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());
+ EXPECT_EQ(5, N->getCount());
+ EXPECT_EQ(7, N->getLowerBound());
+ EXPECT_EQ(N, DISubrange::get(Context, 5, 7));
+ EXPECT_EQ(DISubrange::get(Context, 5, 0), DISubrange::get(Context, 5));
+
+ TempDISubrange Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DISubrangeTest, getEmptyArray) {
+ auto *N = DISubrange::get(Context, -1, 0);
+ EXPECT_EQ(dwarf::DW_TAG_subrange_type, N->getTag());
+ EXPECT_EQ(-1, N->getCount());
+ EXPECT_EQ(0, N->getLowerBound());
+ EXPECT_EQ(N, DISubrange::get(Context, -1, 0));
+}
+
+typedef MetadataTest DIEnumeratorTest;
+
+TEST_F(DIEnumeratorTest, get) {
+ auto *N = DIEnumerator::get(Context, 7, "name");
+ EXPECT_EQ(dwarf::DW_TAG_enumerator, N->getTag());
+ EXPECT_EQ(7, N->getValue());
+ EXPECT_EQ("name", N->getName());
+ EXPECT_EQ(N, DIEnumerator::get(Context, 7, "name"));
+
+ EXPECT_NE(N, DIEnumerator::get(Context, 8, "name"));
+ EXPECT_NE(N, DIEnumerator::get(Context, 7, "nam"));
+
+ TempDIEnumerator Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DIBasicTypeTest;
+
+TEST_F(DIBasicTypeTest, get) {
+ auto *N =
+ DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33, 26, 7);
+ EXPECT_EQ(dwarf::DW_TAG_base_type, N->getTag());
+ EXPECT_EQ("special", N->getName());
+ EXPECT_EQ(33u, N->getSizeInBits());
+ EXPECT_EQ(26u, N->getAlignInBits());
+ EXPECT_EQ(7u, N->getEncoding());
+ EXPECT_EQ(0u, N->getLine());
+ EXPECT_EQ(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+ 26, 7));
+
+ EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type,
+ "special", 33, 26, 7));
+ EXPECT_NE(N,
+ DIBasicType::get(Context, dwarf::DW_TAG_base_type, "s", 33, 26, 7));
+ EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 32,
+ 26, 7));
+ EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+ 25, 7));
+ EXPECT_NE(N, DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special", 33,
+ 26, 6));
+
+ TempDIBasicType Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DIBasicTypeTest, getWithLargeValues) {
+ auto *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "special",
+ UINT64_MAX, UINT64_MAX - 1, 7);
+ EXPECT_EQ(UINT64_MAX, N->getSizeInBits());
+ EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits());
+}
+
+TEST_F(DIBasicTypeTest, getUnspecified) {
+ auto *N =
+ DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, "unspecified");
+ EXPECT_EQ(dwarf::DW_TAG_unspecified_type, N->getTag());
+ EXPECT_EQ("unspecified", N->getName());
+ EXPECT_EQ(0u, N->getSizeInBits());
+ EXPECT_EQ(0u, N->getAlignInBits());
+ EXPECT_EQ(0u, N->getEncoding());
+ EXPECT_EQ(0u, N->getLine());
+}
+
+typedef MetadataTest DITypeTest;
+
+TEST_F(DITypeTest, clone) {
+ // Check that DIType has a specialized clone that returns TempDIType.
+ DIType *N = DIBasicType::get(Context, dwarf::DW_TAG_base_type, "int", 32, 32,
+ dwarf::DW_ATE_signed);
+
+ TempDIType Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DITypeTest, setFlags) {
+ // void (void)
+ Metadata *TypesOps[] = {nullptr};
+ Metadata *Types = MDTuple::get(Context, TypesOps);
+
+ DIType *D = DISubroutineType::getDistinct(Context, 0u, Types);
+ EXPECT_EQ(0u, D->getFlags());
+ D->setFlags(DINode::FlagRValueReference);
+ EXPECT_EQ(DINode::FlagRValueReference, D->getFlags());
+ D->setFlags(0u);
+ EXPECT_EQ(0u, D->getFlags());
+
+ TempDIType T = DISubroutineType::getTemporary(Context, 0u, Types);
+ EXPECT_EQ(0u, T->getFlags());
+ T->setFlags(DINode::FlagRValueReference);
+ EXPECT_EQ(DINode::FlagRValueReference, T->getFlags());
+ T->setFlags(0u);
+ EXPECT_EQ(0u, T->getFlags());
+}
+
+typedef MetadataTest DIDerivedTypeTest;
+
+TEST_F(DIDerivedTypeTest, get) {
+ DIFile *File = getFile();
+ DIScopeRef Scope = getSubprogramRef();
+ DITypeRef BaseType = getBasicType("basic");
+ MDTuple *ExtraData = getTuple();
+
+ auto *N = DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+ File, 1, Scope, BaseType, 2, 3, 4, 5, ExtraData);
+ EXPECT_EQ(dwarf::DW_TAG_pointer_type, N->getTag());
+ EXPECT_EQ("something", N->getName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(1u, N->getLine());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(BaseType, N->getBaseType());
+ EXPECT_EQ(2u, N->getSizeInBits());
+ EXPECT_EQ(3u, N->getAlignInBits());
+ EXPECT_EQ(4u, N->getOffsetInBits());
+ EXPECT_EQ(5u, N->getFlags());
+ EXPECT_EQ(ExtraData, N->getExtraData());
+ EXPECT_EQ(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 2, 3,
+ 4, 5, ExtraData));
+
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_reference_type,
+ "something", File, 1, Scope, BaseType, 2, 3,
+ 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "else",
+ File, 1, Scope, BaseType, 2, 3, 4, 5,
+ ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", getFile(), 1, Scope, BaseType, 2,
+ 3, 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 2, Scope, BaseType, 2, 3,
+ 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, getSubprogramRef(),
+ BaseType, 2, 3, 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(
+ Context, dwarf::DW_TAG_pointer_type, "something", File, 1,
+ Scope, getBasicType("basic2"), 2, 3, 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 3, 3,
+ 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 2, 2,
+ 4, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 2, 3,
+ 5, 5, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 2, 3,
+ 4, 4, ExtraData));
+ EXPECT_NE(N, DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type,
+ "something", File, 1, Scope, BaseType, 2, 3,
+ 4, 5, getTuple()));
+
+ TempDIDerivedType Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DIDerivedTypeTest, getWithLargeValues) {
+ DIFile *File = getFile();
+ DIScopeRef Scope = getSubprogramRef();
+ DITypeRef BaseType = getBasicType("basic");
+ MDTuple *ExtraData = getTuple();
+
+ auto *N = DIDerivedType::get(Context, dwarf::DW_TAG_pointer_type, "something",
+ File, 1, Scope, BaseType, UINT64_MAX,
+ UINT64_MAX - 1, UINT64_MAX - 2, 5, ExtraData);
+ EXPECT_EQ(UINT64_MAX, N->getSizeInBits());
+ EXPECT_EQ(UINT64_MAX - 1, N->getAlignInBits());
+ EXPECT_EQ(UINT64_MAX - 2, N->getOffsetInBits());
+}
+
+typedef MetadataTest DICompositeTypeTest;
+
+TEST_F(DICompositeTypeTest, get) {
+ unsigned Tag = dwarf::DW_TAG_structure_type;
+ StringRef Name = "some name";
+ DIFile *File = getFile();
+ unsigned Line = 1;
+ DIScopeRef Scope = getSubprogramRef();
+ DITypeRef BaseType = getCompositeType();
+ uint64_t SizeInBits = 2;
+ uint64_t AlignInBits = 3;
+ uint64_t OffsetInBits = 4;
+ unsigned Flags = 5;
+ MDTuple *Elements = getTuple();
+ unsigned RuntimeLang = 6;
+ DITypeRef VTableHolder = getCompositeType();
+ MDTuple *TemplateParams = getTuple();
+ StringRef Identifier = "some id";
+
+ auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier);
+ EXPECT_EQ(Tag, N->getTag());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(BaseType, N->getBaseType());
+ EXPECT_EQ(SizeInBits, N->getSizeInBits());
+ EXPECT_EQ(AlignInBits, N->getAlignInBits());
+ EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
+ EXPECT_EQ(Flags, N->getFlags());
+ EXPECT_EQ(Elements, N->getElements().get());
+ EXPECT_EQ(RuntimeLang, N->getRuntimeLang());
+ EXPECT_EQ(VTableHolder, N->getVTableHolder());
+ EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
+ EXPECT_EQ(Identifier, N->getIdentifier());
+
+ EXPECT_EQ(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+
+ EXPECT_NE(N, DICompositeType::get(Context, Tag + 1, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, "abc", File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, getFile(), Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line + 1, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, getSubprogramRef(), BaseType,
+ SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
+ RuntimeLang, VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, getBasicType("other"),
+ SizeInBits, AlignInBits, OffsetInBits, Flags, Elements,
+ RuntimeLang, VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits + 1, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits + 1,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits + 1, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags + 1, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, getTuple(), RuntimeLang,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang + 1,
+ VTableHolder, TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
+ AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
+ getCompositeType(), TemplateParams, Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, getTuple(), Identifier));
+ EXPECT_NE(N, DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, "other"));
+
+ // Be sure that missing identifiers get null pointers.
+ EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, "")
+ ->getRawIdentifier());
+ EXPECT_FALSE(DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams)
+ ->getRawIdentifier());
+
+ TempDICompositeType Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DICompositeTypeTest, getWithLargeValues) {
+ unsigned Tag = dwarf::DW_TAG_structure_type;
+ StringRef Name = "some name";
+ DIFile *File = getFile();
+ unsigned Line = 1;
+ DIScopeRef Scope = getSubprogramRef();
+ DITypeRef BaseType = getCompositeType();
+ uint64_t SizeInBits = UINT64_MAX;
+ uint64_t AlignInBits = UINT64_MAX - 1;
+ uint64_t OffsetInBits = UINT64_MAX - 2;
+ unsigned Flags = 5;
+ MDTuple *Elements = getTuple();
+ unsigned RuntimeLang = 6;
+ DITypeRef VTableHolder = getCompositeType();
+ MDTuple *TemplateParams = getTuple();
+ StringRef Identifier = "some id";
+
+ auto *N = DICompositeType::get(Context, Tag, Name, File, Line, Scope,
+ BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, Elements, RuntimeLang,
+ VTableHolder, TemplateParams, Identifier);
+ EXPECT_EQ(SizeInBits, N->getSizeInBits());
+ EXPECT_EQ(AlignInBits, N->getAlignInBits());
+ EXPECT_EQ(OffsetInBits, N->getOffsetInBits());
+}
+
+TEST_F(DICompositeTypeTest, replaceOperands) {
+ unsigned Tag = dwarf::DW_TAG_structure_type;
+ StringRef Name = "some name";
+ DIFile *File = getFile();
+ unsigned Line = 1;
+ DIScopeRef Scope = getSubprogramRef();
+ DITypeRef BaseType = getCompositeType();
+ uint64_t SizeInBits = 2;
+ uint64_t AlignInBits = 3;
+ uint64_t OffsetInBits = 4;
+ unsigned Flags = 5;
+ unsigned RuntimeLang = 6;
+ StringRef Identifier = "some id";
+
+ auto *N = DICompositeType::get(
+ Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits,
+ OffsetInBits, Flags, nullptr, RuntimeLang, nullptr, nullptr, Identifier);
+
+ auto *Elements = MDTuple::getDistinct(Context, None);
+ EXPECT_EQ(nullptr, N->getElements().get());
+ N->replaceElements(Elements);
+ EXPECT_EQ(Elements, N->getElements().get());
+ N->replaceElements(nullptr);
+ EXPECT_EQ(nullptr, N->getElements().get());
+
+ DITypeRef VTableHolder = getCompositeType();
+ EXPECT_EQ(nullptr, N->getVTableHolder());
+ N->replaceVTableHolder(VTableHolder);
+ EXPECT_EQ(VTableHolder, N->getVTableHolder());
+ N->replaceVTableHolder(nullptr);
+ EXPECT_EQ(nullptr, N->getVTableHolder());
+
+ auto *TemplateParams = MDTuple::getDistinct(Context, None);
+ EXPECT_EQ(nullptr, N->getTemplateParams().get());
+ N->replaceTemplateParams(TemplateParams);
+ EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
+ N->replaceTemplateParams(nullptr);
+ EXPECT_EQ(nullptr, N->getTemplateParams().get());
+}
+
+typedef MetadataTest DISubroutineTypeTest;
+
+TEST_F(DISubroutineTypeTest, get) {
+ unsigned Flags = 1;
+ MDTuple *TypeArray = getTuple();
+
+ auto *N = DISubroutineType::get(Context, Flags, TypeArray);
+ EXPECT_EQ(dwarf::DW_TAG_subroutine_type, N->getTag());
+ EXPECT_EQ(Flags, N->getFlags());
+ EXPECT_EQ(TypeArray, N->getTypeArray().get());
+ EXPECT_EQ(N, DISubroutineType::get(Context, Flags, TypeArray));
+
+ EXPECT_NE(N, DISubroutineType::get(Context, Flags + 1, TypeArray));
+ EXPECT_NE(N, DISubroutineType::get(Context, Flags, getTuple()));
+
+ TempDISubroutineType Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+
+ // Test always-empty operands.
+ EXPECT_EQ(nullptr, N->getScope());
+ EXPECT_EQ(nullptr, N->getFile());
+ EXPECT_EQ("", N->getName());
+}
+
+typedef MetadataTest DIFileTest;
+
+TEST_F(DIFileTest, get) {
+ StringRef Filename = "file";
+ StringRef Directory = "dir";
+ auto *N = DIFile::get(Context, Filename, Directory);
+
+ EXPECT_EQ(dwarf::DW_TAG_file_type, N->getTag());
+ EXPECT_EQ(Filename, N->getFilename());
+ EXPECT_EQ(Directory, N->getDirectory());
+ EXPECT_EQ(N, DIFile::get(Context, Filename, Directory));
+
+ EXPECT_NE(N, DIFile::get(Context, "other", Directory));
+ EXPECT_NE(N, DIFile::get(Context, Filename, "other"));
+
+ TempDIFile Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DIFileTest, ScopeGetFile) {
+ // Ensure that DIScope::getFile() returns itself.
+ DIScope *N = DIFile::get(Context, "file", "dir");
+ EXPECT_EQ(N, N->getFile());
+}
+
+typedef MetadataTest DICompileUnitTest;
+
+TEST_F(DICompileUnitTest, get) {
+ unsigned SourceLanguage = 1;
+ DIFile *File = getFile();
+ StringRef Producer = "some producer";
+ bool IsOptimized = false;
+ StringRef Flags = "flag after flag";
+ unsigned RuntimeVersion = 2;
+ StringRef SplitDebugFilename = "another/file";
+ unsigned EmissionKind = 3;
+ MDTuple *EnumTypes = getTuple();
+ MDTuple *RetainedTypes = getTuple();
+ MDTuple *Subprograms = getTuple();
+ MDTuple *GlobalVariables = getTuple();
+ MDTuple *ImportedEntities = getTuple();
+ uint64_t DWOId = 0x10000000c0ffee;
+ MDTuple *Macros = getTuple();
+ auto *N = DICompileUnit::getDistinct(
+ Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+ RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+ RetainedTypes, Subprograms, GlobalVariables, ImportedEntities, Macros,
+ DWOId);
+
+ EXPECT_EQ(dwarf::DW_TAG_compile_unit, N->getTag());
+ EXPECT_EQ(SourceLanguage, N->getSourceLanguage());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Producer, N->getProducer());
+ EXPECT_EQ(IsOptimized, N->isOptimized());
+ EXPECT_EQ(Flags, N->getFlags());
+ EXPECT_EQ(RuntimeVersion, N->getRuntimeVersion());
+ EXPECT_EQ(SplitDebugFilename, N->getSplitDebugFilename());
+ EXPECT_EQ(EmissionKind, N->getEmissionKind());
+ EXPECT_EQ(EnumTypes, N->getEnumTypes().get());
+ EXPECT_EQ(RetainedTypes, N->getRetainedTypes().get());
+ EXPECT_EQ(Subprograms, N->getSubprograms().get());
+ EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
+ EXPECT_EQ(ImportedEntities, N->getImportedEntities().get());
+ EXPECT_EQ(Macros, N->getMacros().get());
+ EXPECT_EQ(DWOId, N->getDWOId());
+
+ TempDICompileUnit Temp = N->clone();
+ EXPECT_EQ(dwarf::DW_TAG_compile_unit, Temp->getTag());
+ EXPECT_EQ(SourceLanguage, Temp->getSourceLanguage());
+ EXPECT_EQ(File, Temp->getFile());
+ EXPECT_EQ(Producer, Temp->getProducer());
+ EXPECT_EQ(IsOptimized, Temp->isOptimized());
+ EXPECT_EQ(Flags, Temp->getFlags());
+ EXPECT_EQ(RuntimeVersion, Temp->getRuntimeVersion());
+ EXPECT_EQ(SplitDebugFilename, Temp->getSplitDebugFilename());
+ EXPECT_EQ(EmissionKind, Temp->getEmissionKind());
+ EXPECT_EQ(EnumTypes, Temp->getEnumTypes().get());
+ EXPECT_EQ(RetainedTypes, Temp->getRetainedTypes().get());
+ EXPECT_EQ(Subprograms, Temp->getSubprograms().get());
+ EXPECT_EQ(GlobalVariables, Temp->getGlobalVariables().get());
+ EXPECT_EQ(ImportedEntities, Temp->getImportedEntities().get());
+ EXPECT_EQ(Macros, Temp->getMacros().get());
+ EXPECT_EQ(DWOId, Temp->getDWOId());
+
+ auto *TempAddress = Temp.get();
+ auto *Clone = MDNode::replaceWithPermanent(std::move(Temp));
+ EXPECT_TRUE(Clone->isDistinct());
+ EXPECT_EQ(TempAddress, Clone);
+}
+
+TEST_F(DICompileUnitTest, replaceArrays) {
+ unsigned SourceLanguage = 1;
+ DIFile *File = getFile();
+ StringRef Producer = "some producer";
+ bool IsOptimized = false;
+ StringRef Flags = "flag after flag";
+ unsigned RuntimeVersion = 2;
+ StringRef SplitDebugFilename = "another/file";
+ unsigned EmissionKind = 3;
+ MDTuple *EnumTypes = MDTuple::getDistinct(Context, None);
+ MDTuple *RetainedTypes = MDTuple::getDistinct(Context, None);
+ MDTuple *ImportedEntities = MDTuple::getDistinct(Context, None);
+ uint64_t DWOId = 0xc0ffee;
+ auto *N = DICompileUnit::getDistinct(
+ Context, SourceLanguage, File, Producer, IsOptimized, Flags,
+ RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes,
+ RetainedTypes, nullptr, nullptr, ImportedEntities, nullptr, DWOId);
+
+ auto *Subprograms = MDTuple::getDistinct(Context, None);
+ EXPECT_EQ(nullptr, N->getSubprograms().get());
+ N->replaceSubprograms(Subprograms);
+ EXPECT_EQ(Subprograms, N->getSubprograms().get());
+ N->replaceSubprograms(nullptr);
+ EXPECT_EQ(nullptr, N->getSubprograms().get());
+
+ auto *GlobalVariables = MDTuple::getDistinct(Context, None);
+ EXPECT_EQ(nullptr, N->getGlobalVariables().get());
+ N->replaceGlobalVariables(GlobalVariables);
+ EXPECT_EQ(GlobalVariables, N->getGlobalVariables().get());
+ N->replaceGlobalVariables(nullptr);
+ EXPECT_EQ(nullptr, N->getGlobalVariables().get());
+
+ auto *Macros = MDTuple::getDistinct(Context, None);
+ EXPECT_EQ(nullptr, N->getMacros().get());
+ N->replaceMacros(Macros);
+ EXPECT_EQ(Macros, N->getMacros().get());
+ N->replaceMacros(nullptr);
+ EXPECT_EQ(nullptr, N->getMacros().get());
+}
+
+typedef MetadataTest DISubprogramTest;
+
+TEST_F(DISubprogramTest, get) {
+ DIScopeRef Scope = getCompositeType();
+ StringRef Name = "name";
+ StringRef LinkageName = "linkage";
+ DIFile *File = getFile();
+ unsigned Line = 2;
+ DISubroutineType *Type = getSubroutineType();
+ bool IsLocalToUnit = false;
+ bool IsDefinition = true;
+ unsigned ScopeLine = 3;
+ DITypeRef ContainingType = getCompositeType();
+ unsigned Virtuality = 4;
+ unsigned VirtualIndex = 5;
+ unsigned Flags = 6;
+ bool IsOptimized = false;
+ MDTuple *TemplateParams = getTuple();
+ DISubprogram *Declaration = getSubprogram();
+ MDTuple *Variables = getTuple();
+
+ auto *N = DISubprogram::get(
+ Context, Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
+ IsDefinition, ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags,
+ IsOptimized, TemplateParams, Declaration, Variables);
+
+ EXPECT_EQ(dwarf::DW_TAG_subprogram, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(LinkageName, N->getLinkageName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
+ EXPECT_EQ(IsDefinition, N->isDefinition());
+ EXPECT_EQ(ScopeLine, N->getScopeLine());
+ EXPECT_EQ(ContainingType, N->getContainingType());
+ EXPECT_EQ(Virtuality, N->getVirtuality());
+ EXPECT_EQ(VirtualIndex, N->getVirtualIndex());
+ EXPECT_EQ(Flags, N->getFlags());
+ EXPECT_EQ(IsOptimized, N->isOptimized());
+ EXPECT_EQ(TemplateParams, N->getTemplateParams().get());
+ EXPECT_EQ(Declaration, N->getDeclaration());
+ EXPECT_EQ(Variables, N->getVariables().get());
+ EXPECT_EQ(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+
+ EXPECT_NE(N, DISubprogram::get(Context, getCompositeType(), Name, LinkageName,
+ File, Line, Type, IsLocalToUnit, IsDefinition,
+ ScopeLine, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, "other", LinkageName, File,
+ Line, Type, IsLocalToUnit, IsDefinition,
+ ScopeLine, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, "other", File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, getFile(),
+ Line, Type, IsLocalToUnit, IsDefinition,
+ ScopeLine, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File,
+ Line + 1, Type, IsLocalToUnit, IsDefinition,
+ ScopeLine, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ getSubroutineType(), IsLocalToUnit,
+ IsDefinition, ScopeLine, ContainingType,
+ Virtuality, VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, !IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, !IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition,
+ ScopeLine + 1, ContainingType, Virtuality,
+ VirtualIndex, Flags, IsOptimized,
+ TemplateParams, Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ getCompositeType(), Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality + 1, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex + 1,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ ~Flags, IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, !IsOptimized, TemplateParams,
+ Declaration, Variables));
+ EXPECT_NE(N,
+ DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex, Flags,
+ IsOptimized, getTuple(), Declaration, Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ getSubprogram(), Variables));
+ EXPECT_NE(N, DISubprogram::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, ScopeLine,
+ ContainingType, Virtuality, VirtualIndex,
+ Flags, IsOptimized, TemplateParams,
+ Declaration, getTuple()));
+
+ TempDISubprogram Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DILexicalBlockTest;
+
+TEST_F(DILexicalBlockTest, get) {
+ DILocalScope *Scope = getSubprogram();
+ DIFile *File = getFile();
+ unsigned Line = 5;
+ unsigned Column = 8;
+
+ auto *N = DILexicalBlock::get(Context, Scope, File, Line, Column);
+
+ EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Column, N->getColumn());
+ EXPECT_EQ(N, DILexicalBlock::get(Context, Scope, File, Line, Column));
+
+ EXPECT_NE(N,
+ DILexicalBlock::get(Context, getSubprogram(), File, Line, Column));
+ EXPECT_NE(N, DILexicalBlock::get(Context, Scope, getFile(), Line, Column));
+ EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line + 1, Column));
+ EXPECT_NE(N, DILexicalBlock::get(Context, Scope, File, Line, Column + 1));
+
+ TempDILexicalBlock Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DILexicalBlockTest, Overflow) {
+ DISubprogram *SP = getSubprogram();
+ DIFile *F = getFile();
+ {
+ auto *LB = DILexicalBlock::get(Context, SP, F, 2, 7);
+ EXPECT_EQ(2u, LB->getLine());
+ EXPECT_EQ(7u, LB->getColumn());
+ }
+ unsigned U16 = 1u << 16;
+ {
+ auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16 - 1);
+ EXPECT_EQ(UINT32_MAX, LB->getLine());
+ EXPECT_EQ(U16 - 1, LB->getColumn());
+ }
+ {
+ auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16);
+ EXPECT_EQ(UINT32_MAX, LB->getLine());
+ EXPECT_EQ(0u, LB->getColumn());
+ }
+ {
+ auto *LB = DILexicalBlock::get(Context, SP, F, UINT32_MAX, U16 + 1);
+ EXPECT_EQ(UINT32_MAX, LB->getLine());
+ EXPECT_EQ(0u, LB->getColumn());
+ }
+}
+
+typedef MetadataTest DILexicalBlockFileTest;
+
+TEST_F(DILexicalBlockFileTest, get) {
+ DILocalScope *Scope = getSubprogram();
+ DIFile *File = getFile();
+ unsigned Discriminator = 5;
+
+ auto *N = DILexicalBlockFile::get(Context, Scope, File, Discriminator);
+
+ EXPECT_EQ(dwarf::DW_TAG_lexical_block, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Discriminator, N->getDiscriminator());
+ EXPECT_EQ(N, DILexicalBlockFile::get(Context, Scope, File, Discriminator));
+
+ EXPECT_NE(N, DILexicalBlockFile::get(Context, getSubprogram(), File,
+ Discriminator));
+ EXPECT_NE(N,
+ DILexicalBlockFile::get(Context, Scope, getFile(), Discriminator));
+ EXPECT_NE(N,
+ DILexicalBlockFile::get(Context, Scope, File, Discriminator + 1));
+
+ TempDILexicalBlockFile Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DINamespaceTest;
+
+TEST_F(DINamespaceTest, get) {
+ DIScope *Scope = getFile();
+ DIFile *File = getFile();
+ StringRef Name = "namespace";
+ unsigned Line = 5;
+
+ auto *N = DINamespace::get(Context, Scope, File, Name, Line);
+
+ EXPECT_EQ(dwarf::DW_TAG_namespace, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(N, DINamespace::get(Context, Scope, File, Name, Line));
+
+ EXPECT_NE(N, DINamespace::get(Context, getFile(), File, Name, Line));
+ EXPECT_NE(N, DINamespace::get(Context, Scope, getFile(), Name, Line));
+ EXPECT_NE(N, DINamespace::get(Context, Scope, File, "other", Line));
+ EXPECT_NE(N, DINamespace::get(Context, Scope, File, Name, Line + 1));
+
+ TempDINamespace Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DIModuleTest;
+
+TEST_F(DIModuleTest, get) {
+ DIScope *Scope = getFile();
+ StringRef Name = "module";
+ StringRef ConfigMacro = "-DNDEBUG";
+ StringRef Includes = "-I.";
+ StringRef Sysroot = "/";
+
+ auto *N = DIModule::get(Context, Scope, Name, ConfigMacro, Includes, Sysroot);
+
+ EXPECT_EQ(dwarf::DW_TAG_module, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(ConfigMacro, N->getConfigurationMacros());
+ EXPECT_EQ(Includes, N->getIncludePath());
+ EXPECT_EQ(Sysroot, N->getISysRoot());
+ EXPECT_EQ(N, DIModule::get(Context, Scope, Name,
+ ConfigMacro, Includes, Sysroot));
+ EXPECT_NE(N, DIModule::get(Context, getFile(), Name,
+ ConfigMacro, Includes, Sysroot));
+ EXPECT_NE(N, DIModule::get(Context, Scope, "other",
+ ConfigMacro, Includes, Sysroot));
+ EXPECT_NE(N, DIModule::get(Context, Scope, Name,
+ "other", Includes, Sysroot));
+ EXPECT_NE(N, DIModule::get(Context, Scope, Name,
+ ConfigMacro, "other", Sysroot));
+ EXPECT_NE(N, DIModule::get(Context, Scope, Name,
+ ConfigMacro, Includes, "other"));
+
+ TempDIModule Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DITemplateTypeParameterTest;
+
+TEST_F(DITemplateTypeParameterTest, get) {
+ StringRef Name = "template";
+ DITypeRef Type = getBasicType("basic");
+
+ auto *N = DITemplateTypeParameter::get(Context, Name, Type);
+
+ EXPECT_EQ(dwarf::DW_TAG_template_type_parameter, N->getTag());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(N, DITemplateTypeParameter::get(Context, Name, Type));
+
+ EXPECT_NE(N, DITemplateTypeParameter::get(Context, "other", Type));
+ EXPECT_NE(N,
+ DITemplateTypeParameter::get(Context, Name, getBasicType("other")));
+
+ TempDITemplateTypeParameter Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DITemplateValueParameterTest;
+
+TEST_F(DITemplateValueParameterTest, get) {
+ unsigned Tag = dwarf::DW_TAG_template_value_parameter;
+ StringRef Name = "template";
+ DITypeRef Type = getBasicType("basic");
+ Metadata *Value = getConstantAsMetadata();
+
+ auto *N = DITemplateValueParameter::get(Context, Tag, Name, Type, Value);
+ EXPECT_EQ(Tag, N->getTag());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(Value, N->getValue());
+ EXPECT_EQ(N, DITemplateValueParameter::get(Context, Tag, Name, Type, Value));
+
+ EXPECT_NE(N, DITemplateValueParameter::get(
+ Context, dwarf::DW_TAG_GNU_template_template_param, Name,
+ Type, Value));
+ EXPECT_NE(N,
+ DITemplateValueParameter::get(Context, Tag, "other", Type, Value));
+ EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name,
+ getBasicType("other"), Value));
+ EXPECT_NE(N, DITemplateValueParameter::get(Context, Tag, Name, Type,
+ getConstantAsMetadata()));
+
+ TempDITemplateValueParameter Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DIGlobalVariableTest;
+
+TEST_F(DIGlobalVariableTest, get) {
+ DIScope *Scope = getSubprogram();
+ StringRef Name = "name";
+ StringRef LinkageName = "linkage";
+ DIFile *File = getFile();
+ unsigned Line = 5;
+ DITypeRef Type = getDerivedType();
+ bool IsLocalToUnit = false;
+ bool IsDefinition = true;
+ Constant *Variable = getConstant();
+ DIDerivedType *StaticDataMemberDeclaration =
+ cast<DIDerivedType>(getDerivedType());
+
+ auto *N = DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, Variable,
+ StaticDataMemberDeclaration);
+ EXPECT_EQ(dwarf::DW_TAG_variable, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(LinkageName, N->getLinkageName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(IsLocalToUnit, N->isLocalToUnit());
+ EXPECT_EQ(IsDefinition, N->isDefinition());
+ EXPECT_EQ(Variable, N->getVariable());
+ EXPECT_EQ(StaticDataMemberDeclaration, N->getStaticDataMemberDeclaration());
+ EXPECT_EQ(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+ Line, Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, getSubprogram(), Name, LinkageName,
+ File, Line, Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, "other", LinkageName, File,
+ Line, Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, "other", File, Line,
+ Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, Scope, Name, LinkageName, getFile(),
+ Line, Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+ Line + 1, Type, IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line,
+ getDerivedType(), IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+ Line, Type, !IsLocalToUnit, IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N, DIGlobalVariable::get(Context, Scope, Name, LinkageName, File,
+ Line, Type, IsLocalToUnit, !IsDefinition,
+ Variable, StaticDataMemberDeclaration));
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition,
+ getConstant(), StaticDataMemberDeclaration));
+ EXPECT_NE(N,
+ DIGlobalVariable::get(Context, Scope, Name, LinkageName, File, Line,
+ Type, IsLocalToUnit, IsDefinition, Variable,
+ cast<DIDerivedType>(getDerivedType())));
+
+ TempDIGlobalVariable Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DILocalVariableTest;
+
+TEST_F(DILocalVariableTest, get) {
+ DILocalScope *Scope = getSubprogram();
+ StringRef Name = "name";
+ DIFile *File = getFile();
+ unsigned Line = 5;
+ DITypeRef Type = getDerivedType();
+ unsigned Arg = 6;
+ unsigned Flags = 7;
+
+ auto *N =
+ DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg, Flags);
+ EXPECT_TRUE(N->isParameter());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(Arg, N->getArg());
+ EXPECT_EQ(Flags, N->getFlags());
+ EXPECT_EQ(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg,
+ Flags));
+
+ EXPECT_FALSE(
+ DILocalVariable::get(Context, Scope, Name, File, Line, Type, 0, Flags)
+ ->isParameter());
+ EXPECT_NE(N, DILocalVariable::get(Context, getSubprogram(), Name, File, Line,
+ Type, Arg, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, "other", File, Line, Type,
+ Arg, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, getFile(), Line, Type,
+ Arg, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line + 1, Type,
+ Arg, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line,
+ getDerivedType(), Arg, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type,
+ Arg + 1, Flags));
+ EXPECT_NE(N, DILocalVariable::get(Context, Scope, Name, File, Line, Type, Arg,
+ ~Flags));
+
+ TempDILocalVariable Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DILocalVariableTest, getArg256) {
+ EXPECT_EQ(255u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
+ 0, nullptr, 255, 0)
+ ->getArg());
+ EXPECT_EQ(256u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
+ 0, nullptr, 256, 0)
+ ->getArg());
+ EXPECT_EQ(257u, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
+ 0, nullptr, 257, 0)
+ ->getArg());
+ unsigned Max = UINT16_MAX;
+ EXPECT_EQ(Max, DILocalVariable::get(Context, getSubprogram(), "", getFile(),
+ 0, nullptr, Max, 0)
+ ->getArg());
+}
+
+typedef MetadataTest DIExpressionTest;
+
+TEST_F(DIExpressionTest, get) {
+ uint64_t Elements[] = {2, 6, 9, 78, 0};
+ auto *N = DIExpression::get(Context, Elements);
+ EXPECT_EQ(makeArrayRef(Elements), N->getElements());
+ EXPECT_EQ(N, DIExpression::get(Context, Elements));
+
+ EXPECT_EQ(5u, N->getNumElements());
+ EXPECT_EQ(2u, N->getElement(0));
+ EXPECT_EQ(6u, N->getElement(1));
+ EXPECT_EQ(9u, N->getElement(2));
+ EXPECT_EQ(78u, N->getElement(3));
+ EXPECT_EQ(0u, N->getElement(4));
+
+ TempDIExpression Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+TEST_F(DIExpressionTest, isValid) {
+#define EXPECT_VALID(...) \
+ do { \
+ uint64_t Elements[] = {__VA_ARGS__}; \
+ EXPECT_TRUE(DIExpression::get(Context, Elements)->isValid()); \
+ } while (false)
+#define EXPECT_INVALID(...) \
+ do { \
+ uint64_t Elements[] = {__VA_ARGS__}; \
+ EXPECT_FALSE(DIExpression::get(Context, Elements)->isValid()); \
+ } while (false)
+
+ // Empty expression should be valid.
+ EXPECT_TRUE(DIExpression::get(Context, None));
+
+ // Valid constructions.
+ EXPECT_VALID(dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_plus, 6, dwarf::DW_OP_deref);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_bit_piece, 3, 7);
+ EXPECT_VALID(dwarf::DW_OP_deref, dwarf::DW_OP_plus, 6, dwarf::DW_OP_bit_piece, 3, 7);
+
+ // Invalid constructions.
+ EXPECT_INVALID(~0u);
+ EXPECT_INVALID(dwarf::DW_OP_plus);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_plus, 3);
+ EXPECT_INVALID(dwarf::DW_OP_bit_piece, 3, 7, dwarf::DW_OP_deref);
+
+#undef EXPECT_VALID
+#undef EXPECT_INVALID
+}
+
+typedef MetadataTest DIObjCPropertyTest;
+
+TEST_F(DIObjCPropertyTest, get) {
+ StringRef Name = "name";
+ DIFile *File = getFile();
+ unsigned Line = 5;
+ StringRef GetterName = "getter";
+ StringRef SetterName = "setter";
+ unsigned Attributes = 7;
+ DITypeRef Type = getBasicType("basic");
+
+ auto *N = DIObjCProperty::get(Context, Name, File, Line, GetterName,
+ SetterName, Attributes, Type);
+
+ EXPECT_EQ(dwarf::DW_TAG_APPLE_property, N->getTag());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(File, N->getFile());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(GetterName, N->getGetterName());
+ EXPECT_EQ(SetterName, N->getSetterName());
+ EXPECT_EQ(Attributes, N->getAttributes());
+ EXPECT_EQ(Type, N->getType());
+ EXPECT_EQ(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
+ SetterName, Attributes, Type));
+
+ EXPECT_NE(N, DIObjCProperty::get(Context, "other", File, Line, GetterName,
+ SetterName, Attributes, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, getFile(), Line, GetterName,
+ SetterName, Attributes, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line + 1, GetterName,
+ SetterName, Attributes, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, "other",
+ SetterName, Attributes, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
+ "other", Attributes, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
+ SetterName, Attributes + 1, Type));
+ EXPECT_NE(N, DIObjCProperty::get(Context, Name, File, Line, GetterName,
+ SetterName, Attributes,
+ getBasicType("other")));
+
+ TempDIObjCProperty Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest DIImportedEntityTest;
+
+TEST_F(DIImportedEntityTest, get) {
+ unsigned Tag = dwarf::DW_TAG_imported_module;
+ DIScope *Scope = getSubprogram();
+ DINodeRef Entity = getCompositeType();
+ unsigned Line = 5;
+ StringRef Name = "name";
+
+ auto *N = DIImportedEntity::get(Context, Tag, Scope, Entity, Line, Name);
+
+ EXPECT_EQ(Tag, N->getTag());
+ EXPECT_EQ(Scope, N->getScope());
+ EXPECT_EQ(Entity, N->getEntity());
+ EXPECT_EQ(Line, N->getLine());
+ EXPECT_EQ(Name, N->getName());
+ EXPECT_EQ(N, DIImportedEntity::get(Context, Tag, Scope, Entity, Line, Name));
+
+ EXPECT_NE(N,
+ DIImportedEntity::get(Context, dwarf::DW_TAG_imported_declaration,
+ Scope, Entity, Line, Name));
+ EXPECT_NE(N, DIImportedEntity::get(Context, Tag, getSubprogram(), Entity,
+ Line, Name));
+ EXPECT_NE(N, DIImportedEntity::get(Context, Tag, Scope, getCompositeType(),
+ Line, Name));
+ EXPECT_NE(N,
+ DIImportedEntity::get(Context, Tag, Scope, Entity, Line + 1, Name));
+ EXPECT_NE(N,
+ DIImportedEntity::get(Context, Tag, Scope, Entity, Line, "other"));
+
+ TempDIImportedEntity Temp = N->clone();
+ EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
+}
+
+typedef MetadataTest MetadataAsValueTest;
+
+TEST_F(MetadataAsValueTest, MDNode) {
+ MDNode *N = MDNode::get(Context, None);
+ auto *V = MetadataAsValue::get(Context, N);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(N, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N);
+ EXPECT_EQ(V, V2);
+}
+
+TEST_F(MetadataAsValueTest, MDNodeMDNode) {
+ MDNode *N = MDNode::get(Context, None);
+ Metadata *Ops[] = {N};
+ MDNode *N2 = MDNode::get(Context, Ops);
+ auto *V = MetadataAsValue::get(Context, N2);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(N2, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N2);
+ EXPECT_EQ(V, V2);
+
+ auto *V3 = MetadataAsValue::get(Context, N);
+ EXPECT_TRUE(V3->getType()->isMetadataTy());
+ EXPECT_NE(V, V3);
+ EXPECT_EQ(N, V3->getMetadata());
+}
+
+TEST_F(MetadataAsValueTest, MDNodeConstant) {
+ auto *C = ConstantInt::getTrue(Context);
+ auto *MD = ConstantAsMetadata::get(C);
+ Metadata *Ops[] = {MD};
+ auto *N = MDNode::get(Context, Ops);
+
+ auto *V = MetadataAsValue::get(Context, MD);
+ EXPECT_TRUE(V->getType()->isMetadataTy());
+ EXPECT_EQ(MD, V->getMetadata());
+
+ auto *V2 = MetadataAsValue::get(Context, N);
+ EXPECT_EQ(MD, V2->getMetadata());
+ EXPECT_EQ(V, V2);
+}
+
+typedef MetadataTest ValueAsMetadataTest;
+
+TEST_F(ValueAsMetadataTest, UpdatesOnRAUW) {
+ Type *Ty = Type::getInt1PtrTy(Context);
+ std::unique_ptr<GlobalVariable> GV0(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ auto *MD = ValueAsMetadata::get(GV0.get());
+ EXPECT_TRUE(MD->getValue() == GV0.get());
+ ASSERT_TRUE(GV0->use_empty());
+
+ std::unique_ptr<GlobalVariable> GV1(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ GV0->replaceAllUsesWith(GV1.get());
+ EXPECT_TRUE(MD->getValue() == GV1.get());
+}
+
+TEST_F(ValueAsMetadataTest, CollidingDoubleUpdates) {
+ // Create a constant.
+ ConstantAsMetadata *CI = ConstantAsMetadata::get(
+ ConstantInt::get(getGlobalContext(), APInt(8, 0)));
+
+ // Create a temporary to prevent nodes from resolving.
+ auto Temp = MDTuple::getTemporary(Context, None);
+
+ // When the first operand of N1 gets reset to nullptr, it'll collide with N2.
+ Metadata *Ops1[] = {CI, CI, Temp.get()};
+ Metadata *Ops2[] = {nullptr, CI, Temp.get()};
+
+ auto *N1 = MDTuple::get(Context, Ops1);
+ auto *N2 = MDTuple::get(Context, Ops2);
+ ASSERT_NE(N1, N2);
+
+ // Tell metadata that the constant is getting deleted.
+ //
+ // After this, N1 will be invalid, so don't touch it.
+ ValueAsMetadata::handleDeletion(CI->getValue());
+ EXPECT_EQ(nullptr, N2->getOperand(0));
+ EXPECT_EQ(nullptr, N2->getOperand(1));
+ EXPECT_EQ(Temp.get(), N2->getOperand(2));
+
+ // Clean up Temp for teardown.
+ Temp->replaceAllUsesWith(nullptr);
+}
+
+typedef MetadataTest TrackingMDRefTest;
+
+TEST_F(TrackingMDRefTest, UpdatesOnRAUW) {
+ Type *Ty = Type::getInt1PtrTy(Context);
+ std::unique_ptr<GlobalVariable> GV0(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV0.get()));
+ EXPECT_TRUE(MD->getValue() == GV0.get());
+ ASSERT_TRUE(GV0->use_empty());
+
+ std::unique_ptr<GlobalVariable> GV1(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ GV0->replaceAllUsesWith(GV1.get());
+ EXPECT_TRUE(MD->getValue() == GV1.get());
+
+ // Reset it, so we don't inadvertently test deletion.
+ MD.reset();
+}
+
+TEST_F(TrackingMDRefTest, UpdatesOnDeletion) {
+ Type *Ty = Type::getInt1PtrTy(Context);
+ std::unique_ptr<GlobalVariable> GV(
+ new GlobalVariable(Ty, false, GlobalValue::ExternalLinkage));
+ TypedTrackingMDRef<ValueAsMetadata> MD(ValueAsMetadata::get(GV.get()));
+ EXPECT_TRUE(MD->getValue() == GV.get());
+ ASSERT_TRUE(GV->use_empty());
+
+ GV.reset();
+ EXPECT_TRUE(!MD);
+}
+
+TEST(NamedMDNodeTest, Search) {
+ LLVMContext Context;
+ ConstantAsMetadata *C =
+ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 1));
+ ConstantAsMetadata *C2 =
+ ConstantAsMetadata::get(ConstantInt::get(Type::getInt32Ty(Context), 2));
+
+ Metadata *const V = C;
+ Metadata *const V2 = C2;
+ MDNode *n = MDNode::get(Context, V);
+ MDNode *n2 = MDNode::get(Context, V2);
+
+ Module M("MyModule", Context);
+ const char *Name = "llvm.NMD1";
+ NamedMDNode *NMD = M.getOrInsertNamedMetadata(Name);
+ NMD->addOperand(n);
+ NMD->addOperand(n2);
+
+ std::string Str;
+ raw_string_ostream oss(Str);
+ NMD->print(oss);
+ EXPECT_STREQ("!llvm.NMD1 = !{!0, !1}\n",
+ oss.str().c_str());
+}
+
+typedef MetadataTest FunctionAttachmentTest;
+TEST_F(FunctionAttachmentTest, setMetadata) {
+ Function *F = getFunction("foo");
+ ASSERT_FALSE(F->hasMetadata());
+ EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));
+ EXPECT_EQ(nullptr, F->getMetadata("dbg"));
+ EXPECT_EQ(nullptr, F->getMetadata("other"));
+
+ DISubprogram *SP1 = getSubprogram();
+ DISubprogram *SP2 = getSubprogram();
+ ASSERT_NE(SP1, SP2);
+
+ F->setMetadata("dbg", SP1);
+ EXPECT_TRUE(F->hasMetadata());
+ EXPECT_EQ(SP1, F->getMetadata(LLVMContext::MD_dbg));
+ EXPECT_EQ(SP1, F->getMetadata("dbg"));
+ EXPECT_EQ(nullptr, F->getMetadata("other"));
+
+ F->setMetadata(LLVMContext::MD_dbg, SP2);
+ EXPECT_TRUE(F->hasMetadata());
+ EXPECT_EQ(SP2, F->getMetadata(LLVMContext::MD_dbg));
+ EXPECT_EQ(SP2, F->getMetadata("dbg"));
+ EXPECT_EQ(nullptr, F->getMetadata("other"));
+
+ F->setMetadata("dbg", nullptr);
+ EXPECT_FALSE(F->hasMetadata());
+ EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));
+ EXPECT_EQ(nullptr, F->getMetadata("dbg"));
+ EXPECT_EQ(nullptr, F->getMetadata("other"));
+
+ MDTuple *T1 = getTuple();
+ MDTuple *T2 = getTuple();
+ ASSERT_NE(T1, T2);
+
+ F->setMetadata("other1", T1);
+ F->setMetadata("other2", T2);
+ EXPECT_TRUE(F->hasMetadata());
+ EXPECT_EQ(T1, F->getMetadata("other1"));
+ EXPECT_EQ(T2, F->getMetadata("other2"));
+ EXPECT_EQ(nullptr, F->getMetadata("dbg"));
+
+ F->setMetadata("other1", T2);
+ F->setMetadata("other2", T1);
+ EXPECT_EQ(T2, F->getMetadata("other1"));
+ EXPECT_EQ(T1, F->getMetadata("other2"));
+
+ F->setMetadata("other1", nullptr);
+ F->setMetadata("other2", nullptr);
+ EXPECT_FALSE(F->hasMetadata());
+ EXPECT_EQ(nullptr, F->getMetadata("other1"));
+ EXPECT_EQ(nullptr, F->getMetadata("other2"));
+}
+
+TEST_F(FunctionAttachmentTest, getAll) {
+ Function *F = getFunction("foo");
+
+ MDTuple *T1 = getTuple();
+ MDTuple *T2 = getTuple();
+ MDTuple *P = getTuple();
+ DISubprogram *SP = getSubprogram();
+
+ F->setMetadata("other1", T2);
+ F->setMetadata(LLVMContext::MD_dbg, SP);
+ F->setMetadata("other2", T1);
+ F->setMetadata(LLVMContext::MD_prof, P);
+ F->setMetadata("other2", T2);
+ F->setMetadata("other1", T1);
+
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDs;
+ F->getAllMetadata(MDs);
+ ASSERT_EQ(4u, MDs.size());
+ EXPECT_EQ(LLVMContext::MD_dbg, MDs[0].first);
+ EXPECT_EQ(LLVMContext::MD_prof, MDs[1].first);
+ EXPECT_EQ(Context.getMDKindID("other1"), MDs[2].first);
+ EXPECT_EQ(Context.getMDKindID("other2"), MDs[3].first);
+ EXPECT_EQ(SP, MDs[0].second);
+ EXPECT_EQ(P, MDs[1].second);
+ EXPECT_EQ(T1, MDs[2].second);
+ EXPECT_EQ(T2, MDs[3].second);
+}
+
+TEST_F(FunctionAttachmentTest, dropUnknownMetadata) {
+ Function *F = getFunction("foo");
+
+ MDTuple *T1 = getTuple();
+ MDTuple *T2 = getTuple();
+ MDTuple *P = getTuple();
+ DISubprogram *SP = getSubprogram();
+
+ F->setMetadata("other1", T1);
+ F->setMetadata(LLVMContext::MD_dbg, SP);
+ F->setMetadata("other2", T2);
+ F->setMetadata(LLVMContext::MD_prof, P);
+
+ unsigned Known[] = {Context.getMDKindID("other2"), LLVMContext::MD_prof};
+ F->dropUnknownMetadata(Known);
+
+ EXPECT_EQ(T2, F->getMetadata("other2"));
+ EXPECT_EQ(P, F->getMetadata(LLVMContext::MD_prof));
+ EXPECT_EQ(nullptr, F->getMetadata("other1"));
+ EXPECT_EQ(nullptr, F->getMetadata(LLVMContext::MD_dbg));
+
+ F->setMetadata("other2", nullptr);
+ F->setMetadata(LLVMContext::MD_prof, nullptr);
+ EXPECT_FALSE(F->hasMetadata());
+}
+
+TEST_F(FunctionAttachmentTest, Verifier) {
+ Function *F = getFunction("foo");
+ F->setMetadata("attach", getTuple());
+
+ // Confirm this has no body.
+ ASSERT_TRUE(F->empty());
+
+ // Functions without a body cannot have metadata attachments (they also can't
+ // be verified directly, so check that the module fails to verify).
+ EXPECT_TRUE(verifyModule(*F->getParent()));
+
+ // Functions with a body can.
+ (void)new UnreachableInst(Context, BasicBlock::Create(Context, "bb", F));
+ EXPECT_FALSE(verifyModule(*F->getParent()));
+ EXPECT_FALSE(verifyFunction(*F));
+}
+
+TEST_F(FunctionAttachmentTest, EntryCount) {
+ Function *F = getFunction("foo");
+ EXPECT_FALSE(F->getEntryCount().hasValue());
+ F->setEntryCount(12304);
+ EXPECT_TRUE(F->getEntryCount().hasValue());
+ EXPECT_EQ(12304u, *F->getEntryCount());
+}
+
+TEST_F(FunctionAttachmentTest, SubprogramAttachment) {
+ Function *F = getFunction("foo");
+ DISubprogram *SP = getSubprogram();
+ F->setSubprogram(SP);
+
+ // Note that the static_cast confirms that F->getSubprogram() actually
+ // returns an DISubprogram.
+ EXPECT_EQ(SP, static_cast<DISubprogram *>(F->getSubprogram()));
+ EXPECT_EQ(SP, F->getMetadata("dbg"));
+ EXPECT_EQ(SP, F->getMetadata(LLVMContext::MD_dbg));
+}
+
+}
diff --git a/gnu/llvm/unittests/IR/PassManagerTest.cpp b/gnu/llvm/unittests/IR/PassManagerTest.cpp
new file mode 100644
index 00000000000..41af0b0bd25
--- /dev/null
+++ b/gnu/llvm/unittests/IR/PassManagerTest.cpp
@@ -0,0 +1,349 @@
+//===- llvm/unittest/IR/PassManager.cpp - PassManager tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class TestFunctionAnalysis {
+public:
+ struct Result {
+ Result(int Count) : InstructionCount(Count) {}
+ int InstructionCount;
+ };
+
+ /// \brief Returns an opaque, unique ID for this pass type.
+ static void *ID() { return (void *)&PassID; }
+
+ /// \brief Returns the name of the analysis.
+ static StringRef name() { return "TestFunctionAnalysis"; }
+
+ TestFunctionAnalysis(int &Runs) : Runs(Runs) {}
+
+ /// \brief Run the analysis pass over the function and return a result.
+ Result run(Function &F, FunctionAnalysisManager *AM) {
+ ++Runs;
+ int Count = 0;
+ for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI)
+ for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE;
+ ++II)
+ ++Count;
+ return Result(Count);
+ }
+
+private:
+ /// \brief Private static data to provide unique ID.
+ static char PassID;
+
+ int &Runs;
+};
+
+char TestFunctionAnalysis::PassID;
+
+class TestModuleAnalysis {
+public:
+ struct Result {
+ Result(int Count) : FunctionCount(Count) {}
+ int FunctionCount;
+ };
+
+ static void *ID() { return (void *)&PassID; }
+
+ static StringRef name() { return "TestModuleAnalysis"; }
+
+ TestModuleAnalysis(int &Runs) : Runs(Runs) {}
+
+ Result run(Module &M, ModuleAnalysisManager *AM) {
+ ++Runs;
+ int Count = 0;
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ ++Count;
+ return Result(Count);
+ }
+
+private:
+ static char PassID;
+
+ int &Runs;
+};
+
+char TestModuleAnalysis::PassID;
+
+struct TestModulePass {
+ TestModulePass(int &RunCount) : RunCount(RunCount) {}
+
+ PreservedAnalyses run(Module &M) {
+ ++RunCount;
+ return PreservedAnalyses::none();
+ }
+
+ static StringRef name() { return "TestModulePass"; }
+
+ int &RunCount;
+};
+
+struct TestPreservingModulePass {
+ PreservedAnalyses run(Module &M) { return PreservedAnalyses::all(); }
+
+ static StringRef name() { return "TestPreservingModulePass"; }
+};
+
+struct TestMinPreservingModulePass {
+ PreservedAnalyses run(Module &M, ModuleAnalysisManager *AM) {
+ PreservedAnalyses PA;
+
+ // Force running an analysis.
+ (void)AM->getResult<TestModuleAnalysis>(M);
+
+ PA.preserve<FunctionAnalysisManagerModuleProxy>();
+ return PA;
+ }
+
+ static StringRef name() { return "TestMinPreservingModulePass"; }
+};
+
+struct TestFunctionPass {
+ TestFunctionPass(int &RunCount, int &AnalyzedInstrCount,
+ int &AnalyzedFunctionCount,
+ bool OnlyUseCachedResults = false)
+ : RunCount(RunCount), AnalyzedInstrCount(AnalyzedInstrCount),
+ AnalyzedFunctionCount(AnalyzedFunctionCount),
+ OnlyUseCachedResults(OnlyUseCachedResults) {}
+
+ PreservedAnalyses run(Function &F, FunctionAnalysisManager *AM) {
+ ++RunCount;
+
+ const ModuleAnalysisManager &MAM =
+ AM->getResult<ModuleAnalysisManagerFunctionProxy>(F).getManager();
+ if (TestModuleAnalysis::Result *TMA =
+ MAM.getCachedResult<TestModuleAnalysis>(*F.getParent()))
+ AnalyzedFunctionCount += TMA->FunctionCount;
+
+ if (OnlyUseCachedResults) {
+ // Hack to force the use of the cached interface.
+ if (TestFunctionAnalysis::Result *AR =
+ AM->getCachedResult<TestFunctionAnalysis>(F))
+ AnalyzedInstrCount += AR->InstructionCount;
+ } else {
+ // Typical path just runs the analysis as needed.
+ TestFunctionAnalysis::Result &AR = AM->getResult<TestFunctionAnalysis>(F);
+ AnalyzedInstrCount += AR.InstructionCount;
+ }
+
+ return PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "TestFunctionPass"; }
+
+ int &RunCount;
+ int &AnalyzedInstrCount;
+ int &AnalyzedFunctionCount;
+ bool OnlyUseCachedResults;
+};
+
+// A test function pass that invalidates all function analyses for a function
+// with a specific name.
+struct TestInvalidationFunctionPass {
+ TestInvalidationFunctionPass(StringRef FunctionName) : Name(FunctionName) {}
+
+ PreservedAnalyses run(Function &F) {
+ return F.getName() == Name ? PreservedAnalyses::none()
+ : PreservedAnalyses::all();
+ }
+
+ static StringRef name() { return "TestInvalidationFunctionPass"; }
+
+ StringRef Name;
+};
+
+std::unique_ptr<Module> parseIR(const char *IR) {
+ LLVMContext &C = getGlobalContext();
+ SMDiagnostic Err;
+ return parseAssemblyString(IR, Err, C);
+}
+
+class PassManagerTest : public ::testing::Test {
+protected:
+ std::unique_ptr<Module> M;
+
+public:
+ PassManagerTest()
+ : M(parseIR("define void @f() {\n"
+ "entry:\n"
+ " call void @g()\n"
+ " call void @h()\n"
+ " ret void\n"
+ "}\n"
+ "define void @g() {\n"
+ " ret void\n"
+ "}\n"
+ "define void @h() {\n"
+ " ret void\n"
+ "}\n")) {}
+};
+
+TEST_F(PassManagerTest, BasicPreservedAnalyses) {
+ PreservedAnalyses PA1 = PreservedAnalyses();
+ EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
+ PreservedAnalyses PA2 = PreservedAnalyses::none();
+ EXPECT_FALSE(PA2.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA2.preserved<TestModuleAnalysis>());
+ PreservedAnalyses PA3 = PreservedAnalyses::all();
+ EXPECT_TRUE(PA3.preserved<TestFunctionAnalysis>());
+ EXPECT_TRUE(PA3.preserved<TestModuleAnalysis>());
+ PreservedAnalyses PA4 = PA1;
+ EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
+ PA4 = PA3;
+ EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
+ EXPECT_TRUE(PA4.preserved<TestModuleAnalysis>());
+ PA4 = std::move(PA2);
+ EXPECT_FALSE(PA4.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
+ PA4.preserve<TestFunctionAnalysis>();
+ EXPECT_TRUE(PA4.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA4.preserved<TestModuleAnalysis>());
+ PA1.preserve<TestModuleAnalysis>();
+ EXPECT_FALSE(PA1.preserved<TestFunctionAnalysis>());
+ EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
+ PA1.preserve<TestFunctionAnalysis>();
+ EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
+ EXPECT_TRUE(PA1.preserved<TestModuleAnalysis>());
+ PA1.intersect(PA4);
+ EXPECT_TRUE(PA1.preserved<TestFunctionAnalysis>());
+ EXPECT_FALSE(PA1.preserved<TestModuleAnalysis>());
+}
+
+TEST_F(PassManagerTest, Basic) {
+ FunctionAnalysisManager FAM;
+ int FunctionAnalysisRuns = 0;
+ FAM.registerPass(TestFunctionAnalysis(FunctionAnalysisRuns));
+
+ ModuleAnalysisManager MAM;
+ int ModuleAnalysisRuns = 0;
+ MAM.registerPass(TestModuleAnalysis(ModuleAnalysisRuns));
+ MAM.registerPass(FunctionAnalysisManagerModuleProxy(FAM));
+ FAM.registerPass(ModuleAnalysisManagerFunctionProxy(MAM));
+
+ ModulePassManager MPM;
+
+ // Count the runs over a Function.
+ int FunctionPassRunCount1 = 0;
+ int AnalyzedInstrCount1 = 0;
+ int AnalyzedFunctionCount1 = 0;
+ {
+ // Pointless scoped copy to test move assignment.
+ ModulePassManager NestedMPM;
+ FunctionPassManager FPM;
+ {
+ // Pointless scope to test move assignment.
+ FunctionPassManager NestedFPM;
+ NestedFPM.addPass(TestFunctionPass(FunctionPassRunCount1, AnalyzedInstrCount1,
+ AnalyzedFunctionCount1));
+ FPM = std::move(NestedFPM);
+ }
+ NestedMPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ MPM = std::move(NestedMPM);
+ }
+
+ // Count the runs over a module.
+ int ModulePassRunCount = 0;
+ MPM.addPass(TestModulePass(ModulePassRunCount));
+
+ // Count the runs over a Function in a separate manager.
+ int FunctionPassRunCount2 = 0;
+ int AnalyzedInstrCount2 = 0;
+ int AnalyzedFunctionCount2 = 0;
+ {
+ FunctionPassManager FPM;
+ FPM.addPass(TestFunctionPass(FunctionPassRunCount2, AnalyzedInstrCount2,
+ AnalyzedFunctionCount2));
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+
+ // A third function pass manager but with only preserving intervening passes
+ // and with a function pass that invalidates exactly one analysis.
+ MPM.addPass(TestPreservingModulePass());
+ int FunctionPassRunCount3 = 0;
+ int AnalyzedInstrCount3 = 0;
+ int AnalyzedFunctionCount3 = 0;
+ {
+ FunctionPassManager FPM;
+ FPM.addPass(TestFunctionPass(FunctionPassRunCount3, AnalyzedInstrCount3,
+ AnalyzedFunctionCount3));
+ FPM.addPass(TestInvalidationFunctionPass("f"));
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+
+ // A fourth function pass manager but with a minimal intervening passes.
+ MPM.addPass(TestMinPreservingModulePass());
+ int FunctionPassRunCount4 = 0;
+ int AnalyzedInstrCount4 = 0;
+ int AnalyzedFunctionCount4 = 0;
+ {
+ FunctionPassManager FPM;
+ FPM.addPass(TestFunctionPass(FunctionPassRunCount4, AnalyzedInstrCount4,
+ AnalyzedFunctionCount4));
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+
+ // A fifth function pass manager but which uses only cached results.
+ int FunctionPassRunCount5 = 0;
+ int AnalyzedInstrCount5 = 0;
+ int AnalyzedFunctionCount5 = 0;
+ {
+ FunctionPassManager FPM;
+ FPM.addPass(TestInvalidationFunctionPass("f"));
+ FPM.addPass(TestFunctionPass(FunctionPassRunCount5, AnalyzedInstrCount5,
+ AnalyzedFunctionCount5,
+ /*OnlyUseCachedResults=*/true));
+ MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM)));
+ }
+
+ MPM.run(*M, &MAM);
+
+ // Validate module pass counters.
+ EXPECT_EQ(1, ModulePassRunCount);
+
+ // Validate all function pass counter sets are the same.
+ EXPECT_EQ(3, FunctionPassRunCount1);
+ EXPECT_EQ(5, AnalyzedInstrCount1);
+ EXPECT_EQ(0, AnalyzedFunctionCount1);
+ EXPECT_EQ(3, FunctionPassRunCount2);
+ EXPECT_EQ(5, AnalyzedInstrCount2);
+ EXPECT_EQ(0, AnalyzedFunctionCount2);
+ EXPECT_EQ(3, FunctionPassRunCount3);
+ EXPECT_EQ(5, AnalyzedInstrCount3);
+ EXPECT_EQ(0, AnalyzedFunctionCount3);
+ EXPECT_EQ(3, FunctionPassRunCount4);
+ EXPECT_EQ(5, AnalyzedInstrCount4);
+ EXPECT_EQ(0, AnalyzedFunctionCount4);
+ EXPECT_EQ(3, FunctionPassRunCount5);
+ EXPECT_EQ(2, AnalyzedInstrCount5); // Only 'g' and 'h' were cached.
+ EXPECT_EQ(0, AnalyzedFunctionCount5);
+
+ // Validate the analysis counters:
+ // first run over 3 functions, then module pass invalidates
+ // second run over 3 functions, nothing invalidates
+ // third run over 0 functions, but 1 function invalidated
+ // fourth run over 1 function
+ EXPECT_EQ(7, FunctionAnalysisRuns);
+
+ EXPECT_EQ(1, ModuleAnalysisRuns);
+}
+}
diff --git a/gnu/llvm/unittests/IR/PatternMatch.cpp b/gnu/llvm/unittests/IR/PatternMatch.cpp
new file mode 100644
index 00000000000..f3a27b8d250
--- /dev/null
+++ b/gnu/llvm/unittests/IR/PatternMatch.cpp
@@ -0,0 +1,298 @@
+//===---- llvm/unittest/IR/PatternMatch.cpp - PatternMatch 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 "llvm/Analysis/ValueTracking.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/NoFolder.h"
+#include "llvm/IR/Operator.h"
+#include "llvm/IR/PatternMatch.h"
+#include "llvm/IR/Type.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::PatternMatch;
+
+namespace {
+
+struct PatternMatchTest : ::testing::Test {
+ LLVMContext Ctx;
+ std::unique_ptr<Module> M;
+ Function *F;
+ BasicBlock *BB;
+ IRBuilder<true, NoFolder> IRB;
+
+ PatternMatchTest()
+ : M(new Module("PatternMatchTestModule", Ctx)),
+ F(Function::Create(
+ FunctionType::get(Type::getVoidTy(Ctx), /* IsVarArg */ false),
+ Function::ExternalLinkage, "f", M.get())),
+ BB(BasicBlock::Create(Ctx, "entry", F)), IRB(BB) {}
+};
+
+TEST_F(PatternMatchTest, OneUse) {
+ // Build up a little tree of values:
+ //
+ // One = (1 + 2) + 42
+ // Two = One + 42
+ // Leaf = (Two + 8) + (Two + 13)
+ Value *One = IRB.CreateAdd(IRB.CreateAdd(IRB.getInt32(1), IRB.getInt32(2)),
+ IRB.getInt32(42));
+ Value *Two = IRB.CreateAdd(One, IRB.getInt32(42));
+ Value *Leaf = IRB.CreateAdd(IRB.CreateAdd(Two, IRB.getInt32(8)),
+ IRB.CreateAdd(Two, IRB.getInt32(13)));
+ Value *V;
+
+ EXPECT_TRUE(m_OneUse(m_Value(V)).match(One));
+ EXPECT_EQ(One, V);
+
+ EXPECT_FALSE(m_OneUse(m_Value()).match(Two));
+ EXPECT_FALSE(m_OneUse(m_Value()).match(Leaf));
+}
+
+TEST_F(PatternMatchTest, FloatingPointOrderedMin) {
+ Type *FltTy = IRB.getFloatTy();
+ Value *L = ConstantFP::get(FltTy, 1.0);
+ Value *R = ConstantFP::get(FltTy, 2.0);
+ Value *MatchL, *MatchR;
+
+ // Test OLT.
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test OLE.
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test no match on OGE.
+ EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
+
+ // Test no match on OGT.
+ EXPECT_FALSE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
+
+ // Test match on OGE with inverted select.
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test match on OGT with inverted select.
+ EXPECT_TRUE(m_OrdFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+}
+
+TEST_F(PatternMatchTest, FloatingPointOrderedMax) {
+ Type *FltTy = IRB.getFloatTy();
+ Value *L = ConstantFP::get(FltTy, 1.0);
+ Value *R = ConstantFP::get(FltTy, 2.0);
+ Value *MatchL, *MatchR;
+
+ // Test OGT.
+ EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGT(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test OGE.
+ EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOGE(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test no match on OLE.
+ EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), L, R)));
+
+ // Test no match on OLT.
+ EXPECT_FALSE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), L, R)));
+
+ // Test match on OLE with inverted select.
+ EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLE(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test match on OLT with inverted select.
+ EXPECT_TRUE(m_OrdFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpOLT(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+}
+
+TEST_F(PatternMatchTest, FloatingPointUnorderedMin) {
+ Type *FltTy = IRB.getFloatTy();
+ Value *L = ConstantFP::get(FltTy, 1.0);
+ Value *R = ConstantFP::get(FltTy, 2.0);
+ Value *MatchL, *MatchR;
+
+ // Test ULT.
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test ULE.
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test no match on UGE.
+ EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
+
+ // Test no match on UGT.
+ EXPECT_FALSE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
+
+ // Test match on UGE with inverted select.
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test match on UGT with inverted select.
+ EXPECT_TRUE(m_UnordFMin(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+}
+
+TEST_F(PatternMatchTest, FloatingPointUnorderedMax) {
+ Type *FltTy = IRB.getFloatTy();
+ Value *L = ConstantFP::get(FltTy, 1.0);
+ Value *R = ConstantFP::get(FltTy, 2.0);
+ Value *MatchL, *MatchR;
+
+ // Test UGT.
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGT(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test UGE.
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpUGE(L, R), L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test no match on ULE.
+ EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), L, R)));
+
+ // Test no match on ULT.
+ EXPECT_FALSE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), L, R)));
+
+ // Test match on ULE with inverted select.
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULE(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ // Test match on ULT with inverted select.
+ EXPECT_TRUE(m_UnordFMax(m_Value(MatchL), m_Value(MatchR))
+ .match(IRB.CreateSelect(IRB.CreateFCmpULT(L, R), R, L)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+}
+
+TEST_F(PatternMatchTest, OverflowingBinOps) {
+ Value *L = IRB.getInt32(1);
+ Value *R = IRB.getInt32(2);
+ Value *MatchL, *MatchR;
+
+ EXPECT_TRUE(
+ m_NSWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWAdd(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(
+ m_NSWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWSub(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(
+ m_NSWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNSWMul(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(m_NSWShl(m_Value(MatchL), m_Value(MatchR)).match(
+ IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ EXPECT_TRUE(
+ m_NUWAdd(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWAdd(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(
+ m_NUWSub(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWSub(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(
+ m_NUWMul(m_Value(MatchL), m_Value(MatchR)).match(IRB.CreateNUWMul(L, R)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+ MatchL = MatchR = nullptr;
+ EXPECT_TRUE(m_NUWShl(m_Value(MatchL), m_Value(MatchR)).match(
+ IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false)));
+ EXPECT_EQ(L, MatchL);
+ EXPECT_EQ(R, MatchR);
+
+ EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R)));
+ EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
+ EXPECT_FALSE(m_NSWAdd(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R)));
+ EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R)));
+ EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R)));
+ EXPECT_FALSE(m_NSWSub(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
+ EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R)));
+ EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNUWMul(L, R)));
+ EXPECT_FALSE(m_NSWMul(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
+ EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R)));
+ EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(
+ IRB.CreateShl(L, R, "", /* NUW */ true, /* NSW */ false)));
+ EXPECT_FALSE(m_NSWShl(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
+
+ EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateAdd(L, R)));
+ EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNSWAdd(L, R)));
+ EXPECT_FALSE(m_NUWAdd(m_Value(), m_Value()).match(IRB.CreateNUWSub(L, R)));
+ EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateSub(L, R)));
+ EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNSWSub(L, R)));
+ EXPECT_FALSE(m_NUWSub(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
+ EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateMul(L, R)));
+ EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNSWMul(L, R)));
+ EXPECT_FALSE(m_NUWMul(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
+ EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateShl(L, R)));
+ EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(
+ IRB.CreateShl(L, R, "", /* NUW */ false, /* NSW */ true)));
+ EXPECT_FALSE(m_NUWShl(m_Value(), m_Value()).match(IRB.CreateNUWAdd(L, R)));
+}
+
+} // anonymous namespace.
diff --git a/gnu/llvm/unittests/IR/TypeBuilderTest.cpp b/gnu/llvm/unittests/IR/TypeBuilderTest.cpp
new file mode 100644
index 00000000000..b7b3e45e35e
--- /dev/null
+++ b/gnu/llvm/unittests/IR/TypeBuilderTest.cpp
@@ -0,0 +1,253 @@
+//===- llvm/unittest/TypeBuilderTest.cpp - TypeBuilder tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/TypeBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(TypeBuilderTest, Void) {
+ EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getVoidTy(getGlobalContext()), (TypeBuilder<void, false>::get(getGlobalContext())));
+ // Special cases for C compatibility:
+ EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()),
+ (TypeBuilder<void*, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()),
+ (TypeBuilder<const void*, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()),
+ (TypeBuilder<volatile void*, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()),
+ (TypeBuilder<const volatile void*, false>::get(
+ getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, HostIntegers) {
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<int8_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()), (TypeBuilder<uint8_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<int16_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt16Ty(getGlobalContext()), (TypeBuilder<uint16_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<int32_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (TypeBuilder<uint32_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<int64_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt64Ty(getGlobalContext()), (TypeBuilder<uint64_t, false>::get(getGlobalContext())));
+
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(size_t) * CHAR_BIT),
+ (TypeBuilder<size_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), sizeof(ptrdiff_t) * CHAR_BIT),
+ (TypeBuilder<ptrdiff_t, false>::get(getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, CrossCompilableIntegers) {
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, true>::get(getGlobalContext())));
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), 1), (TypeBuilder<types::i<1>, false>::get(getGlobalContext())));
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, true>::get(getGlobalContext())));
+ EXPECT_EQ(IntegerType::get(getGlobalContext(), 72), (TypeBuilder<types::i<72>, false>::get(getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, Float) {
+ EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<float, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<double, false>::get(getGlobalContext())));
+ // long double isn't supported yet.
+ EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getFloatTy(getGlobalContext()), (TypeBuilder<types::ieee_float, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getDoubleTy(getGlobalContext()), (TypeBuilder<types::ieee_double, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getX86_FP80Ty(getGlobalContext()), (TypeBuilder<types::x86_fp80, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getFP128Ty(getGlobalContext()), (TypeBuilder<types::fp128, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getPPC_FP128Ty(getGlobalContext()), (TypeBuilder<types::ppc_fp128, false>::get(getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, Derived) {
+ EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())),
+ (TypeBuilder<int8_t**, false>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7),
+ (TypeBuilder<int8_t[7], false>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0),
+ (TypeBuilder<int8_t[], false>::get(getGlobalContext())));
+
+ EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())),
+ (TypeBuilder<types::i<8>**, false>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7),
+ (TypeBuilder<types::i<8>[7], false>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0),
+ (TypeBuilder<types::i<8>[], false>::get(getGlobalContext())));
+
+ EXPECT_EQ(PointerType::getUnqual(Type::getInt8PtrTy(getGlobalContext())),
+ (TypeBuilder<types::i<8>**, true>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 7),
+ (TypeBuilder<types::i<8>[7], true>::get(getGlobalContext())));
+ EXPECT_EQ(ArrayType::get(Type::getInt8Ty(getGlobalContext()), 0),
+ (TypeBuilder<types::i<8>[], true>::get(getGlobalContext())));
+
+
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const int8_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<volatile int8_t, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const volatile int8_t, false>::get(getGlobalContext())));
+
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const types::i<8>, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<volatile types::i<8>, false>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const volatile types::i<8>, false>::get(getGlobalContext())));
+
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const types::i<8>, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<volatile types::i<8>, true>::get(getGlobalContext())));
+ EXPECT_EQ(Type::getInt8Ty(getGlobalContext()),
+ (TypeBuilder<const volatile types::i<8>, true>::get(getGlobalContext())));
+
+ EXPECT_EQ(Type::getInt8PtrTy(getGlobalContext()),
+ (TypeBuilder<const volatile int8_t*const volatile, false>::get(getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, Functions) {
+ std::vector<Type*> params;
+ EXPECT_EQ(FunctionType::get(Type::getVoidTy(getGlobalContext()), params, false),
+ (TypeBuilder<void(), true>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(...), false>::get(getGlobalContext())));
+ params.push_back(TypeBuilder<int32_t*, false>::get(getGlobalContext()));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false),
+ (TypeBuilder<int8_t(const int32_t*), false>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(const int32_t*, ...), false>::get(getGlobalContext())));
+ params.push_back(TypeBuilder<char*, false>::get(getGlobalContext()));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false),
+ (TypeBuilder<int8_t(int32_t*, void*), false>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(int32_t*, char*, ...), false>::get(getGlobalContext())));
+ params.push_back(TypeBuilder<char, false>::get(getGlobalContext()));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false),
+ (TypeBuilder<int8_t(int32_t*, void*, char), false>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(int32_t*, char*, char, ...), false>::get(getGlobalContext())));
+ params.push_back(TypeBuilder<char, false>::get(getGlobalContext()));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false),
+ (TypeBuilder<int8_t(int32_t*, void*, char, char), false>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(int32_t*, char*, char, char, ...),
+ false>::get(getGlobalContext())));
+ params.push_back(TypeBuilder<char, false>::get(getGlobalContext()));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, false),
+ (TypeBuilder<int8_t(int32_t*, void*, char, char, char),
+ false>::get(getGlobalContext())));
+ EXPECT_EQ(FunctionType::get(Type::getInt8Ty(getGlobalContext()), params, true),
+ (TypeBuilder<int8_t(int32_t*, char*, char, char, char, ...),
+ false>::get(getGlobalContext())));
+}
+
+TEST(TypeBuilderTest, Context) {
+ // We used to cache TypeBuilder results in static local variables. This
+ // produced the same type for different contexts, which of course broke
+ // things.
+ LLVMContext context1;
+ EXPECT_EQ(&context1,
+ &(TypeBuilder<types::i<1>, true>::get(context1))->getContext());
+ LLVMContext context2;
+ EXPECT_EQ(&context2,
+ &(TypeBuilder<types::i<1>, true>::get(context2))->getContext());
+}
+
+struct MyType {
+ int a;
+ int *b;
+ void *array[1];
+};
+
+struct MyPortableType {
+ int32_t a;
+ int32_t *b;
+ void *array[1];
+};
+
+} // anonymous namespace
+
+namespace llvm {
+template<bool cross> class TypeBuilder<MyType, cross> {
+public:
+ static StructType *get(LLVMContext &Context) {
+ // Using the static result variable ensures that the type is
+ // only looked up once.
+ std::vector<Type*> st;
+ st.push_back(TypeBuilder<int, cross>::get(Context));
+ st.push_back(TypeBuilder<int*, cross>::get(Context));
+ st.push_back(TypeBuilder<void*[], cross>::get(Context));
+ static StructType *const result = StructType::get(Context, st);
+ return result;
+ }
+
+ // You may find this a convenient place to put some constants
+ // to help with getelementptr. They don't have any effect on
+ // the operation of TypeBuilder.
+ enum Fields {
+ FIELD_A,
+ FIELD_B,
+ FIELD_ARRAY
+ };
+};
+
+template<bool cross> class TypeBuilder<MyPortableType, cross> {
+public:
+ static StructType *get(LLVMContext &Context) {
+ // Using the static result variable ensures that the type is
+ // only looked up once.
+ std::vector<Type*> st;
+ st.push_back(TypeBuilder<types::i<32>, cross>::get(Context));
+ st.push_back(TypeBuilder<types::i<32>*, cross>::get(Context));
+ st.push_back(TypeBuilder<types::i<8>*[], cross>::get(Context));
+ static StructType *const result = StructType::get(Context, st);
+ return result;
+ }
+
+ // You may find this a convenient place to put some constants
+ // to help with getelementptr. They don't have any effect on
+ // the operation of TypeBuilder.
+ enum Fields {
+ FIELD_A,
+ FIELD_B,
+ FIELD_ARRAY
+ };
+};
+} // namespace llvm
+namespace {
+
+TEST(TypeBuilderTest, Extensions) {
+ EXPECT_EQ(PointerType::getUnqual(StructType::get(
+ TypeBuilder<int, false>::get(getGlobalContext()),
+ TypeBuilder<int*, false>::get(getGlobalContext()),
+ TypeBuilder<void*[], false>::get(getGlobalContext()),
+ (void*)nullptr)),
+ (TypeBuilder<MyType*, false>::get(getGlobalContext())));
+ EXPECT_EQ(PointerType::getUnqual(StructType::get(
+ TypeBuilder<types::i<32>, false>::get(getGlobalContext()),
+ TypeBuilder<types::i<32>*, false>::get(getGlobalContext()),
+ TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()),
+ (void*)nullptr)),
+ (TypeBuilder<MyPortableType*, false>::get(getGlobalContext())));
+ EXPECT_EQ(PointerType::getUnqual(StructType::get(
+ TypeBuilder<types::i<32>, false>::get(getGlobalContext()),
+ TypeBuilder<types::i<32>*, false>::get(getGlobalContext()),
+ TypeBuilder<types::i<8>*[], false>::get(getGlobalContext()),
+ (void*)nullptr)),
+ (TypeBuilder<MyPortableType*, true>::get(getGlobalContext())));
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/IR/TypesTest.cpp b/gnu/llvm/unittests/IR/TypesTest.cpp
new file mode 100644
index 00000000000..f006db51de5
--- /dev/null
+++ b/gnu/llvm/unittests/IR/TypesTest.cpp
@@ -0,0 +1,38 @@
+//===- llvm/unittest/IR/TypesTest.cpp - Type 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/IR/DerivedTypes.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(TypesTest, StructType) {
+ LLVMContext C;
+
+ // PR13522
+ StructType *Struct = StructType::create(C, "FooBar");
+ EXPECT_EQ("FooBar", Struct->getName());
+ Struct->setName(Struct->getName().substr(0, 3));
+ EXPECT_EQ("Foo", Struct->getName());
+ Struct->setName("");
+ EXPECT_TRUE(Struct->getName().empty());
+ EXPECT_FALSE(Struct->hasName());
+}
+
+TEST(TypesTest, LayoutIdenticalEmptyStructs) {
+ LLVMContext C;
+
+ StructType *Foo = StructType::create(C, "Foo");
+ StructType *Bar = StructType::create(C, "Bar");
+ EXPECT_TRUE(Foo->isLayoutIdentical(Bar));
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/IR/UseTest.cpp b/gnu/llvm/unittests/IR/UseTest.cpp
new file mode 100644
index 00000000000..d9d20af941d
--- /dev/null
+++ b/gnu/llvm/unittests/IR/UseTest.cpp
@@ -0,0 +1,112 @@
+//===- llvm/unittest/IR/UseTest.cpp - Use 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/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/User.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(UseTest, sort) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x) {\n"
+ "entry:\n"
+ " %v0 = add i32 %x, 0\n"
+ " %v2 = add i32 %x, 2\n"
+ " %v5 = add i32 %x, 5\n"
+ " %v1 = add i32 %x, 1\n"
+ " %v3 = add i32 %x, 3\n"
+ " %v7 = add i32 %x, 7\n"
+ " %v6 = add i32 %x, 6\n"
+ " %v4 = add i32 %x, 4\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ char vnbuf[8];
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+ Function *F = M->getFunction("f");
+ ASSERT_TRUE(F);
+ ASSERT_TRUE(F->arg_begin() != F->arg_end());
+ Argument &X = *F->arg_begin();
+ ASSERT_EQ("x", X.getName());
+
+ X.sortUseList([](const Use &L, const Use &R) {
+ return L.getUser()->getName() < R.getUser()->getName();
+ });
+ unsigned I = 0;
+ for (User *U : X.users()) {
+ format("v%u", I++).snprint(vnbuf, sizeof(vnbuf));
+ EXPECT_EQ(vnbuf, U->getName());
+ }
+ ASSERT_EQ(8u, I);
+
+ X.sortUseList([](const Use &L, const Use &R) {
+ return L.getUser()->getName() > R.getUser()->getName();
+ });
+ I = 0;
+ for (User *U : X.users()) {
+ format("v%u", (7 - I++)).snprint(vnbuf, sizeof(vnbuf));
+ EXPECT_EQ(vnbuf, U->getName());
+ }
+ ASSERT_EQ(8u, I);
+}
+
+TEST(UseTest, reverse) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x) {\n"
+ "entry:\n"
+ " %v0 = add i32 %x, 0\n"
+ " %v2 = add i32 %x, 2\n"
+ " %v5 = add i32 %x, 5\n"
+ " %v1 = add i32 %x, 1\n"
+ " %v3 = add i32 %x, 3\n"
+ " %v7 = add i32 %x, 7\n"
+ " %v6 = add i32 %x, 6\n"
+ " %v4 = add i32 %x, 4\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ char vnbuf[8];
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+ Function *F = M->getFunction("f");
+ ASSERT_TRUE(F);
+ ASSERT_TRUE(F->arg_begin() != F->arg_end());
+ Argument &X = *F->arg_begin();
+ ASSERT_EQ("x", X.getName());
+
+ X.sortUseList([](const Use &L, const Use &R) {
+ return L.getUser()->getName() < R.getUser()->getName();
+ });
+ unsigned I = 0;
+ for (User *U : X.users()) {
+ format("v%u", I++).snprint(vnbuf, sizeof(vnbuf));
+ EXPECT_EQ(vnbuf, U->getName());
+ }
+ ASSERT_EQ(8u, I);
+
+ X.reverseUseList();
+ I = 0;
+ for (User *U : X.users()) {
+ format("v%u", (7 - I++)).snprint(vnbuf, sizeof(vnbuf));
+ EXPECT_EQ(vnbuf, U->getName());
+ }
+ ASSERT_EQ(8u, I);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/IR/UserTest.cpp b/gnu/llvm/unittests/IR/UserTest.cpp
new file mode 100644
index 00000000000..8d488389448
--- /dev/null
+++ b/gnu/llvm/unittests/IR/UserTest.cpp
@@ -0,0 +1,120 @@
+//===- llvm/unittest/IR/UserTest.cpp - User 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/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/User.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(UserTest, ValueOpIteration) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "entry:\n"
+ " switch i32 undef, label %s0\n"
+ " [ i32 1, label %s1\n"
+ " i32 2, label %s2\n"
+ " i32 3, label %s3\n"
+ " i32 4, label %s4\n"
+ " i32 5, label %s5\n"
+ " i32 6, label %s6\n"
+ " i32 7, label %s7\n"
+ " i32 8, label %s8\n"
+ " i32 9, label %s9 ]\n"
+ "\n"
+ "s0:\n"
+ " br label %exit\n"
+ "s1:\n"
+ " br label %exit\n"
+ "s2:\n"
+ " br label %exit\n"
+ "s3:\n"
+ " br label %exit\n"
+ "s4:\n"
+ " br label %exit\n"
+ "s5:\n"
+ " br label %exit\n"
+ "s6:\n"
+ " br label %exit\n"
+ "s7:\n"
+ " br label %exit\n"
+ "s8:\n"
+ " br label %exit\n"
+ "s9:\n"
+ " br label %exit\n"
+ "\n"
+ "exit:\n"
+ " %phi = phi i32 [ 0, %s0 ], [ 1, %s1 ],\n"
+ " [ 2, %s2 ], [ 3, %s3 ],\n"
+ " [ 4, %s4 ], [ 5, %s5 ],\n"
+ " [ 6, %s6 ], [ 7, %s7 ],\n"
+ " [ 8, %s8 ], [ 9, %s9 ]\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f");
+ BasicBlock &ExitBB = F->back();
+ PHINode &P = cast<PHINode>(ExitBB.front());
+ EXPECT_TRUE(P.value_op_begin() == P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() == P.value_op_end());
+ EXPECT_TRUE(P.value_op_begin() != P.value_op_end());
+ EXPECT_FALSE(P.value_op_end() != P.value_op_end());
+ EXPECT_TRUE(P.value_op_begin() < P.value_op_end());
+ EXPECT_FALSE(P.value_op_begin() < P.value_op_begin());
+ EXPECT_TRUE(P.value_op_end() > P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() > P.value_op_begin());
+ EXPECT_TRUE(P.value_op_begin() <= P.value_op_begin());
+ EXPECT_FALSE(P.value_op_end() <= P.value_op_begin());
+ EXPECT_TRUE(P.value_op_begin() >= P.value_op_begin());
+ EXPECT_FALSE(P.value_op_begin() >= P.value_op_end());
+ EXPECT_EQ(10, std::distance(P.value_op_begin(), P.value_op_end()));
+
+ User::value_op_iterator I = P.value_op_begin();
+ I += 3;
+ EXPECT_EQ(std::next(P.value_op_begin(), 3), I);
+ EXPECT_EQ(P.getOperand(3), *I);
+ I++;
+ EXPECT_EQ(P.getOperand(6), I[2]);
+ EXPECT_EQ(P.value_op_end(), (I - 2) + 8);
+}
+
+TEST(UserTest, PersonalityUser) {
+ Module M("", getGlobalContext());
+ FunctionType *RetVoidTy =
+ FunctionType::get(Type::getVoidTy(getGlobalContext()), false);
+ Function *PersonalityF = Function::Create(
+ RetVoidTy, GlobalValue::ExternalLinkage, "PersonalityFn", &M);
+ Function *TestF =
+ Function::Create(RetVoidTy, GlobalValue::ExternalLinkage, "TestFn", &M);
+
+ // Set up the personality function
+ TestF->setPersonalityFn(PersonalityF);
+ auto PersonalityUsers = PersonalityF->user_begin();
+
+ // One user and that user is the Test function
+ EXPECT_EQ(*PersonalityUsers, TestF);
+ EXPECT_EQ(++PersonalityUsers, PersonalityF->user_end());
+
+ // Reset the personality function
+ TestF->setPersonalityFn(nullptr);
+
+ // No users should remain
+ EXPECT_TRUE(TestF->user_empty());
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/IR/ValueHandleTest.cpp b/gnu/llvm/unittests/IR/ValueHandleTest.cpp
new file mode 100644
index 00000000000..e1d598bbc58
--- /dev/null
+++ b/gnu/llvm/unittests/IR/ValueHandleTest.cpp
@@ -0,0 +1,413 @@
+//===- ValueHandleTest.cpp - ValueHandle tests ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/ValueHandle.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+class ValueHandle : public testing::Test {
+protected:
+ Constant *ConstantV;
+ std::unique_ptr<BitCastInst> BitcastV;
+
+ ValueHandle() :
+ ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
+ BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))) {
+ }
+};
+
+class ConcreteCallbackVH final : public CallbackVH {
+public:
+ ConcreteCallbackVH(Value *V) : CallbackVH(V) {}
+};
+
+TEST_F(ValueHandle, WeakVH_BasicOperation) {
+ WeakVH WVH(BitcastV.get());
+ EXPECT_EQ(BitcastV.get(), WVH);
+ WVH = ConstantV;
+ EXPECT_EQ(ConstantV, WVH);
+
+ // Make sure I can call a method on the underlying Value. It
+ // doesn't matter which method.
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), WVH->getType());
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*WVH).getType());
+}
+
+TEST_F(ValueHandle, WeakVH_Comparisons) {
+ WeakVH BitcastWVH(BitcastV.get());
+ WeakVH ConstantWVH(ConstantV);
+
+ EXPECT_TRUE(BitcastWVH == BitcastWVH);
+ EXPECT_TRUE(BitcastV.get() == BitcastWVH);
+ EXPECT_TRUE(BitcastWVH == BitcastV.get());
+ EXPECT_FALSE(BitcastWVH == ConstantWVH);
+
+ EXPECT_TRUE(BitcastWVH != ConstantWVH);
+ EXPECT_TRUE(BitcastV.get() != ConstantWVH);
+ EXPECT_TRUE(BitcastWVH != ConstantV);
+ EXPECT_FALSE(BitcastWVH != BitcastWVH);
+
+ // Cast to Value* so comparisons work.
+ Value *BV = BitcastV.get();
+ Value *CV = ConstantV;
+ EXPECT_EQ(BV < CV, BitcastWVH < ConstantWVH);
+ EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantWVH);
+ EXPECT_EQ(BV > CV, BitcastWVH > ConstantWVH);
+ EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantWVH);
+
+ EXPECT_EQ(BV < CV, BitcastV.get() < ConstantWVH);
+ EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantWVH);
+ EXPECT_EQ(BV > CV, BitcastV.get() > ConstantWVH);
+ EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantWVH);
+
+ EXPECT_EQ(BV < CV, BitcastWVH < ConstantV);
+ EXPECT_EQ(BV <= CV, BitcastWVH <= ConstantV);
+ EXPECT_EQ(BV > CV, BitcastWVH > ConstantV);
+ EXPECT_EQ(BV >= CV, BitcastWVH >= ConstantV);
+}
+
+TEST_F(ValueHandle, WeakVH_FollowsRAUW) {
+ WeakVH WVH(BitcastV.get());
+ WeakVH WVH_Copy(WVH);
+ WeakVH WVH_Recreated(BitcastV.get());
+ BitcastV->replaceAllUsesWith(ConstantV);
+ EXPECT_EQ(ConstantV, WVH);
+ EXPECT_EQ(ConstantV, WVH_Copy);
+ EXPECT_EQ(ConstantV, WVH_Recreated);
+}
+
+TEST_F(ValueHandle, WeakVH_NullOnDeletion) {
+ WeakVH WVH(BitcastV.get());
+ WeakVH WVH_Copy(WVH);
+ WeakVH WVH_Recreated(BitcastV.get());
+ BitcastV.reset();
+ Value *null_value = nullptr;
+ EXPECT_EQ(null_value, WVH);
+ EXPECT_EQ(null_value, WVH_Copy);
+ EXPECT_EQ(null_value, WVH_Recreated);
+}
+
+
+TEST_F(ValueHandle, AssertingVH_BasicOperation) {
+ AssertingVH<CastInst> AVH(BitcastV.get());
+ CastInst *implicit_to_exact_type = AVH;
+ (void)implicit_to_exact_type; // Avoid warning.
+
+ AssertingVH<Value> GenericAVH(BitcastV.get());
+ EXPECT_EQ(BitcastV.get(), GenericAVH);
+ GenericAVH = ConstantV;
+ EXPECT_EQ(ConstantV, GenericAVH);
+
+ // Make sure I can call a method on the underlying CastInst. It
+ // doesn't matter which method.
+ EXPECT_FALSE(AVH->mayWriteToMemory());
+ EXPECT_FALSE((*AVH).mayWriteToMemory());
+}
+
+TEST_F(ValueHandle, AssertingVH_Const) {
+ const CastInst *ConstBitcast = BitcastV.get();
+ AssertingVH<const CastInst> AVH(ConstBitcast);
+ const CastInst *implicit_to_exact_type = AVH;
+ (void)implicit_to_exact_type; // Avoid warning.
+}
+
+TEST_F(ValueHandle, AssertingVH_Comparisons) {
+ AssertingVH<Value> BitcastAVH(BitcastV.get());
+ AssertingVH<Value> ConstantAVH(ConstantV);
+
+ EXPECT_TRUE(BitcastAVH == BitcastAVH);
+ EXPECT_TRUE(BitcastV.get() == BitcastAVH);
+ EXPECT_TRUE(BitcastAVH == BitcastV.get());
+ EXPECT_FALSE(BitcastAVH == ConstantAVH);
+
+ EXPECT_TRUE(BitcastAVH != ConstantAVH);
+ EXPECT_TRUE(BitcastV.get() != ConstantAVH);
+ EXPECT_TRUE(BitcastAVH != ConstantV);
+ EXPECT_FALSE(BitcastAVH != BitcastAVH);
+
+ // Cast to Value* so comparisons work.
+ Value *BV = BitcastV.get();
+ Value *CV = ConstantV;
+ EXPECT_EQ(BV < CV, BitcastAVH < ConstantAVH);
+ EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantAVH);
+ EXPECT_EQ(BV > CV, BitcastAVH > ConstantAVH);
+ EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantAVH);
+
+ EXPECT_EQ(BV < CV, BitcastV.get() < ConstantAVH);
+ EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantAVH);
+ EXPECT_EQ(BV > CV, BitcastV.get() > ConstantAVH);
+ EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantAVH);
+
+ EXPECT_EQ(BV < CV, BitcastAVH < ConstantV);
+ EXPECT_EQ(BV <= CV, BitcastAVH <= ConstantV);
+ EXPECT_EQ(BV > CV, BitcastAVH > ConstantV);
+ EXPECT_EQ(BV >= CV, BitcastAVH >= ConstantV);
+}
+
+TEST_F(ValueHandle, AssertingVH_DoesNotFollowRAUW) {
+ AssertingVH<Value> AVH(BitcastV.get());
+ BitcastV->replaceAllUsesWith(ConstantV);
+ EXPECT_EQ(BitcastV.get(), AVH);
+}
+
+#ifdef NDEBUG
+
+TEST_F(ValueHandle, AssertingVH_ReducesToPointer) {
+ EXPECT_EQ(sizeof(CastInst *), sizeof(AssertingVH<CastInst>));
+}
+
+#else // !NDEBUG
+
+#ifdef GTEST_HAS_DEATH_TEST
+
+TEST_F(ValueHandle, AssertingVH_Asserts) {
+ AssertingVH<Value> AVH(BitcastV.get());
+ EXPECT_DEATH({BitcastV.reset();},
+ "An asserting value handle still pointed to this value!");
+ AssertingVH<Value> Copy(AVH);
+ AVH = nullptr;
+ EXPECT_DEATH({BitcastV.reset();},
+ "An asserting value handle still pointed to this value!");
+ Copy = nullptr;
+ BitcastV.reset();
+}
+
+#endif // GTEST_HAS_DEATH_TEST
+
+#endif // NDEBUG
+
+TEST_F(ValueHandle, CallbackVH_BasicOperation) {
+ ConcreteCallbackVH CVH(BitcastV.get());
+ EXPECT_EQ(BitcastV.get(), CVH);
+ CVH = ConstantV;
+ EXPECT_EQ(ConstantV, CVH);
+
+ // Make sure I can call a method on the underlying Value. It
+ // doesn't matter which method.
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), CVH->getType());
+ EXPECT_EQ(Type::getInt32Ty(getGlobalContext()), (*CVH).getType());
+}
+
+TEST_F(ValueHandle, CallbackVH_Comparisons) {
+ ConcreteCallbackVH BitcastCVH(BitcastV.get());
+ ConcreteCallbackVH ConstantCVH(ConstantV);
+
+ EXPECT_TRUE(BitcastCVH == BitcastCVH);
+ EXPECT_TRUE(BitcastV.get() == BitcastCVH);
+ EXPECT_TRUE(BitcastCVH == BitcastV.get());
+ EXPECT_FALSE(BitcastCVH == ConstantCVH);
+
+ EXPECT_TRUE(BitcastCVH != ConstantCVH);
+ EXPECT_TRUE(BitcastV.get() != ConstantCVH);
+ EXPECT_TRUE(BitcastCVH != ConstantV);
+ EXPECT_FALSE(BitcastCVH != BitcastCVH);
+
+ // Cast to Value* so comparisons work.
+ Value *BV = BitcastV.get();
+ Value *CV = ConstantV;
+ EXPECT_EQ(BV < CV, BitcastCVH < ConstantCVH);
+ EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantCVH);
+ EXPECT_EQ(BV > CV, BitcastCVH > ConstantCVH);
+ EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantCVH);
+
+ EXPECT_EQ(BV < CV, BitcastV.get() < ConstantCVH);
+ EXPECT_EQ(BV <= CV, BitcastV.get() <= ConstantCVH);
+ EXPECT_EQ(BV > CV, BitcastV.get() > ConstantCVH);
+ EXPECT_EQ(BV >= CV, BitcastV.get() >= ConstantCVH);
+
+ EXPECT_EQ(BV < CV, BitcastCVH < ConstantV);
+ EXPECT_EQ(BV <= CV, BitcastCVH <= ConstantV);
+ EXPECT_EQ(BV > CV, BitcastCVH > ConstantV);
+ EXPECT_EQ(BV >= CV, BitcastCVH >= ConstantV);
+}
+
+TEST_F(ValueHandle, CallbackVH_CallbackOnDeletion) {
+ class RecordingVH final : public CallbackVH {
+ public:
+ int DeletedCalls;
+ int AURWCalls;
+
+ RecordingVH() : DeletedCalls(0), AURWCalls(0) {}
+ RecordingVH(Value *V) : CallbackVH(V), DeletedCalls(0), AURWCalls(0) {}
+
+ private:
+ void deleted() override {
+ DeletedCalls++;
+ CallbackVH::deleted();
+ }
+ void allUsesReplacedWith(Value *) override { AURWCalls++; }
+ };
+
+ RecordingVH RVH;
+ RVH = BitcastV.get();
+ EXPECT_EQ(0, RVH.DeletedCalls);
+ EXPECT_EQ(0, RVH.AURWCalls);
+ BitcastV.reset();
+ EXPECT_EQ(1, RVH.DeletedCalls);
+ EXPECT_EQ(0, RVH.AURWCalls);
+}
+
+TEST_F(ValueHandle, CallbackVH_CallbackOnRAUW) {
+ class RecordingVH final : public CallbackVH {
+ public:
+ int DeletedCalls;
+ Value *AURWArgument;
+
+ RecordingVH() : DeletedCalls(0), AURWArgument(nullptr) {}
+ RecordingVH(Value *V)
+ : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr) {}
+
+ private:
+ void deleted() override {
+ DeletedCalls++;
+ CallbackVH::deleted();
+ }
+ void allUsesReplacedWith(Value *new_value) override {
+ EXPECT_EQ(nullptr, AURWArgument);
+ AURWArgument = new_value;
+ }
+ };
+
+ RecordingVH RVH;
+ RVH = BitcastV.get();
+ EXPECT_EQ(0, RVH.DeletedCalls);
+ EXPECT_EQ(nullptr, RVH.AURWArgument);
+ BitcastV->replaceAllUsesWith(ConstantV);
+ EXPECT_EQ(0, RVH.DeletedCalls);
+ EXPECT_EQ(ConstantV, RVH.AURWArgument);
+}
+
+TEST_F(ValueHandle, CallbackVH_DeletionCanRAUW) {
+ class RecoveringVH final : public CallbackVH {
+ public:
+ int DeletedCalls;
+ Value *AURWArgument;
+ LLVMContext *Context;
+
+ RecoveringVH() : DeletedCalls(0), AURWArgument(nullptr),
+ Context(&getGlobalContext()) {}
+ RecoveringVH(Value *V)
+ : CallbackVH(V), DeletedCalls(0), AURWArgument(nullptr),
+ Context(&getGlobalContext()) {}
+
+ private:
+ void deleted() override {
+ getValPtr()->replaceAllUsesWith(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())));
+ setValPtr(nullptr);
+ }
+ void allUsesReplacedWith(Value *new_value) override {
+ ASSERT_TRUE(nullptr != getValPtr());
+ EXPECT_EQ(1U, getValPtr()->getNumUses());
+ EXPECT_EQ(nullptr, AURWArgument);
+ AURWArgument = new_value;
+ }
+ };
+
+ // Normally, if a value has uses, deleting it will crash. However, we can use
+ // a CallbackVH to remove the uses before the check for no uses.
+ RecoveringVH RVH;
+ RVH = BitcastV.get();
+ std::unique_ptr<BinaryOperator> BitcastUser(
+ BinaryOperator::CreateAdd(RVH,
+ Constant::getNullValue(Type::getInt32Ty(getGlobalContext()))));
+ EXPECT_EQ(BitcastV.get(), BitcastUser->getOperand(0));
+ BitcastV.reset(); // Would crash without the ValueHandler.
+ EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())), RVH.AURWArgument);
+ EXPECT_EQ(Constant::getNullValue(Type::getInt32Ty(getGlobalContext())),
+ BitcastUser->getOperand(0));
+}
+
+TEST_F(ValueHandle, DestroyingOtherVHOnSameValueDoesntBreakIteration) {
+ // When a CallbackVH modifies other ValueHandles in its callbacks,
+ // that shouldn't interfere with non-modified ValueHandles receiving
+ // their appropriate callbacks.
+ //
+ // We create the active CallbackVH in the middle of a palindromic
+ // arrangement of other VHs so that the bad behavior would be
+ // triggered in whichever order callbacks run.
+
+ class DestroyingVH final : public CallbackVH {
+ public:
+ std::unique_ptr<WeakVH> ToClear[2];
+ DestroyingVH(Value *V) {
+ ToClear[0].reset(new WeakVH(V));
+ setValPtr(V);
+ ToClear[1].reset(new WeakVH(V));
+ }
+ void deleted() override {
+ ToClear[0].reset();
+ ToClear[1].reset();
+ CallbackVH::deleted();
+ }
+ void allUsesReplacedWith(Value *) override {
+ ToClear[0].reset();
+ ToClear[1].reset();
+ }
+ };
+
+ {
+ WeakVH ShouldBeVisited1(BitcastV.get());
+ DestroyingVH C(BitcastV.get());
+ WeakVH ShouldBeVisited2(BitcastV.get());
+
+ BitcastV->replaceAllUsesWith(ConstantV);
+ EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited1));
+ EXPECT_EQ(ConstantV, static_cast<Value*>(ShouldBeVisited2));
+ }
+
+ {
+ WeakVH ShouldBeVisited1(BitcastV.get());
+ DestroyingVH C(BitcastV.get());
+ WeakVH ShouldBeVisited2(BitcastV.get());
+
+ BitcastV.reset();
+ EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited1));
+ EXPECT_EQ(nullptr, static_cast<Value*>(ShouldBeVisited2));
+ }
+}
+
+TEST_F(ValueHandle, AssertingVHCheckedLast) {
+ // If a CallbackVH exists to clear out a group of AssertingVHs on
+ // Value deletion, the CallbackVH should get a chance to do so
+ // before the AssertingVHs assert.
+
+ class ClearingVH final : public CallbackVH {
+ public:
+ AssertingVH<Value> *ToClear[2];
+ ClearingVH(Value *V,
+ AssertingVH<Value> &A0, AssertingVH<Value> &A1)
+ : CallbackVH(V) {
+ ToClear[0] = &A0;
+ ToClear[1] = &A1;
+ }
+
+ void deleted() override {
+ *ToClear[0] = nullptr;
+ *ToClear[1] = nullptr;
+ CallbackVH::deleted();
+ }
+ };
+
+ AssertingVH<Value> A1, A2;
+ A1 = BitcastV.get();
+ ClearingVH C(BitcastV.get(), A1, A2);
+ A2 = BitcastV.get();
+ // C.deleted() should run first, clearing the two AssertingVHs,
+ // which should prevent them from asserting.
+ BitcastV.reset();
+}
+
+}
diff --git a/gnu/llvm/unittests/IR/ValueMapTest.cpp b/gnu/llvm/unittests/IR/ValueMapTest.cpp
new file mode 100644
index 00000000000..1431a8d87de
--- /dev/null
+++ b/gnu/llvm/unittests/IR/ValueMapTest.cpp
@@ -0,0 +1,295 @@
+//===- llvm/unittest/ADT/ValueMapTest.cpp - ValueMap 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/IR/ValueMap.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+// Test fixture
+template<typename T>
+class ValueMapTest : public testing::Test {
+protected:
+ Constant *ConstantV;
+ std::unique_ptr<BitCastInst> BitcastV;
+ std::unique_ptr<BinaryOperator> AddV;
+
+ ValueMapTest() :
+ ConstantV(ConstantInt::get(Type::getInt32Ty(getGlobalContext()), 0)),
+ BitcastV(new BitCastInst(ConstantV, Type::getInt32Ty(getGlobalContext()))),
+ AddV(BinaryOperator::CreateAdd(ConstantV, ConstantV)) {
+ }
+};
+
+// Run everything on Value*, a subtype to make sure that casting works as
+// expected, and a const subtype to make sure we cast const correctly.
+typedef ::testing::Types<Value, Instruction, const Instruction> KeyTypes;
+TYPED_TEST_CASE(ValueMapTest, KeyTypes);
+
+TYPED_TEST(ValueMapTest, Null) {
+ ValueMap<TypeParam*, int> VM1;
+ VM1[nullptr] = 7;
+ EXPECT_EQ(7, VM1.lookup(nullptr));
+}
+
+TYPED_TEST(ValueMapTest, FollowsValue) {
+ ValueMap<TypeParam*, int> VM;
+ VM[this->BitcastV.get()] = 7;
+ EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
+ EXPECT_EQ(0u, VM.count(this->AddV.get()));
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ EXPECT_EQ(7, VM.lookup(this->AddV.get()));
+ EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
+ this->AddV.reset();
+ EXPECT_EQ(0u, VM.count(this->AddV.get()));
+ EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
+ EXPECT_EQ(0U, VM.size());
+}
+
+TYPED_TEST(ValueMapTest, OperationsWork) {
+ ValueMap<TypeParam*, int> VM;
+ ValueMap<TypeParam*, int> VM2(16); (void)VM2;
+ typename ValueMapConfig<TypeParam*>::ExtraData Data;
+ ValueMap<TypeParam*, int> VM3(Data, 16); (void)VM3;
+ EXPECT_TRUE(VM.empty());
+
+ VM[this->BitcastV.get()] = 7;
+
+ // Find:
+ typename ValueMap<TypeParam*, int>::iterator I =
+ VM.find(this->BitcastV.get());
+ ASSERT_TRUE(I != VM.end());
+ EXPECT_EQ(this->BitcastV.get(), I->first);
+ EXPECT_EQ(7, I->second);
+ EXPECT_TRUE(VM.find(this->AddV.get()) == VM.end());
+
+ // Const find:
+ const ValueMap<TypeParam*, int> &CVM = VM;
+ typename ValueMap<TypeParam*, int>::const_iterator CI =
+ CVM.find(this->BitcastV.get());
+ ASSERT_TRUE(CI != CVM.end());
+ EXPECT_EQ(this->BitcastV.get(), CI->first);
+ EXPECT_EQ(7, CI->second);
+ EXPECT_TRUE(CVM.find(this->AddV.get()) == CVM.end());
+
+ // Insert:
+ std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult1 =
+ VM.insert(std::make_pair(this->AddV.get(), 3));
+ EXPECT_EQ(this->AddV.get(), InsertResult1.first->first);
+ EXPECT_EQ(3, InsertResult1.first->second);
+ EXPECT_TRUE(InsertResult1.second);
+ EXPECT_EQ(1u, VM.count(this->AddV.get()));
+ std::pair<typename ValueMap<TypeParam*, int>::iterator, bool> InsertResult2 =
+ VM.insert(std::make_pair(this->AddV.get(), 5));
+ EXPECT_EQ(this->AddV.get(), InsertResult2.first->first);
+ EXPECT_EQ(3, InsertResult2.first->second);
+ EXPECT_FALSE(InsertResult2.second);
+
+ // Erase:
+ VM.erase(InsertResult2.first);
+ EXPECT_EQ(0U, VM.count(this->AddV.get()));
+ EXPECT_EQ(1U, VM.count(this->BitcastV.get()));
+ VM.erase(this->BitcastV.get());
+ EXPECT_EQ(0U, VM.count(this->BitcastV.get()));
+ EXPECT_EQ(0U, VM.size());
+
+ // Range insert:
+ SmallVector<std::pair<Instruction*, int>, 2> Elems;
+ Elems.push_back(std::make_pair(this->AddV.get(), 1));
+ Elems.push_back(std::make_pair(this->BitcastV.get(), 2));
+ VM.insert(Elems.begin(), Elems.end());
+ EXPECT_EQ(1, VM.lookup(this->AddV.get()));
+ EXPECT_EQ(2, VM.lookup(this->BitcastV.get()));
+}
+
+template<typename ExpectedType, typename VarType>
+void CompileAssertHasType(VarType) {
+ static_assert(std::is_same<ExpectedType, VarType>::value,
+ "Not the same type");
+}
+
+TYPED_TEST(ValueMapTest, Iteration) {
+ ValueMap<TypeParam*, int> VM;
+ VM[this->BitcastV.get()] = 2;
+ VM[this->AddV.get()] = 3;
+ size_t size = 0;
+ for (typename ValueMap<TypeParam*, int>::iterator I = VM.begin(), E = VM.end();
+ I != E; ++I) {
+ ++size;
+ std::pair<TypeParam*, int> value = *I; (void)value;
+ CompileAssertHasType<TypeParam*>(I->first);
+ if (I->second == 2) {
+ EXPECT_EQ(this->BitcastV.get(), I->first);
+ I->second = 5;
+ } else if (I->second == 3) {
+ EXPECT_EQ(this->AddV.get(), I->first);
+ I->second = 6;
+ } else {
+ ADD_FAILURE() << "Iterated through an extra value.";
+ }
+ }
+ EXPECT_EQ(2U, size);
+ EXPECT_EQ(5, VM[this->BitcastV.get()]);
+ EXPECT_EQ(6, VM[this->AddV.get()]);
+
+ size = 0;
+ // Cast to const ValueMap to avoid a bug in DenseMap's iterators.
+ const ValueMap<TypeParam*, int>& CVM = VM;
+ for (typename ValueMap<TypeParam*, int>::const_iterator I = CVM.begin(),
+ E = CVM.end(); I != E; ++I) {
+ ++size;
+ std::pair<TypeParam*, int> value = *I; (void)value;
+ CompileAssertHasType<TypeParam*>(I->first);
+ if (I->second == 5) {
+ EXPECT_EQ(this->BitcastV.get(), I->first);
+ } else if (I->second == 6) {
+ EXPECT_EQ(this->AddV.get(), I->first);
+ } else {
+ ADD_FAILURE() << "Iterated through an extra value.";
+ }
+ }
+ EXPECT_EQ(2U, size);
+}
+
+TYPED_TEST(ValueMapTest, DefaultCollisionBehavior) {
+ // By default, we overwrite the old value with the replaced value.
+ ValueMap<TypeParam*, int> VM;
+ VM[this->BitcastV.get()] = 7;
+ VM[this->AddV.get()] = 9;
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
+ EXPECT_EQ(9, VM.lookup(this->AddV.get()));
+}
+
+TYPED_TEST(ValueMapTest, ConfiguredCollisionBehavior) {
+ // TODO: Implement this when someone needs it.
+}
+
+template<typename KeyT, typename MutexT>
+struct LockMutex : ValueMapConfig<KeyT, MutexT> {
+ struct ExtraData {
+ MutexT *M;
+ bool *CalledRAUW;
+ bool *CalledDeleted;
+ };
+ static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
+ *Data.CalledRAUW = true;
+ EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked.";
+ }
+ static void onDelete(const ExtraData &Data, KeyT Old) {
+ *Data.CalledDeleted = true;
+ EXPECT_FALSE(Data.M->try_lock()) << "Mutex should already be locked.";
+ }
+ static MutexT *getMutex(const ExtraData &Data) { return Data.M; }
+};
+// FIXME: These tests started failing on Windows.
+#if LLVM_ENABLE_THREADS && !defined(LLVM_ON_WIN32)
+TYPED_TEST(ValueMapTest, LocksMutex) {
+ sys::Mutex M(false); // Not recursive.
+ bool CalledRAUW = false, CalledDeleted = false;
+ typedef LockMutex<TypeParam*, sys::Mutex> ConfigType;
+ typename ConfigType::ExtraData Data = {&M, &CalledRAUW, &CalledDeleted};
+ ValueMap<TypeParam*, int, ConfigType> VM(Data);
+ VM[this->BitcastV.get()] = 7;
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ this->AddV.reset();
+ EXPECT_TRUE(CalledRAUW);
+ EXPECT_TRUE(CalledDeleted);
+}
+#endif
+
+template<typename KeyT>
+struct NoFollow : ValueMapConfig<KeyT> {
+ enum { FollowRAUW = false };
+};
+
+TYPED_TEST(ValueMapTest, NoFollowRAUW) {
+ ValueMap<TypeParam*, int, NoFollow<TypeParam*> > VM;
+ VM[this->BitcastV.get()] = 7;
+ EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
+ EXPECT_EQ(0u, VM.count(this->AddV.get()));
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
+ EXPECT_EQ(0, VM.lookup(this->AddV.get()));
+ this->AddV.reset();
+ EXPECT_EQ(7, VM.lookup(this->BitcastV.get()));
+ EXPECT_EQ(0, VM.lookup(this->AddV.get()));
+ this->BitcastV.reset();
+ EXPECT_EQ(0, VM.lookup(this->BitcastV.get()));
+ EXPECT_EQ(0, VM.lookup(this->AddV.get()));
+ EXPECT_EQ(0U, VM.size());
+}
+
+template<typename KeyT>
+struct CountOps : ValueMapConfig<KeyT> {
+ struct ExtraData {
+ int *Deletions;
+ int *RAUWs;
+ };
+
+ static void onRAUW(const ExtraData &Data, KeyT Old, KeyT New) {
+ ++*Data.RAUWs;
+ }
+ static void onDelete(const ExtraData &Data, KeyT Old) {
+ ++*Data.Deletions;
+ }
+};
+
+TYPED_TEST(ValueMapTest, CallsConfig) {
+ int Deletions = 0, RAUWs = 0;
+ typename CountOps<TypeParam*>::ExtraData Data = {&Deletions, &RAUWs};
+ ValueMap<TypeParam*, int, CountOps<TypeParam*> > VM(Data);
+ VM[this->BitcastV.get()] = 7;
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ EXPECT_EQ(0, Deletions);
+ EXPECT_EQ(1, RAUWs);
+ this->AddV.reset();
+ EXPECT_EQ(1, Deletions);
+ EXPECT_EQ(1, RAUWs);
+ this->BitcastV.reset();
+ EXPECT_EQ(1, Deletions);
+ EXPECT_EQ(1, RAUWs);
+}
+
+template<typename KeyT>
+struct ModifyingConfig : ValueMapConfig<KeyT> {
+ // We'll put a pointer here back to the ValueMap this key is in, so
+ // that we can modify it (and clobber *this) before the ValueMap
+ // tries to do the same modification. In previous versions of
+ // ValueMap, that exploded.
+ typedef ValueMap<KeyT, int, ModifyingConfig<KeyT> > **ExtraData;
+
+ static void onRAUW(ExtraData Map, KeyT Old, KeyT New) {
+ (*Map)->erase(Old);
+ }
+ static void onDelete(ExtraData Map, KeyT Old) {
+ (*Map)->erase(Old);
+ }
+};
+TYPED_TEST(ValueMapTest, SurvivesModificationByConfig) {
+ ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > *MapAddress;
+ ValueMap<TypeParam*, int, ModifyingConfig<TypeParam*> > VM(&MapAddress);
+ MapAddress = &VM;
+ // Now the ModifyingConfig can modify the Map inside a callback.
+ VM[this->BitcastV.get()] = 7;
+ this->BitcastV->replaceAllUsesWith(this->AddV.get());
+ EXPECT_EQ(0u, VM.count(this->BitcastV.get()));
+ EXPECT_EQ(0u, VM.count(this->AddV.get()));
+ VM[this->AddV.get()] = 7;
+ this->AddV.reset();
+ EXPECT_EQ(0u, VM.count(this->AddV.get()));
+}
+
+}
diff --git a/gnu/llvm/unittests/IR/ValueTest.cpp b/gnu/llvm/unittests/IR/ValueTest.cpp
new file mode 100644
index 00000000000..9cf1306dae6
--- /dev/null
+++ b/gnu/llvm/unittests/IR/ValueTest.cpp
@@ -0,0 +1,238 @@
+//===- llvm/unittest/IR/ValueTest.cpp - Value 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/AsmParser/Parser.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSlotTracker.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+
+namespace {
+
+TEST(ValueTest, UsedInBasicBlock) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "bb0:\n"
+ " %y1 = add i32 %y, 1\n"
+ " %y2 = add i32 %y, 1\n"
+ " %y3 = add i32 %y, 1\n"
+ " %y4 = add i32 %y, 1\n"
+ " %y5 = add i32 %y, 1\n"
+ " %y6 = add i32 %y, 1\n"
+ " %y7 = add i32 %y, 1\n"
+ " %y8 = add i32 %x, 1\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f");
+
+ EXPECT_FALSE(F->isUsedInBasicBlock(&F->front()));
+ EXPECT_TRUE((++F->arg_begin())->isUsedInBasicBlock(&F->front()));
+ EXPECT_TRUE(F->arg_begin()->isUsedInBasicBlock(&F->front()));
+}
+
+TEST(GlobalTest, CreateAddressSpace) {
+ LLVMContext &Ctx = getGlobalContext();
+ std::unique_ptr<Module> M(new Module("TestModule", Ctx));
+ Type *Int8Ty = Type::getInt8Ty(Ctx);
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+
+ GlobalVariable *Dummy0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy",
+ nullptr,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ EXPECT_TRUE(Value::MaximumAlignment == 536870912U);
+ Dummy0->setAlignment(536870912U);
+ EXPECT_EQ(Dummy0->getAlignment(), 536870912U);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *Dummy1 = M->getOrInsertGlobal("dummy", Int32Ty);
+ EXPECT_EQ(Dummy0, Dummy1);
+ EXPECT_EQ(1u, Dummy1->getType()->getPointerAddressSpace());
+
+
+ // This one requires a bitcast, but the address space must also stay the same.
+ GlobalVariable *DummyCast0
+ = new GlobalVariable(*M,
+ Int32Ty,
+ true,
+ GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty),
+ "dummy_cast",
+ nullptr,
+ GlobalVariable::NotThreadLocal,
+ 1);
+
+ // Make sure the address space isn't dropped when returning this.
+ Constant *DummyCast1 = M->getOrInsertGlobal("dummy_cast", Int8Ty);
+ EXPECT_EQ(1u, DummyCast1->getType()->getPointerAddressSpace());
+ EXPECT_NE(DummyCast0, DummyCast1) << *DummyCast1;
+}
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+TEST(GlobalTest, AlignDeath) {
+ LLVMContext &Ctx = getGlobalContext();
+ std::unique_ptr<Module> M(new Module("TestModule", Ctx));
+ Type *Int32Ty = Type::getInt32Ty(Ctx);
+ GlobalVariable *Var =
+ new GlobalVariable(*M, Int32Ty, true, GlobalValue::ExternalLinkage,
+ Constant::getAllOnesValue(Int32Ty), "var", nullptr,
+ GlobalVariable::NotThreadLocal, 1);
+
+ EXPECT_DEATH(Var->setAlignment(536870913U), "Alignment is not a power of 2");
+ EXPECT_DEATH(Var->setAlignment(1073741824U),
+ "Alignment is greater than MaximumAlignment");
+}
+#endif
+#endif
+
+TEST(ValueTest, printSlots) {
+ // Check that Value::print() and Value::printAsOperand() work with and
+ // without a slot tracker.
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "entry:\n"
+ " %0 = add i32 %y, 1\n"
+ " %1 = add i32 %y, 1\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f");
+ ASSERT_TRUE(F);
+ ASSERT_FALSE(F->empty());
+ BasicBlock &BB = F->getEntryBlock();
+ ASSERT_EQ(3u, BB.size());
+
+ Instruction *I0 = &*BB.begin();
+ ASSERT_TRUE(I0);
+ Instruction *I1 = &*++BB.begin();
+ ASSERT_TRUE(I1);
+
+ ModuleSlotTracker MST(M.get());
+
+#define CHECK_PRINT(INST, STR) \
+ do { \
+ { \
+ std::string S; \
+ raw_string_ostream OS(S); \
+ INST->print(OS); \
+ EXPECT_EQ(STR, OS.str()); \
+ } \
+ { \
+ std::string S; \
+ raw_string_ostream OS(S); \
+ INST->print(OS, MST); \
+ EXPECT_EQ(STR, OS.str()); \
+ } \
+ } while (false)
+ CHECK_PRINT(I0, " %0 = add i32 %y, 1");
+ CHECK_PRINT(I1, " %1 = add i32 %y, 1");
+#undef CHECK_PRINT
+
+#define CHECK_PRINT_AS_OPERAND(INST, TYPE, STR) \
+ do { \
+ { \
+ std::string S; \
+ raw_string_ostream OS(S); \
+ INST->printAsOperand(OS, TYPE); \
+ EXPECT_EQ(StringRef(STR), StringRef(OS.str())); \
+ } \
+ { \
+ std::string S; \
+ raw_string_ostream OS(S); \
+ INST->printAsOperand(OS, TYPE, MST); \
+ EXPECT_EQ(StringRef(STR), StringRef(OS.str())); \
+ } \
+ } while (false)
+ CHECK_PRINT_AS_OPERAND(I0, false, "%0");
+ CHECK_PRINT_AS_OPERAND(I1, false, "%1");
+ CHECK_PRINT_AS_OPERAND(I0, true, "i32 %0");
+ CHECK_PRINT_AS_OPERAND(I1, true, "i32 %1");
+#undef CHECK_PRINT_AS_OPERAND
+}
+
+TEST(ValueTest, getLocalSlots) {
+ // Verify that the getLocalSlot method returns the correct slot numbers.
+ LLVMContext C;
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "entry:\n"
+ " %0 = add i32 %y, 1\n"
+ " %1 = add i32 %y, 1\n"
+ " br label %2\n"
+ "\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f");
+ ASSERT_TRUE(F);
+ ASSERT_FALSE(F->empty());
+ BasicBlock &EntryBB = F->getEntryBlock();
+ ASSERT_EQ(3u, EntryBB.size());
+ BasicBlock *BB2 = &*++F->begin();
+ ASSERT_TRUE(BB2);
+
+ Instruction *I0 = &*EntryBB.begin();
+ ASSERT_TRUE(I0);
+ Instruction *I1 = &*++EntryBB.begin();
+ ASSERT_TRUE(I1);
+
+ ModuleSlotTracker MST(M.get());
+ MST.incorporateFunction(*F);
+ EXPECT_EQ(MST.getLocalSlot(I0), 0);
+ EXPECT_EQ(MST.getLocalSlot(I1), 1);
+ EXPECT_EQ(MST.getLocalSlot(&EntryBB), -1);
+ EXPECT_EQ(MST.getLocalSlot(BB2), 2);
+}
+
+#if defined(GTEST_HAS_DEATH_TEST) && !defined(NDEBUG)
+TEST(ValueTest, getLocalSlotDeath) {
+ LLVMContext C;
+ const char *ModuleString = "define void @f(i32 %x, i32 %y) {\n"
+ "entry:\n"
+ " %0 = add i32 %y, 1\n"
+ " %1 = add i32 %y, 1\n"
+ " br label %2\n"
+ "\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f");
+ ASSERT_TRUE(F);
+ ASSERT_FALSE(F->empty());
+ BasicBlock *BB2 = &*++F->begin();
+ ASSERT_TRUE(BB2);
+
+ ModuleSlotTracker MST(M.get());
+ EXPECT_DEATH(MST.getLocalSlot(BB2), "No function incorporated");
+}
+#endif
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/IR/VerifierTest.cpp b/gnu/llvm/unittests/IR/VerifierTest.cpp
new file mode 100644
index 00000000000..4e94b4375f9
--- /dev/null
+++ b/gnu/llvm/unittests/IR/VerifierTest.cpp
@@ -0,0 +1,111 @@
+//===- llvm/unittest/IR/VerifierTest.cpp - Verifier 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/IR/Verifier.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace {
+
+TEST(VerifierTest, Branch_i1) {
+ LLVMContext &C = getGlobalContext();
+ Module M("M", C);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
+ Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
+ BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
+ BasicBlock *Exit = BasicBlock::Create(C, "exit", F);
+ ReturnInst::Create(C, Exit);
+
+ // To avoid triggering an assertion in BranchInst::Create, we first create
+ // a branch with an 'i1' condition ...
+
+ Constant *False = ConstantInt::getFalse(C);
+ BranchInst *BI = BranchInst::Create(Exit, Exit, False, Entry);
+
+ // ... then use setOperand to redirect it to a value of different type.
+
+ Constant *Zero32 = ConstantInt::get(IntegerType::get(C, 32), 0);
+ BI->setOperand(0, Zero32);
+
+ EXPECT_TRUE(verifyFunction(*F));
+}
+
+TEST(VerifierTest, InvalidRetAttribute) {
+ LLVMContext &C = getGlobalContext();
+ Module M("M", C);
+ FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
+ Function *F = cast<Function>(M.getOrInsertFunction("foo", FTy));
+ AttributeSet AS = F->getAttributes();
+ F->setAttributes(AS.addAttribute(C, AttributeSet::ReturnIndex,
+ Attribute::UWTable));
+
+ std::string Error;
+ raw_string_ostream ErrorOS(Error);
+ EXPECT_TRUE(verifyModule(M, &ErrorOS));
+ EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
+ "Attribute 'uwtable' only applies to functions!"));
+}
+
+TEST(VerifierTest, CrossModuleRef) {
+ LLVMContext &C = getGlobalContext();
+ Module M1("M1", C);
+ Module M2("M2", C);
+ Module M3("M2", C);
+ FunctionType *FTy = FunctionType::get(Type::getInt32Ty(C), /*isVarArg=*/false);
+ Function *F1 = cast<Function>(M1.getOrInsertFunction("foo1", FTy));
+ Function *F2 = cast<Function>(M2.getOrInsertFunction("foo2", FTy));
+ Function *F3 = cast<Function>(M3.getOrInsertFunction("foo3", FTy));
+
+ BasicBlock *Entry1 = BasicBlock::Create(C, "entry", F1);
+ BasicBlock *Entry3 = BasicBlock::Create(C, "entry", F3);
+
+ // BAD: Referencing function in another module
+ CallInst::Create(F2,"call",Entry1);
+
+ // BAD: Referencing personality routine in another module
+ F3->setPersonalityFn(F2);
+
+ // Fill in the body
+ Constant *ConstZero = ConstantInt::get(Type::getInt32Ty(C), 0);
+ ReturnInst::Create(C, ConstZero, Entry1);
+ ReturnInst::Create(C, ConstZero, Entry3);
+
+ std::string Error;
+ raw_string_ostream ErrorOS(Error);
+ EXPECT_FALSE(verifyModule(M2, &ErrorOS));
+ EXPECT_TRUE(verifyModule(M1, &ErrorOS));
+ EXPECT_TRUE(StringRef(ErrorOS.str()).equals(
+ "Referencing function in another module!\n"
+ " %call = call i32 @foo2()\n"
+ "; ModuleID = 'M1'\n"
+ "i32 ()* @foo2\n"
+ "; ModuleID = 'M2'\n"));
+
+ Error.clear();
+ EXPECT_TRUE(verifyModule(M3, &ErrorOS));
+ EXPECT_TRUE(StringRef(ErrorOS.str()).startswith(
+ "Referencing personality function in another module!"));
+
+ // Erase bad methods to avoid triggering an assertion failure on destruction
+ F1->eraseFromParent();
+ F3->eraseFromParent();
+}
+
+
+
+}
+}
diff --git a/gnu/llvm/unittests/IR/WaymarkTest.cpp b/gnu/llvm/unittests/IR/WaymarkTest.cpp
new file mode 100644
index 00000000000..a8924efed3f
--- /dev/null
+++ b/gnu/llvm/unittests/IR/WaymarkTest.cpp
@@ -0,0 +1,58 @@
+//===- llvm/unittest/IR/WaymarkTest.cpp - getUser() unit tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// we perform white-box tests
+//
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+#include <algorithm>
+
+namespace llvm {
+namespace {
+
+Constant *char2constant(char c) {
+ return ConstantInt::get(Type::getInt8Ty(getGlobalContext()), c);
+}
+
+
+TEST(WaymarkTest, NativeArray) {
+ static uint8_t tail[22] = "s02s33s30y2y0s1x0syxS";
+ Value * values[22];
+ std::transform(tail, tail + 22, values, char2constant);
+ FunctionType *FT = FunctionType::get(Type::getVoidTy(getGlobalContext()), true);
+ std::unique_ptr<Function> F(
+ Function::Create(FT, GlobalValue::ExternalLinkage));
+ const CallInst *A = CallInst::Create(F.get(), makeArrayRef(values));
+ ASSERT_NE(A, (const CallInst*)nullptr);
+ ASSERT_EQ(1U + 22, A->getNumOperands());
+ const Use *U = &A->getOperandUse(0);
+ const Use *Ue = &A->getOperandUse(22);
+ for (; U != Ue; ++U)
+ {
+ EXPECT_EQ(A, U->getUser());
+ }
+ delete A;
+}
+
+TEST(WaymarkTest, TwoBit) {
+ Use* many = (Use*)calloc(sizeof(Use), 8212 + 1);
+ ASSERT_TRUE(many);
+ Use::initTags(many, many + 8212);
+ for (Use *U = many, *Ue = many + 8212 - 1; U != Ue; ++U)
+ {
+ EXPECT_EQ(reinterpret_cast<User *>(Ue + 1), U->getUser());
+ }
+ free(many);
+}
+
+} // end anonymous namespace
+} // end namespace llvm
diff --git a/gnu/llvm/unittests/LineEditor/CMakeLists.txt b/gnu/llvm/unittests/LineEditor/CMakeLists.txt
new file mode 100644
index 00000000000..70d7497fed9
--- /dev/null
+++ b/gnu/llvm/unittests/LineEditor/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS
+ LineEditor
+ Support
+ )
+
+add_llvm_unittest(LineEditorTests
+ LineEditor.cpp
+ )
diff --git a/gnu/llvm/unittests/LineEditor/LineEditor.cpp b/gnu/llvm/unittests/LineEditor/LineEditor.cpp
new file mode 100644
index 00000000000..4d9081fd5c2
--- /dev/null
+++ b/gnu/llvm/unittests/LineEditor/LineEditor.cpp
@@ -0,0 +1,83 @@
+//===-- LineEditor.cpp ----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/LineEditor/LineEditor.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+class LineEditorTest : public testing::Test {
+public:
+ SmallString<64> HistPath;
+ LineEditor *LE;
+
+ LineEditorTest() {
+ init();
+ }
+
+ void init() {
+ sys::fs::createTemporaryFile("temp", "history", HistPath);
+ ASSERT_FALSE(HistPath.empty());
+ LE = new LineEditor("test", HistPath);
+ }
+
+ ~LineEditorTest() override {
+ delete LE;
+ sys::fs::remove(HistPath.str());
+ }
+};
+
+TEST_F(LineEditorTest, HistorySaveLoad) {
+ LE->saveHistory();
+ LE->loadHistory();
+}
+
+struct TestListCompleter {
+ std::vector<LineEditor::Completion> Completions;
+
+ TestListCompleter(const std::vector<LineEditor::Completion> &Completions)
+ : Completions(Completions) {}
+
+ std::vector<LineEditor::Completion> operator()(StringRef Buffer,
+ size_t Pos) const {
+ EXPECT_TRUE(Buffer.empty());
+ EXPECT_EQ(0u, Pos);
+ return Completions;
+ }
+};
+
+TEST_F(LineEditorTest, ListCompleters) {
+ std::vector<LineEditor::Completion> Comps;
+
+ Comps.push_back(LineEditor::Completion("foo", "int foo()"));
+ LE->setListCompleter(TestListCompleter(Comps));
+ LineEditor::CompletionAction CA = LE->getCompletionAction("", 0);
+ EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind);
+ EXPECT_EQ("foo", CA.Text);
+
+ Comps.push_back(LineEditor::Completion("bar", "int bar()"));
+ LE->setListCompleter(TestListCompleter(Comps));
+ CA = LE->getCompletionAction("", 0);
+ EXPECT_EQ(LineEditor::CompletionAction::AK_ShowCompletions, CA.Kind);
+ ASSERT_EQ(2u, CA.Completions.size());
+ ASSERT_EQ("int foo()", CA.Completions[0]);
+ ASSERT_EQ("int bar()", CA.Completions[1]);
+
+ Comps.clear();
+ Comps.push_back(LineEditor::Completion("fee", "int fee()"));
+ Comps.push_back(LineEditor::Completion("fi", "int fi()"));
+ Comps.push_back(LineEditor::Completion("foe", "int foe()"));
+ Comps.push_back(LineEditor::Completion("fum", "int fum()"));
+ LE->setListCompleter(TestListCompleter(Comps));
+ CA = LE->getCompletionAction("", 0);
+ EXPECT_EQ(LineEditor::CompletionAction::AK_Insert, CA.Kind);
+ EXPECT_EQ("f", CA.Text);
+}
diff --git a/gnu/llvm/unittests/LineEditor/Makefile b/gnu/llvm/unittests/LineEditor/Makefile
new file mode 100644
index 00000000000..058b6e46eb9
--- /dev/null
+++ b/gnu/llvm/unittests/LineEditor/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/LineEditor/Makefile -----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = LineEditor
+LINK_COMPONENTS := lineeditor
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Linker/CMakeLists.txt b/gnu/llvm/unittests/Linker/CMakeLists.txt
new file mode 100644
index 00000000000..05f45c0a8ce
--- /dev/null
+++ b/gnu/llvm/unittests/Linker/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS
+ AsmParser
+ core
+ linker
+ )
+
+set(LinkerSources
+ LinkModulesTest.cpp
+ )
+
+add_llvm_unittest(LinkerTests
+ ${LinkerSources}
+ )
diff --git a/gnu/llvm/unittests/Linker/LinkModulesTest.cpp b/gnu/llvm/unittests/Linker/LinkModulesTest.cpp
new file mode 100644
index 00000000000..322a44f8aaf
--- /dev/null
+++ b/gnu/llvm/unittests/Linker/LinkModulesTest.cpp
@@ -0,0 +1,333 @@
+//===- llvm/unittest/Linker/LinkModulesTest.cpp - IRBuilder 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 "llvm/AsmParser/Parser.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Linker/Linker.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm-c/Core.h"
+#include "llvm-c/Linker.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class LinkModuleTest : public testing::Test {
+protected:
+ void SetUp() override {
+ M.reset(new Module("MyModule", Ctx));
+ FunctionType *FTy = FunctionType::get(
+ Type::getInt8PtrTy(Ctx), Type::getInt32Ty(Ctx), false /*=isVarArg*/);
+ F = Function::Create(FTy, Function::ExternalLinkage, "ba_func", M.get());
+ F->setCallingConv(CallingConv::C);
+
+ EntryBB = BasicBlock::Create(Ctx, "entry", F);
+ SwitchCase1BB = BasicBlock::Create(Ctx, "switch.case.1", F);
+ SwitchCase2BB = BasicBlock::Create(Ctx, "switch.case.2", F);
+ ExitBB = BasicBlock::Create(Ctx, "exit", F);
+
+ AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
+
+ GV = new GlobalVariable(*M.get(), AT, false /*=isConstant*/,
+ GlobalValue::InternalLinkage, nullptr,"switch.bas");
+
+ // Global Initializer
+ std::vector<Constant *> Init;
+ Constant *SwitchCase1BA = BlockAddress::get(SwitchCase1BB);
+ Init.push_back(SwitchCase1BA);
+
+ Constant *SwitchCase2BA = BlockAddress::get(SwitchCase2BB);
+ Init.push_back(SwitchCase2BA);
+
+ ConstantInt *One = ConstantInt::get(Type::getInt32Ty(Ctx), 1);
+ Constant *OnePtr = ConstantExpr::getCast(Instruction::IntToPtr, One,
+ Type::getInt8PtrTy(Ctx));
+ Init.push_back(OnePtr);
+
+ GV->setInitializer(ConstantArray::get(AT, Init));
+ }
+
+ void TearDown() override { M.reset(); }
+
+ LLVMContext Ctx;
+ std::unique_ptr<Module> M;
+ Function *F;
+ ArrayType *AT;
+ GlobalVariable *GV;
+ BasicBlock *EntryBB;
+ BasicBlock *SwitchCase1BB;
+ BasicBlock *SwitchCase2BB;
+ BasicBlock *ExitBB;
+};
+
+static void expectNoDiags(const DiagnosticInfo &DI, void *C) {
+ EXPECT_TRUE(false);
+}
+
+TEST_F(LinkModuleTest, BlockAddress) {
+ IRBuilder<> Builder(EntryBB);
+
+ std::vector<Value *> GEPIndices;
+ GEPIndices.push_back(ConstantInt::get(Type::getInt32Ty(Ctx), 0));
+ GEPIndices.push_back(&*F->arg_begin());
+
+ Value *GEP = Builder.CreateGEP(AT, GV, GEPIndices, "switch.gep");
+ Value *Load = Builder.CreateLoad(GEP, "switch.load");
+
+ Builder.CreateRet(Load);
+
+ Builder.SetInsertPoint(SwitchCase1BB);
+ Builder.CreateBr(ExitBB);
+
+ Builder.SetInsertPoint(SwitchCase2BB);
+ Builder.CreateBr(ExitBB);
+
+ Builder.SetInsertPoint(ExitBB);
+ Builder.CreateRet(ConstantPointerNull::get(Type::getInt8PtrTy(Ctx)));
+
+ Module *LinkedModule = new Module("MyModuleLinked", Ctx);
+ Ctx.setDiagnosticHandler(expectNoDiags);
+ Linker::linkModules(*LinkedModule, std::move(M));
+
+ // Check that the global "@switch.bas" is well-formed.
+ const GlobalVariable *LinkedGV = LinkedModule->getNamedGlobal("switch.bas");
+ const Constant *Init = LinkedGV->getInitializer();
+
+ // @switch.bas = internal global [3 x i8*]
+ // [i8* blockaddress(@ba_func, %switch.case.1),
+ // i8* blockaddress(@ba_func, %switch.case.2),
+ // i8* inttoptr (i32 1 to i8*)]
+
+ ArrayType *AT = ArrayType::get(Type::getInt8PtrTy(Ctx), 3);
+ EXPECT_EQ(AT, Init->getType());
+
+ Value *Elem = Init->getOperand(0);
+ ASSERT_TRUE(isa<BlockAddress>(Elem));
+ EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(),
+ LinkedModule->getFunction("ba_func"));
+ EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(),
+ LinkedModule->getFunction("ba_func"));
+
+ Elem = Init->getOperand(1);
+ ASSERT_TRUE(isa<BlockAddress>(Elem));
+ EXPECT_EQ(cast<BlockAddress>(Elem)->getFunction(),
+ LinkedModule->getFunction("ba_func"));
+ EXPECT_EQ(cast<BlockAddress>(Elem)->getBasicBlock()->getParent(),
+ LinkedModule->getFunction("ba_func"));
+
+ delete LinkedModule;
+}
+
+static Module *getExternal(LLVMContext &Ctx, StringRef FuncName) {
+ // Create a module with an empty externally-linked function
+ Module *M = new Module("ExternalModule", Ctx);
+ FunctionType *FTy = FunctionType::get(
+ Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
+
+ Function *F =
+ Function::Create(FTy, Function::ExternalLinkage, FuncName, M);
+ F->setCallingConv(CallingConv::C);
+
+ BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
+ IRBuilder<> Builder(BB);
+ Builder.CreateRetVoid();
+ return M;
+}
+
+static Module *getInternal(LLVMContext &Ctx) {
+ Module *InternalM = new Module("InternalModule", Ctx);
+ FunctionType *FTy = FunctionType::get(
+ Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false /*=isVarArgs*/);
+
+ Function *F =
+ Function::Create(FTy, Function::InternalLinkage, "bar", InternalM);
+ F->setCallingConv(CallingConv::C);
+
+ BasicBlock *BB = BasicBlock::Create(Ctx, "", F);
+ IRBuilder<> Builder(BB);
+ Builder.CreateRetVoid();
+
+ StructType *STy = StructType::create(Ctx, PointerType::get(FTy, 0));
+
+ GlobalVariable *GV =
+ new GlobalVariable(*InternalM, STy, false /*=isConstant*/,
+ GlobalValue::InternalLinkage, nullptr, "g");
+
+ GV->setInitializer(ConstantStruct::get(STy, F));
+ return InternalM;
+}
+
+TEST_F(LinkModuleTest, EmptyModule) {
+ std::unique_ptr<Module> InternalM(getInternal(Ctx));
+ std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
+ Ctx.setDiagnosticHandler(expectNoDiags);
+ Linker::linkModules(*EmptyM, std::move(InternalM));
+}
+
+TEST_F(LinkModuleTest, EmptyModule2) {
+ std::unique_ptr<Module> InternalM(getInternal(Ctx));
+ std::unique_ptr<Module> EmptyM(new Module("EmptyModule1", Ctx));
+ Ctx.setDiagnosticHandler(expectNoDiags);
+ Linker::linkModules(*InternalM, std::move(EmptyM));
+}
+
+TEST_F(LinkModuleTest, TypeMerge) {
+ LLVMContext C;
+ SMDiagnostic Err;
+
+ const char *M1Str = "%t = type {i32}\n"
+ "@t1 = weak global %t zeroinitializer\n";
+ std::unique_ptr<Module> M1 = parseAssemblyString(M1Str, Err, C);
+
+ const char *M2Str = "%t = type {i32}\n"
+ "@t2 = weak global %t zeroinitializer\n";
+ std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, C);
+
+ Ctx.setDiagnosticHandler(expectNoDiags);
+ Linker::linkModules(*M1, std::move(M2));
+
+ EXPECT_EQ(M1->getNamedGlobal("t1")->getType(),
+ M1->getNamedGlobal("t2")->getType());
+}
+
+TEST_F(LinkModuleTest, CAPISuccess) {
+ std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+ std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
+ char *errout = nullptr;
+ LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+ LLVMLinkerDestroySource, &errout);
+ EXPECT_EQ(0, result);
+ EXPECT_EQ(nullptr, errout);
+ // "bar" is present in destination module
+ EXPECT_NE(nullptr, DestM->getFunction("bar"));
+}
+
+TEST_F(LinkModuleTest, CAPIFailure) {
+ // Symbol clash between two modules
+ std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+ std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
+ char *errout = nullptr;
+ LLVMBool result = LLVMLinkModules(wrap(DestM.get()), wrap(SourceM.get()),
+ LLVMLinkerDestroySource, &errout);
+ EXPECT_EQ(1, result);
+ EXPECT_STREQ("Linking globals named 'foo': symbol multiply defined!", errout);
+ LLVMDisposeMessage(errout);
+}
+
+TEST_F(LinkModuleTest, NewCAPISuccess) {
+ std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+ std::unique_ptr<Module> SourceM(getExternal(Ctx, "bar"));
+ LLVMBool Result =
+ LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release()));
+ EXPECT_EQ(0, Result);
+ // "bar" is present in destination module
+ EXPECT_NE(nullptr, DestM->getFunction("bar"));
+}
+
+static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) {
+ auto *Err = reinterpret_cast<std::string *>(C);
+ char *CErr = LLVMGetDiagInfoDescription(DI);
+ *Err = CErr;
+ LLVMDisposeMessage(CErr);
+}
+
+TEST_F(LinkModuleTest, NewCAPIFailure) {
+ // Symbol clash between two modules
+ LLVMContext Ctx;
+ std::string Err;
+ LLVMContextSetDiagnosticHandler(wrap(&Ctx), diagnosticHandler, &Err);
+
+ std::unique_ptr<Module> DestM(getExternal(Ctx, "foo"));
+ std::unique_ptr<Module> SourceM(getExternal(Ctx, "foo"));
+ LLVMBool Result =
+ LLVMLinkModules2(wrap(DestM.get()), wrap(SourceM.release()));
+ EXPECT_EQ(1, Result);
+ EXPECT_EQ("Linking globals named 'foo': symbol multiply defined!", Err);
+}
+
+TEST_F(LinkModuleTest, MoveDistinctMDs) {
+ LLVMContext C;
+ SMDiagnostic Err;
+
+ const char *SrcStr = "define void @foo() !attach !0 {\n"
+ "entry:\n"
+ " call void @llvm.md(metadata !1)\n"
+ " ret void, !attach !2\n"
+ "}\n"
+ "declare void @llvm.md(metadata)\n"
+ "!named = !{!3, !4}\n"
+ "!0 = distinct !{}\n"
+ "!1 = distinct !{}\n"
+ "!2 = distinct !{}\n"
+ "!3 = distinct !{}\n"
+ "!4 = !{!3}\n";
+
+ std::unique_ptr<Module> Src = parseAssemblyString(SrcStr, Err, C);
+ assert(Src);
+ ASSERT_TRUE(Src.get());
+
+ // Get the addresses of the Metadata before merging.
+ Function *F = &*Src->begin();
+ ASSERT_EQ("foo", F->getName());
+ BasicBlock *BB = &F->getEntryBlock();
+ auto *CI = cast<CallInst>(&BB->front());
+ auto *RI = cast<ReturnInst>(BB->getTerminator());
+ NamedMDNode *NMD = &*Src->named_metadata_begin();
+
+ MDNode *M0 = F->getMetadata("attach");
+ MDNode *M1 =
+ cast<MDNode>(cast<MetadataAsValue>(CI->getArgOperand(0))->getMetadata());
+ MDNode *M2 = RI->getMetadata("attach");
+ MDNode *M3 = NMD->getOperand(0);
+ MDNode *M4 = NMD->getOperand(1);
+
+ // Confirm a few things about the IR.
+ EXPECT_TRUE(M0->isDistinct());
+ EXPECT_TRUE(M1->isDistinct());
+ EXPECT_TRUE(M2->isDistinct());
+ EXPECT_TRUE(M3->isDistinct());
+ EXPECT_TRUE(M4->isUniqued());
+ EXPECT_EQ(M3, M4->getOperand(0));
+
+ // Link into destination module.
+ auto Dst = llvm::make_unique<Module>("Linked", C);
+ ASSERT_TRUE(Dst.get());
+ Ctx.setDiagnosticHandler(expectNoDiags);
+ Linker::linkModules(*Dst, std::move(Src));
+
+ // Check that distinct metadata was moved, not cloned. Even !4, the uniqued
+ // node, should effectively be moved, since its only operand hasn't changed.
+ F = &*Dst->begin();
+ BB = &F->getEntryBlock();
+ CI = cast<CallInst>(&BB->front());
+ RI = cast<ReturnInst>(BB->getTerminator());
+ NMD = &*Dst->named_metadata_begin();
+
+ EXPECT_EQ(M0, F->getMetadata("attach"));
+ EXPECT_EQ(M1, cast<MetadataAsValue>(CI->getArgOperand(0))->getMetadata());
+ EXPECT_EQ(M2, RI->getMetadata("attach"));
+ EXPECT_EQ(M3, NMD->getOperand(0));
+ EXPECT_EQ(M4, NMD->getOperand(1));
+
+ // Confirm a few things about the IR. This shouldn't have changed.
+ EXPECT_TRUE(M0->isDistinct());
+ EXPECT_TRUE(M1->isDistinct());
+ EXPECT_TRUE(M2->isDistinct());
+ EXPECT_TRUE(M3->isDistinct());
+ EXPECT_TRUE(M4->isUniqued());
+ EXPECT_EQ(M3, M4->getOperand(0));
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Linker/Makefile b/gnu/llvm/unittests/Linker/Makefile
new file mode 100644
index 00000000000..ddbce07d4a4
--- /dev/null
+++ b/gnu/llvm/unittests/Linker/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Linker/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = Linker
+LINK_COMPONENTS := core linker asmparser
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/MC/CMakeLists.txt b/gnu/llvm/unittests/MC/CMakeLists.txt
new file mode 100644
index 00000000000..f83eaf4779f
--- /dev/null
+++ b/gnu/llvm/unittests/MC/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ MC
+ MCDisassembler
+ Support
+ )
+
+add_llvm_unittest(MCTests
+ Disassembler.cpp
+ StringTableBuilderTest.cpp
+ YAMLTest.cpp
+ )
diff --git a/gnu/llvm/unittests/MC/Disassembler.cpp b/gnu/llvm/unittests/MC/Disassembler.cpp
new file mode 100644
index 00000000000..dd0f1ef9ace
--- /dev/null
+++ b/gnu/llvm/unittests/MC/Disassembler.cpp
@@ -0,0 +1,64 @@
+//===- llvm/unittest/Object/Disassembler.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm-c/Disassembler.h"
+#include "llvm/Support/TargetSelect.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+static const char *symbolLookupCallback(void *DisInfo, uint64_t ReferenceValue,
+ uint64_t *ReferenceType,
+ uint64_t ReferencePC,
+ const char **ReferenceName) {
+ *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None;
+ return nullptr;
+}
+
+TEST(Disassembler, Test1) {
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllDisassemblers();
+
+ uint8_t Bytes[] = {0x90, 0x90, 0xeb, 0xfd};
+ uint8_t *BytesP = Bytes;
+ const char OutStringSize = 100;
+ char OutString[OutStringSize];
+ LLVMDisasmContextRef DCR = LLVMCreateDisasm("x86_64-pc-linux", nullptr, 0,
+ nullptr, symbolLookupCallback);
+ if (!DCR)
+ return;
+
+ size_t InstSize;
+ unsigned NumBytes = sizeof(Bytes);
+ unsigned PC = 0;
+
+ InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,
+ OutStringSize);
+ EXPECT_EQ(InstSize, 1U);
+ EXPECT_EQ(StringRef(OutString), "\tnop");
+ PC += InstSize;
+ BytesP += InstSize;
+ NumBytes -= InstSize;
+
+ InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,
+ OutStringSize);
+ EXPECT_EQ(InstSize, 1U);
+ EXPECT_EQ(StringRef(OutString), "\tnop");
+ PC += InstSize;
+ BytesP += InstSize;
+ NumBytes -= InstSize;
+
+ InstSize = LLVMDisasmInstruction(DCR, BytesP, NumBytes, PC, OutString,
+ OutStringSize);
+ EXPECT_EQ(InstSize, 2U);
+ EXPECT_EQ(StringRef(OutString), "\tjmp\t0x1");
+
+ LLVMDisasmDispose(DCR);
+}
diff --git a/gnu/llvm/unittests/MC/Makefile b/gnu/llvm/unittests/MC/Makefile
new file mode 100644
index 00000000000..3f8d1ef9555
--- /dev/null
+++ b/gnu/llvm/unittests/MC/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/IR/Makefile -------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = MC
+LINK_COMPONENTS := all-targets MCDisassembler Object
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/MC/StringTableBuilderTest.cpp b/gnu/llvm/unittests/MC/StringTableBuilderTest.cpp
new file mode 100644
index 00000000000..4cc0bda0a03
--- /dev/null
+++ b/gnu/llvm/unittests/MC/StringTableBuilderTest.cpp
@@ -0,0 +1,71 @@
+//===----------- StringTableBuilderTest.cpp -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Endian.h"
+#include "gtest/gtest.h"
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+TEST(StringTableBuilderTest, BasicELF) {
+ StringTableBuilder B(StringTableBuilder::ELF);
+
+ B.add("foo");
+ B.add("bar");
+ B.add("foobar");
+
+ B.finalize();
+
+ std::string Expected;
+ Expected += '\x00';
+ Expected += "foobar";
+ Expected += '\x00';
+ Expected += "foo";
+ Expected += '\x00';
+
+ EXPECT_EQ(Expected, B.data());
+ EXPECT_EQ(1U, B.getOffset("foobar"));
+ EXPECT_EQ(4U, B.getOffset("bar"));
+ EXPECT_EQ(8U, B.getOffset("foo"));
+}
+
+TEST(StringTableBuilderTest, BasicWinCOFF) {
+ StringTableBuilder B(StringTableBuilder::WinCOFF);
+
+ // Strings must be 9 chars or longer to go in the table.
+ B.add("hippopotamus");
+ B.add("pygmy hippopotamus");
+ B.add("river horse");
+
+ B.finalize();
+
+ // size_field + "pygmy hippopotamus\0" + "river horse\0"
+ uint32_t ExpectedSize = 4 + 19 + 12;
+ EXPECT_EQ(ExpectedSize, B.data().size());
+
+ std::string Expected;
+
+ ExpectedSize =
+ support::endian::byte_swap<uint32_t, support::little>(ExpectedSize);
+ Expected.append((const char*)&ExpectedSize, 4);
+ Expected += "pygmy hippopotamus";
+ Expected += '\x00';
+ Expected += "river horse";
+ Expected += '\x00';
+
+ EXPECT_EQ(Expected, B.data());
+ EXPECT_EQ(4U, B.getOffset("pygmy hippopotamus"));
+ EXPECT_EQ(10U, B.getOffset("hippopotamus"));
+ EXPECT_EQ(23U, B.getOffset("river horse"));
+}
+
+}
diff --git a/gnu/llvm/unittests/MC/YAMLTest.cpp b/gnu/llvm/unittests/MC/YAMLTest.cpp
new file mode 100644
index 00000000000..09709ad73fc
--- /dev/null
+++ b/gnu/llvm/unittests/MC/YAMLTest.cpp
@@ -0,0 +1,38 @@
+//===- llvm/unittest/Object/YAMLTest.cpp - Tests for Object YAML ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/YAML.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+struct BinaryHolder {
+ yaml::BinaryRef Binary;
+};
+
+namespace llvm {
+namespace yaml {
+template <>
+struct MappingTraits<BinaryHolder> {
+ static void mapping(IO &IO, BinaryHolder &BH) {
+ IO.mapRequired("Binary", BH.Binary);
+ }
+};
+} // end namespace yaml
+} // end namespace llvm
+
+TEST(ObjectYAML, BinaryRef) {
+ BinaryHolder BH;
+ SmallVector<char, 32> Buf;
+ llvm::raw_svector_ostream OS(Buf);
+ yaml::Output YOut(OS);
+ YOut << BH;
+ EXPECT_NE(OS.str().find("''"), StringRef::npos);
+}
diff --git a/gnu/llvm/unittests/Makefile b/gnu/llvm/unittests/Makefile
new file mode 100644
index 00000000000..bf2ed22efea
--- /dev/null
+++ b/gnu/llvm/unittests/Makefile
@@ -0,0 +1,20 @@
+##===- unittests/Makefile ----------------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ..
+
+PARALLEL_DIRS = ADT Analysis AsmParser Bitcode CodeGen DebugInfo \
+ ExecutionEngine IR LineEditor Linker MC Option ProfileData \
+ Support Transforms
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+clean::
+ $(Verb) $(RM) -f *Tests
diff --git a/gnu/llvm/unittests/Makefile.unittest b/gnu/llvm/unittests/Makefile.unittest
new file mode 100644
index 00000000000..a39edc67569
--- /dev/null
+++ b/gnu/llvm/unittests/Makefile.unittest
@@ -0,0 +1,69 @@
+##===- unittests/Makefile.unittest -------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+#
+# This file is included by all of the unit test makefiles.
+#
+##===----------------------------------------------------------------------===##
+
+ifndef MAKEFILE_UNITTEST_NO_INCLUDE_COMMON
+include $(LEVEL)/Makefile.common
+endif
+
+# Clean up out-of-tree stray unittests for Lit not to pick one up.
+.PHONY: cleanup-local
+cleanup-local:
+ -$(Verb) $(FIND) $(filter-out $(PARALLEL_DIRS), $(wildcard *)) -type f \
+ -path '*/$(BuildMode)/*Tests$(EXEEXT)' \
+ -exec rm -f '{}' \;
+
+all:: cleanup-local
+clean:: cleanup-local
+
+# Set up variables for building a unit test.
+ifdef TESTNAME
+
+LLVMUnitTestExe = $(BuildMode)/$(TESTNAME)Tests$(EXEEXT)
+
+# Note that these flags are duplicated when building GoogleTest itself in
+# utils/unittest/googletest/Makefile; ensure that any changes are made to both.
+CPP.Flags += -I$(LLVM_SRC_ROOT)/utils/unittest/googletest/include
+CPP.Flags += $(NO_MISSING_FIELD_INITIALIZERS) $(NO_VARIADIC_MACROS)
+CPP.Flags += -DGTEST_HAS_RTTI=0
+# libstdc++'s TR1 <tuple> header depends on RTTI and uses C++'0x features not
+# supported by Clang, so force googletest to use its own tuple implementation.
+CPP.Flags += -DGTEST_USE_OWN_TR1_TUPLE
+
+# Disable pthreads if LLVM was configured without them.
+ifneq ($(HAVE_PTHREAD), 1)
+ CPP.Flags += -DGTEST_HAS_PTHREAD=0
+endif
+
+TESTLIBS = -lgtest -lgtest_main
+
+ifeq ($(ENABLE_SHARED), 1)
+ ifneq (,$(RPATH))
+ # Add the absolute path to the dynamic library. This is ok because
+ # we'll never install unittests.
+ LD.Flags += $(RPATH) -Wl,$(SharedLibDir)
+ endif
+endif
+
+$(LLVMUnitTestExe): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths)
+ $(Echo) Linking $(BuildMode) unit test $(TESTNAME) $(StripWarnMsg)
+ $(Verb) $(Link) -o $@ $(TOOLLINKOPTS) $(ObjectsO) $(ProjLibsOptions) \
+ $(TESTLIBS) $(LLVMLibsOptions) $(ExtraLibs) $(TOOLLINKOPTSB) $(LIBS)
+ $(Echo) ======= Finished Linking $(BuildMode) Unit test $(TESTNAME) \
+ $(StripWarnMsg)
+
+all:: $(LLVMUnitTestExe)
+
+unitcheck:: $(LLVMUnitTestExe)
+ $(LLVMUnitTestExe)
+
+endif
diff --git a/gnu/llvm/unittests/Option/CMakeLists.txt b/gnu/llvm/unittests/Option/CMakeLists.txt
new file mode 100644
index 00000000000..07f7b91d5f5
--- /dev/null
+++ b/gnu/llvm/unittests/Option/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS
+ Option
+ Support
+ )
+
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(OptsTestTableGen)
+
+add_llvm_unittest(OptionTests
+ OptionParsingTest.cpp
+ )
diff --git a/gnu/llvm/unittests/Option/Makefile b/gnu/llvm/unittests/Option/Makefile
new file mode 100644
index 00000000000..8c90a83da87
--- /dev/null
+++ b/gnu/llvm/unittests/Option/Makefile
@@ -0,0 +1,23 @@
+##===- unittests/Option/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = Option
+LINK_COMPONENTS := option support
+
+BUILT_SOURCES = Opts.inc
+TABLEGEN_INC_FILES_COMMON = 1
+
+include $(LEVEL)/Makefile.config
+
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+$(ObjDir)/Opts.inc.tmp : Opts.td $(LLVM_TBLGEN) $(ObjDir)/.dir
+ $(Echo) "Building Driver Option tables with tblgen"
+ $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
diff --git a/gnu/llvm/unittests/Option/OptionParsingTest.cpp b/gnu/llvm/unittests/Option/OptionParsingTest.cpp
new file mode 100644
index 00000000000..5270dc940f9
--- /dev/null
+++ b/gnu/llvm/unittests/Option/OptionParsingTest.cpp
@@ -0,0 +1,216 @@
+//===- unittest/Support/OptionParsingTest.cpp - OptTable 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 "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::opt;
+
+enum ID {
+ OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) OPT_##ID,
+#include "Opts.inc"
+ LastOption
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Opts.inc"
+#undef PREFIX
+
+enum OptionFlags {
+ OptFlag1 = (1 << 4),
+ OptFlag2 = (1 << 5),
+ OptFlag3 = (1 << 6)
+};
+
+static const OptTable::Info InfoTable[] = {
+#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
+ HELPTEXT, METAVAR) \
+ { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, Option::KIND##Class, PARAM, \
+ FLAGS, OPT_##GROUP, OPT_##ALIAS, ALIASARGS },
+#include "Opts.inc"
+#undef OPTION
+};
+
+namespace {
+class TestOptTable : public OptTable {
+public:
+ TestOptTable(bool IgnoreCase = false)
+ : OptTable(InfoTable, IgnoreCase) {}
+};
+}
+
+const char *Args[] = {
+ "-A",
+ "-Bhi",
+ "--C=desu",
+ "-C", "bye",
+ "-D,adena",
+ "-E", "apple", "bloom",
+ "-Fblarg",
+ "-F", "42",
+ "-Gchuu", "2"
+ };
+
+TEST(Option, OptionParsing) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+ InputArgList AL = T.ParseArgs(Args, MAI, MAC);
+
+ // Check they all exist.
+ EXPECT_TRUE(AL.hasArg(OPT_A));
+ EXPECT_TRUE(AL.hasArg(OPT_B));
+ EXPECT_TRUE(AL.hasArg(OPT_C));
+ EXPECT_TRUE(AL.hasArg(OPT_D));
+ EXPECT_TRUE(AL.hasArg(OPT_E));
+ EXPECT_TRUE(AL.hasArg(OPT_F));
+ EXPECT_TRUE(AL.hasArg(OPT_G));
+
+ // Check the values.
+ EXPECT_EQ(AL.getLastArgValue(OPT_B), "hi");
+ EXPECT_EQ(AL.getLastArgValue(OPT_C), "bye");
+ EXPECT_EQ(AL.getLastArgValue(OPT_D), "adena");
+ std::vector<std::string> Es = AL.getAllArgValues(OPT_E);
+ EXPECT_EQ(Es[0], "apple");
+ EXPECT_EQ(Es[1], "bloom");
+ EXPECT_EQ(AL.getLastArgValue(OPT_F), "42");
+ std::vector<std::string> Gs = AL.getAllArgValues(OPT_G);
+ EXPECT_EQ(Gs[0], "chuu");
+ EXPECT_EQ(Gs[1], "2");
+
+ // Check the help text.
+ std::string Help;
+ raw_string_ostream RSO(Help);
+ T.PrintHelp(RSO, "test", "title!");
+ EXPECT_NE(Help.find("-A"), std::string::npos);
+
+ // Test aliases.
+ arg_iterator Cs = AL.filtered_begin(OPT_C);
+ ASSERT_NE(Cs, AL.filtered_end());
+ EXPECT_EQ(StringRef((*Cs)->getValue()), "desu");
+ ArgStringList ASL;
+ (*Cs)->render(AL, ASL);
+ ASSERT_EQ(ASL.size(), 2u);
+ EXPECT_EQ(StringRef(ASL[0]), "-C");
+ EXPECT_EQ(StringRef(ASL[1]), "desu");
+}
+
+TEST(Option, ParseWithFlagExclusions) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ // Exclude flag3 to avoid parsing as OPT_SLASH_C.
+ InputArgList AL = T.ParseArgs(Args, MAI, MAC,
+ /*FlagsToInclude=*/0,
+ /*FlagsToExclude=*/OptFlag3);
+ EXPECT_TRUE(AL.hasArg(OPT_A));
+ EXPECT_TRUE(AL.hasArg(OPT_C));
+ EXPECT_FALSE(AL.hasArg(OPT_SLASH_C));
+
+ // Exclude flag1 to avoid parsing as OPT_C.
+ AL = T.ParseArgs(Args, MAI, MAC,
+ /*FlagsToInclude=*/0,
+ /*FlagsToExclude=*/OptFlag1);
+ EXPECT_TRUE(AL.hasArg(OPT_B));
+ EXPECT_FALSE(AL.hasArg(OPT_C));
+ EXPECT_TRUE(AL.hasArg(OPT_SLASH_C));
+
+ const char *NewArgs[] = { "/C", "foo", "--C=bar" };
+ AL = T.ParseArgs(NewArgs, MAI, MAC);
+ EXPECT_TRUE(AL.hasArg(OPT_SLASH_C));
+ EXPECT_TRUE(AL.hasArg(OPT_C));
+ EXPECT_EQ(AL.getLastArgValue(OPT_SLASH_C), "foo");
+ EXPECT_EQ(AL.getLastArgValue(OPT_C), "bar");
+}
+
+TEST(Option, ParseAliasInGroup) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-I" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_TRUE(AL.hasArg(OPT_H));
+}
+
+TEST(Option, AliasArgs) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-J", "-Joo" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_TRUE(AL.hasArg(OPT_B));
+ EXPECT_EQ(AL.getAllArgValues(OPT_B)[0], "foo");
+ EXPECT_EQ(AL.getAllArgValues(OPT_B)[1], "bar");
+}
+
+TEST(Option, IgnoreCase) {
+ TestOptTable T(true);
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-a", "-joo" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_TRUE(AL.hasArg(OPT_A));
+ EXPECT_TRUE(AL.hasArg(OPT_B));
+}
+
+TEST(Option, DoNotIgnoreCase) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-a", "-joo" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_FALSE(AL.hasArg(OPT_A));
+ EXPECT_FALSE(AL.hasArg(OPT_B));
+}
+
+TEST(Option, SlurpEmpty) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-A", "-slurp" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_TRUE(AL.hasArg(OPT_A));
+ EXPECT_TRUE(AL.hasArg(OPT_Slurp));
+ EXPECT_EQ(AL.getAllArgValues(OPT_Slurp).size(), 0U);
+}
+
+TEST(Option, Slurp) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ const char *MyArgs[] = { "-A", "-slurp", "-B", "--", "foo" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_EQ(AL.size(), 2U);
+ EXPECT_TRUE(AL.hasArg(OPT_A));
+ EXPECT_FALSE(AL.hasArg(OPT_B));
+ EXPECT_TRUE(AL.hasArg(OPT_Slurp));
+ EXPECT_EQ(AL.getAllArgValues(OPT_Slurp).size(), 3U);
+ EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[0], "-B");
+ EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[1], "--");
+ EXPECT_EQ(AL.getAllArgValues(OPT_Slurp)[2], "foo");
+}
+
+TEST(Option, FlagAliasToJoined) {
+ TestOptTable T;
+ unsigned MAI, MAC;
+
+ // Check that a flag alias provides an empty argument to a joined option.
+ const char *MyArgs[] = { "-K" };
+ InputArgList AL = T.ParseArgs(MyArgs, MAI, MAC);
+ EXPECT_EQ(AL.size(), 1U);
+ EXPECT_TRUE(AL.hasArg(OPT_B));
+ EXPECT_EQ(AL.getAllArgValues(OPT_B).size(), 1U);
+ EXPECT_EQ(AL.getAllArgValues(OPT_B)[0], "");
+}
diff --git a/gnu/llvm/unittests/Option/Opts.td b/gnu/llvm/unittests/Option/Opts.td
new file mode 100644
index 00000000000..c96774a68e0
--- /dev/null
+++ b/gnu/llvm/unittests/Option/Opts.td
@@ -0,0 +1,28 @@
+include "llvm/Option/OptParser.td"
+
+def OptFlag1 : OptionFlag;
+def OptFlag2 : OptionFlag;
+def OptFlag3 : OptionFlag;
+
+def A : Flag<["-"], "A">, HelpText<"The A option">, Flags<[OptFlag1]>;
+def B : Joined<["-"], "B">, HelpText<"The B option">, MetaVarName<"B">, Flags<[OptFlag2]>;
+def C : Separate<["-"], "C">, HelpText<"The C option">, MetaVarName<"C">, Flags<[OptFlag1]>;
+def SLASH_C : Separate<["/", "-"], "C">, HelpText<"The C option">, MetaVarName<"C">, Flags<[OptFlag3]>;
+def D : CommaJoined<["-"], "D">, HelpText<"The D option">, MetaVarName<"D">;
+def E : MultiArg<["-"], "E", 2>, Flags<[OptFlag1, OptFlag2]>;
+def F : JoinedOrSeparate<["-"], "F">, HelpText<"The F option">, MetaVarName<"F">;
+def G : JoinedAndSeparate<["-"], "G">, HelpText<"The G option">, MetaVarName<"G">;
+
+def Ceq : Joined<["-", "--"], "C=">, Alias<C>, Flags<[OptFlag1]>;
+
+def H : Flag<["-"], "H">, Flags<[HelpHidden]>;
+
+def my_group : OptionGroup<"my group">;
+def I : Flag<["-"], "I">, Alias<H>, Group<my_group>;
+
+def J : Flag<["-"], "J">, Alias<B>, AliasArgs<["foo"]>;
+def Joo : Flag<["-"], "Joo">, Alias<B>, AliasArgs<["bar"]>;
+
+def K : Flag<["-"], "K">, Alias<B>;
+
+def Slurp : Option<["-"], "slurp", KIND_REMAINING_ARGS>;
diff --git a/gnu/llvm/unittests/ProfileData/CMakeLists.txt b/gnu/llvm/unittests/ProfileData/CMakeLists.txt
new file mode 100644
index 00000000000..011f8c58179
--- /dev/null
+++ b/gnu/llvm/unittests/ProfileData/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ ProfileData
+ Support
+ )
+
+add_llvm_unittest(ProfileDataTests
+ CoverageMappingTest.cpp
+ InstrProfTest.cpp
+ SampleProfTest.cpp
+ )
diff --git a/gnu/llvm/unittests/ProfileData/CoverageMappingTest.cpp b/gnu/llvm/unittests/ProfileData/CoverageMappingTest.cpp
new file mode 100644
index 00000000000..35b8626c494
--- /dev/null
+++ b/gnu/llvm/unittests/ProfileData/CoverageMappingTest.cpp
@@ -0,0 +1,295 @@
+//===- unittest/ProfileData/CoverageMappingTest.cpp -------------------------=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/CoverageMapping.h"
+#include "llvm/ProfileData/CoverageMappingReader.h"
+#include "llvm/ProfileData/CoverageMappingWriter.h"
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/InstrProfWriter.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+#include <sstream>
+
+using namespace llvm;
+using namespace coverage;
+
+static ::testing::AssertionResult NoError(std::error_code EC) {
+ if (!EC)
+ return ::testing::AssertionSuccess();
+ return ::testing::AssertionFailure() << "error " << EC.value()
+ << ": " << EC.message();
+}
+
+namespace llvm {
+namespace coverage {
+void PrintTo(const Counter &C, ::std::ostream *os) {
+ if (C.isZero())
+ *os << "Zero";
+ else if (C.isExpression())
+ *os << "Expression " << C.getExpressionID();
+ else
+ *os << "Counter " << C.getCounterID();
+}
+
+void PrintTo(const CoverageSegment &S, ::std::ostream *os) {
+ *os << "CoverageSegment(" << S.Line << ", " << S.Col << ", ";
+ if (S.HasCount)
+ *os << S.Count << ", ";
+ *os << (S.IsRegionEntry ? "true" : "false") << ")";
+}
+}
+}
+
+namespace {
+
+struct OneFunctionCoverageReader : CoverageMappingReader {
+ StringRef Name;
+ uint64_t Hash;
+ std::vector<StringRef> Filenames;
+ ArrayRef<CounterMappingRegion> Regions;
+ bool Done;
+
+ OneFunctionCoverageReader(StringRef Name, uint64_t Hash,
+ ArrayRef<StringRef> Filenames,
+ ArrayRef<CounterMappingRegion> Regions)
+ : Name(Name), Hash(Hash), Filenames(Filenames), Regions(Regions),
+ Done(false) {}
+
+ std::error_code readNextRecord(CoverageMappingRecord &Record) override {
+ if (Done)
+ return instrprof_error::eof;
+ Done = true;
+
+ Record.FunctionName = Name;
+ Record.FunctionHash = Hash;
+ Record.Filenames = Filenames;
+ Record.Expressions = {};
+ Record.MappingRegions = Regions;
+ return instrprof_error::success;
+ }
+};
+
+struct CoverageMappingTest : ::testing::Test {
+ StringMap<unsigned> Files;
+ unsigned NextFile;
+ std::vector<CounterMappingRegion> InputCMRs;
+
+ std::vector<StringRef> OutputFiles;
+ std::vector<CounterExpression> OutputExpressions;
+ std::vector<CounterMappingRegion> OutputCMRs;
+
+ InstrProfWriter ProfileWriter;
+ std::unique_ptr<IndexedInstrProfReader> ProfileReader;
+
+ std::unique_ptr<CoverageMapping> LoadedCoverage;
+
+ void SetUp() override {
+ NextFile = 0;
+ }
+
+ unsigned getFile(StringRef Name) {
+ auto R = Files.find(Name);
+ if (R != Files.end())
+ return R->second;
+ Files[Name] = NextFile;
+ return NextFile++;
+ }
+
+ void addCMR(Counter C, StringRef File, unsigned LS, unsigned CS, unsigned LE,
+ unsigned CE) {
+ InputCMRs.push_back(
+ CounterMappingRegion::makeRegion(C, getFile(File), LS, CS, LE, CE));
+ }
+
+ void addExpansionCMR(StringRef File, StringRef ExpandedFile, unsigned LS,
+ unsigned CS, unsigned LE, unsigned CE) {
+ InputCMRs.push_back(CounterMappingRegion::makeExpansion(
+ getFile(File), getFile(ExpandedFile), LS, CS, LE, CE));
+ }
+
+ std::string writeCoverageRegions() {
+ SmallVector<unsigned, 8> FileIDs;
+ for (const auto &E : Files)
+ FileIDs.push_back(E.getValue());
+ std::string Coverage;
+ llvm::raw_string_ostream OS(Coverage);
+ CoverageMappingWriter(FileIDs, None, InputCMRs).write(OS);
+ return OS.str();
+ }
+
+ void readCoverageRegions(std::string Coverage) {
+ SmallVector<StringRef, 8> Filenames;
+ for (const auto &E : Files)
+ Filenames.push_back(E.getKey());
+ RawCoverageMappingReader Reader(Coverage, Filenames, OutputFiles,
+ OutputExpressions, OutputCMRs);
+ ASSERT_TRUE(NoError(Reader.read()));
+ }
+
+ void readProfCounts() {
+ auto Profile = ProfileWriter.writeBuffer();
+ auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
+ ASSERT_TRUE(NoError(ReaderOrErr.getError()));
+ ProfileReader = std::move(ReaderOrErr.get());
+ }
+
+ void loadCoverageMapping(StringRef FuncName, uint64_t Hash) {
+ std::string Regions = writeCoverageRegions();
+ readCoverageRegions(Regions);
+
+ SmallVector<StringRef, 8> Filenames;
+ for (const auto &E : Files)
+ Filenames.push_back(E.getKey());
+ OneFunctionCoverageReader CovReader(FuncName, Hash, Filenames, OutputCMRs);
+ auto CoverageOrErr = CoverageMapping::load(CovReader, *ProfileReader);
+ ASSERT_TRUE(NoError(CoverageOrErr.getError()));
+ LoadedCoverage = std::move(CoverageOrErr.get());
+ }
+};
+
+TEST_F(CoverageMappingTest, basic_write_read) {
+ addCMR(Counter::getCounter(0), "foo", 1, 1, 1, 1);
+ addCMR(Counter::getCounter(1), "foo", 2, 1, 2, 2);
+ addCMR(Counter::getZero(), "foo", 3, 1, 3, 4);
+ addCMR(Counter::getCounter(2), "foo", 4, 1, 4, 8);
+ addCMR(Counter::getCounter(3), "bar", 1, 2, 3, 4);
+ std::string Coverage = writeCoverageRegions();
+ readCoverageRegions(Coverage);
+
+ size_t N = makeArrayRef(InputCMRs).size();
+ ASSERT_EQ(N, OutputCMRs.size());
+ for (size_t I = 0; I < N; ++I) {
+ ASSERT_EQ(InputCMRs[I].Count, OutputCMRs[I].Count);
+ ASSERT_EQ(InputCMRs[I].FileID, OutputCMRs[I].FileID);
+ ASSERT_EQ(InputCMRs[I].startLoc(), OutputCMRs[I].startLoc());
+ ASSERT_EQ(InputCMRs[I].endLoc(), OutputCMRs[I].endLoc());
+ ASSERT_EQ(InputCMRs[I].Kind, OutputCMRs[I].Kind);
+ }
+}
+
+TEST_F(CoverageMappingTest, expansion_gets_first_counter) {
+ addCMR(Counter::getCounter(1), "foo", 10, 1, 10, 2);
+ // This starts earlier in "foo", so the expansion should get its counter.
+ addCMR(Counter::getCounter(2), "foo", 1, 1, 20, 1);
+ addExpansionCMR("bar", "foo", 3, 3, 3, 3);
+ std::string Coverage = writeCoverageRegions();
+ readCoverageRegions(Coverage);
+
+ ASSERT_EQ(CounterMappingRegion::ExpansionRegion, OutputCMRs[2].Kind);
+ ASSERT_EQ(Counter::getCounter(2), OutputCMRs[2].Count);
+ ASSERT_EQ(3U, OutputCMRs[2].LineStart);
+}
+
+TEST_F(CoverageMappingTest, basic_coverage_iteration) {
+ InstrProfRecord Record("func", 0x1234, {30, 20, 10, 0});
+ ProfileWriter.addRecord(std::move(Record));
+ readProfCounts();
+
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+ addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
+ addCMR(Counter::getCounter(2), "file1", 5, 8, 9, 1);
+ addCMR(Counter::getCounter(3), "file1", 10, 10, 11, 11);
+ loadCoverageMapping("func", 0x1234);
+
+ CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+ std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+ ASSERT_EQ(7U, Segments.size());
+ ASSERT_EQ(CoverageSegment(1, 1, 20, true), Segments[0]);
+ ASSERT_EQ(CoverageSegment(4, 7, 30, false), Segments[1]);
+ ASSERT_EQ(CoverageSegment(5, 8, 10, true), Segments[2]);
+ ASSERT_EQ(CoverageSegment(9, 1, 30, false), Segments[3]);
+ ASSERT_EQ(CoverageSegment(9, 9, false), Segments[4]);
+ ASSERT_EQ(CoverageSegment(10, 10, 0, true), Segments[5]);
+ ASSERT_EQ(CoverageSegment(11, 11, false), Segments[6]);
+}
+
+TEST_F(CoverageMappingTest, uncovered_function) {
+ readProfCounts();
+
+ addCMR(Counter::getZero(), "file1", 1, 2, 3, 4);
+ loadCoverageMapping("func", 0x1234);
+
+ CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+ std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+ ASSERT_EQ(2U, Segments.size());
+ ASSERT_EQ(CoverageSegment(1, 2, 0, true), Segments[0]);
+ ASSERT_EQ(CoverageSegment(3, 4, false), Segments[1]);
+}
+
+TEST_F(CoverageMappingTest, uncovered_function_with_mapping) {
+ readProfCounts();
+
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+ addCMR(Counter::getCounter(1), "file1", 1, 1, 4, 7);
+ loadCoverageMapping("func", 0x1234);
+
+ CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+ std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+ ASSERT_EQ(3U, Segments.size());
+ ASSERT_EQ(CoverageSegment(1, 1, 0, true), Segments[0]);
+ ASSERT_EQ(CoverageSegment(4, 7, 0, false), Segments[1]);
+ ASSERT_EQ(CoverageSegment(9, 9, false), Segments[2]);
+}
+
+TEST_F(CoverageMappingTest, combine_regions) {
+ InstrProfRecord Record("func", 0x1234, {10, 20, 30});
+ ProfileWriter.addRecord(std::move(Record));
+ readProfCounts();
+
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+ addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
+ addCMR(Counter::getCounter(2), "file1", 3, 3, 4, 4);
+ loadCoverageMapping("func", 0x1234);
+
+ CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+ std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+ ASSERT_EQ(4U, Segments.size());
+ ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
+ ASSERT_EQ(CoverageSegment(3, 3, 50, true), Segments[1]);
+ ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
+ ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
+}
+
+TEST_F(CoverageMappingTest, dont_combine_expansions) {
+ InstrProfRecord Record("func", 0x1234, {10, 20});
+ ProfileWriter.addRecord(std::move(Record));
+ readProfCounts();
+
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+ addCMR(Counter::getCounter(1), "file1", 3, 3, 4, 4);
+ addCMR(Counter::getCounter(1), "include1", 6, 6, 7, 7);
+ addExpansionCMR("file1", "include1", 3, 3, 4, 4);
+ loadCoverageMapping("func", 0x1234);
+
+ CoverageData Data = LoadedCoverage->getCoverageForFile("file1");
+ std::vector<CoverageSegment> Segments(Data.begin(), Data.end());
+ ASSERT_EQ(4U, Segments.size());
+ ASSERT_EQ(CoverageSegment(1, 1, 10, true), Segments[0]);
+ ASSERT_EQ(CoverageSegment(3, 3, 20, true), Segments[1]);
+ ASSERT_EQ(CoverageSegment(4, 4, 10, false), Segments[2]);
+ ASSERT_EQ(CoverageSegment(9, 9, false), Segments[3]);
+}
+
+TEST_F(CoverageMappingTest, strip_filename_prefix) {
+ InstrProfRecord Record("file1:func", 0x1234, {10});
+ ProfileWriter.addRecord(std::move(Record));
+ readProfCounts();
+
+ addCMR(Counter::getCounter(0), "file1", 1, 1, 9, 9);
+ loadCoverageMapping("file1:func", 0x1234);
+
+ std::vector<std::string> Names;
+ for (const auto &Func : LoadedCoverage->getCoveredFunctions())
+ Names.push_back(Func.Name);
+ ASSERT_EQ(1U, Names.size());
+ ASSERT_EQ("func", Names[0]);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ProfileData/InstrProfTest.cpp b/gnu/llvm/unittests/ProfileData/InstrProfTest.cpp
new file mode 100644
index 00000000000..51f52f2a077
--- /dev/null
+++ b/gnu/llvm/unittests/ProfileData/InstrProfTest.cpp
@@ -0,0 +1,734 @@
+//===- unittest/ProfileData/InstrProfTest.cpp -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/InstrProfReader.h"
+#include "llvm/ProfileData/InstrProfWriter.h"
+#include "llvm/Support/Compression.h"
+#include "gtest/gtest.h"
+
+#include <cstdarg>
+
+using namespace llvm;
+
+static ::testing::AssertionResult NoError(std::error_code EC) {
+ if (!EC)
+ return ::testing::AssertionSuccess();
+ return ::testing::AssertionFailure() << "error " << EC.value()
+ << ": " << EC.message();
+}
+
+static ::testing::AssertionResult ErrorEquals(std::error_code Expected,
+ std::error_code Found) {
+ if (Expected == Found)
+ return ::testing::AssertionSuccess();
+ return ::testing::AssertionFailure() << "error " << Found.value()
+ << ": " << Found.message();
+}
+
+namespace {
+
+struct InstrProfTest : ::testing::Test {
+ InstrProfWriter Writer;
+ std::unique_ptr<IndexedInstrProfReader> Reader;
+
+ void readProfile(std::unique_ptr<MemoryBuffer> Profile) {
+ auto ReaderOrErr = IndexedInstrProfReader::create(std::move(Profile));
+ ASSERT_TRUE(NoError(ReaderOrErr.getError()));
+ Reader = std::move(ReaderOrErr.get());
+ }
+};
+
+TEST_F(InstrProfTest, write_and_read_empty_profile) {
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+ ASSERT_TRUE(Reader->begin() == Reader->end());
+}
+
+TEST_F(InstrProfTest, write_and_read_one_function) {
+ InstrProfRecord Record("foo", 0x1234, {1, 2, 3, 4});
+ Writer.addRecord(std::move(Record));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ auto I = Reader->begin(), E = Reader->end();
+ ASSERT_TRUE(I != E);
+ ASSERT_EQ(StringRef("foo"), I->Name);
+ ASSERT_EQ(0x1234U, I->Hash);
+ ASSERT_EQ(4U, I->Counts.size());
+ ASSERT_EQ(1U, I->Counts[0]);
+ ASSERT_EQ(2U, I->Counts[1]);
+ ASSERT_EQ(3U, I->Counts[2]);
+ ASSERT_EQ(4U, I->Counts[3]);
+ ASSERT_TRUE(++I == E);
+}
+
+TEST_F(InstrProfTest, get_instr_prof_record) {
+ InstrProfRecord Record1("foo", 0x1234, {1, 2});
+ InstrProfRecord Record2("foo", 0x1235, {3, 4});
+ Writer.addRecord(std::move(Record1));
+ Writer.addRecord(std::move(Record2));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("foo", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(2U, R.get().Counts.size());
+ ASSERT_EQ(1U, R.get().Counts[0]);
+ ASSERT_EQ(2U, R.get().Counts[1]);
+
+ R = Reader->getInstrProfRecord("foo", 0x1235);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(2U, R.get().Counts.size());
+ ASSERT_EQ(3U, R.get().Counts[0]);
+ ASSERT_EQ(4U, R.get().Counts[1]);
+
+ R = Reader->getInstrProfRecord("foo", 0x5678);
+ ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, R.getError()));
+
+ R = Reader->getInstrProfRecord("bar", 0x1234);
+ ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, R.getError()));
+}
+
+TEST_F(InstrProfTest, get_function_counts) {
+ InstrProfRecord Record1("foo", 0x1234, {1, 2});
+ InstrProfRecord Record2("foo", 0x1235, {3, 4});
+ Writer.addRecord(std::move(Record1));
+ Writer.addRecord(std::move(Record2));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ std::vector<uint64_t> Counts;
+ ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
+ ASSERT_EQ(2U, Counts.size());
+ ASSERT_EQ(1U, Counts[0]);
+ ASSERT_EQ(2U, Counts[1]);
+
+ ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
+ ASSERT_EQ(2U, Counts.size());
+ ASSERT_EQ(3U, Counts[0]);
+ ASSERT_EQ(4U, Counts[1]);
+
+ std::error_code EC;
+ EC = Reader->getFunctionCounts("foo", 0x5678, Counts);
+ ASSERT_TRUE(ErrorEquals(instrprof_error::hash_mismatch, EC));
+
+ EC = Reader->getFunctionCounts("bar", 0x1234, Counts);
+ ASSERT_TRUE(ErrorEquals(instrprof_error::unknown_function, EC));
+}
+
+TEST_F(InstrProfTest, get_icall_data_read_write) {
+ InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ InstrProfRecord Record2("callee1", 0x1235, {3, 4});
+ InstrProfRecord Record3("callee2", 0x1235, {3, 4});
+ InstrProfRecord Record4("callee3", 0x1235, {3, 4});
+
+ // 4 value sites.
+ Record1.reserveSites(IPVK_IndirectCallTarget, 4);
+ InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2},
+ {(uint64_t) "callee3", 3}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
+ // No value profile data at the second site.
+ Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+ InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
+ InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
+
+ Writer.addRecord(std::move(Record1));
+ Writer.addRecord(std::move(Record2));
+ Writer.addRecord(std::move(Record3));
+ Writer.addRecord(std::move(Record4));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
+ ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
+
+ std::unique_ptr<InstrProfValueData[]> VD =
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+
+ ASSERT_EQ(3U, VD[0].Count);
+ ASSERT_EQ(2U, VD[1].Count);
+ ASSERT_EQ(1U, VD[2].Count);
+
+ ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
+}
+
+TEST_F(InstrProfTest, get_icall_data_read_write_with_weight) {
+ InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ InstrProfRecord Record2("callee1", 0x1235, {3, 4});
+ InstrProfRecord Record3("callee2", 0x1235, {3, 4});
+ InstrProfRecord Record4("callee3", 0x1235, {3, 4});
+
+ // 4 value sites.
+ Record1.reserveSites(IPVK_IndirectCallTarget, 4);
+ InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2},
+ {(uint64_t) "callee3", 3}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
+ // No value profile data at the second site.
+ Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+ InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
+ InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
+
+ Writer.addRecord(std::move(Record1), 10);
+ Writer.addRecord(std::move(Record2));
+ Writer.addRecord(std::move(Record3));
+ Writer.addRecord(std::move(Record4));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
+ ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
+
+ std::unique_ptr<InstrProfValueData[]> VD =
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+ ASSERT_EQ(30U, VD[0].Count);
+ ASSERT_EQ(20U, VD[1].Count);
+ ASSERT_EQ(10U, VD[2].Count);
+
+ ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
+}
+
+TEST_F(InstrProfTest, get_icall_data_read_write_big_endian) {
+ InstrProfRecord Record1("caller", 0x1234, {1, 2});
+ InstrProfRecord Record2("callee1", 0x1235, {3, 4});
+ InstrProfRecord Record3("callee2", 0x1235, {3, 4});
+ InstrProfRecord Record4("callee3", 0x1235, {3, 4});
+
+ // 4 value sites.
+ Record1.reserveSites(IPVK_IndirectCallTarget, 4);
+ InstrProfValueData VD0[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2},
+ {(uint64_t) "callee3", 3}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 0, VD0, 3, nullptr);
+ // No value profile data at the second site.
+ Record1.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+ InstrProfValueData VD2[] = {{(uint64_t) "callee1", 1},
+ {(uint64_t) "callee2", 2}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 2, VD2, 2, nullptr);
+ InstrProfValueData VD3[] = {{(uint64_t) "callee1", 1}};
+ Record1.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
+
+ Writer.addRecord(std::move(Record1));
+ Writer.addRecord(std::move(Record2));
+ Writer.addRecord(std::move(Record3));
+ Writer.addRecord(std::move(Record4));
+
+ // Set big endian output.
+ Writer.setValueProfDataEndianness(support::big);
+
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ // Set big endian input.
+ Reader->setValueProfDataEndianness(support::big);
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(4U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
+ ASSERT_EQ(2U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
+
+ std::unique_ptr<InstrProfValueData[]> VD =
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+ ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee1"));
+
+ // Restore little endian default:
+ Writer.setValueProfDataEndianness(support::little);
+}
+
+TEST_F(InstrProfTest, get_icall_data_merge1) {
+ static const char caller[] = "caller";
+ static const char callee1[] = "callee1";
+ static const char callee2[] = "callee2";
+ static const char callee3[] = "callee3";
+ static const char callee4[] = "callee4";
+
+ InstrProfRecord Record11(caller, 0x1234, {1, 2});
+ InstrProfRecord Record12(caller, 0x1234, {1, 2});
+ InstrProfRecord Record2(callee1, 0x1235, {3, 4});
+ InstrProfRecord Record3(callee2, 0x1235, {3, 4});
+ InstrProfRecord Record4(callee3, 0x1235, {3, 4});
+ InstrProfRecord Record5(callee3, 0x1235, {3, 4});
+ InstrProfRecord Record6(callee4, 0x1235, {3, 5});
+
+ // 5 value sites.
+ Record11.reserveSites(IPVK_IndirectCallTarget, 5);
+ InstrProfValueData VD0[] = {{uint64_t(callee1), 1},
+ {uint64_t(callee2), 2},
+ {uint64_t(callee3), 3},
+ {uint64_t(callee4), 4}};
+ Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 4, nullptr);
+
+ // No value profile data at the second site.
+ Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+
+ InstrProfValueData VD2[] = {
+ {uint64_t(callee1), 1}, {uint64_t(callee2), 2}, {uint64_t(callee3), 3}};
+ Record11.addValueData(IPVK_IndirectCallTarget, 2, VD2, 3, nullptr);
+
+ InstrProfValueData VD3[] = {{uint64_t(callee1), 1}};
+ Record11.addValueData(IPVK_IndirectCallTarget, 3, VD3, 1, nullptr);
+
+ InstrProfValueData VD4[] = {{uint64_t(callee1), 1},
+ {uint64_t(callee2), 2},
+ {uint64_t(callee3), 3}};
+ Record11.addValueData(IPVK_IndirectCallTarget, 4, VD4, 3, nullptr);
+
+ // A differnt record for the same caller.
+ Record12.reserveSites(IPVK_IndirectCallTarget, 5);
+ InstrProfValueData VD02[] = {{uint64_t(callee2), 5}, {uint64_t(callee3), 3}};
+ Record12.addValueData(IPVK_IndirectCallTarget, 0, VD02, 2, nullptr);
+
+ // No value profile data at the second site.
+ Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+
+ InstrProfValueData VD22[] = {
+ {uint64_t(callee2), 1}, {uint64_t(callee3), 3}, {uint64_t(callee4), 4}};
+ Record12.addValueData(IPVK_IndirectCallTarget, 2, VD22, 3, nullptr);
+
+ Record12.addValueData(IPVK_IndirectCallTarget, 3, nullptr, 0, nullptr);
+
+ InstrProfValueData VD42[] = {{uint64_t(callee1), 1},
+ {uint64_t(callee2), 2},
+ {uint64_t(callee3), 3}};
+ Record12.addValueData(IPVK_IndirectCallTarget, 4, VD42, 3, nullptr);
+
+ Writer.addRecord(std::move(Record11));
+ // Merge profile data.
+ Writer.addRecord(std::move(Record12));
+
+ Writer.addRecord(std::move(Record2));
+ Writer.addRecord(std::move(Record3));
+ Writer.addRecord(std::move(Record4));
+ Writer.addRecord(std::move(Record5));
+ Writer.addRecord(std::move(Record6));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ ASSERT_EQ(5U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(0U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
+ ASSERT_EQ(4U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(1U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
+ ASSERT_EQ(3U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
+
+ std::unique_ptr<InstrProfValueData[]> VD =
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+ ASSERT_EQ(StringRef((const char *)VD[0].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(7U, VD[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD[1].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(6U, VD[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD[2].Value, 7), StringRef("callee4"));
+ ASSERT_EQ(4U, VD[2].Count);
+ ASSERT_EQ(StringRef((const char *)VD[3].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(1U, VD[3].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_2(
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(6U, VD_2[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee4"));
+ ASSERT_EQ(4U, VD_2[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(3U, VD_2[2].Count);
+ ASSERT_EQ(StringRef((const char *)VD_2[3].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(1U, VD_2[3].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_3(
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 3));
+ ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(1U, VD_3[0].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_4(
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 4));
+ ASSERT_EQ(StringRef((const char *)VD_4[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(6U, VD_4[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_4[1].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(4U, VD_4[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD_4[2].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(2U, VD_4[2].Count);
+}
+
+TEST_F(InstrProfTest, get_icall_data_merge1_saturation) {
+ static const char bar[] = "bar";
+
+ const uint64_t Max = std::numeric_limits<uint64_t>::max();
+
+ InstrProfRecord Record1("foo", 0x1234, {1});
+ auto Result1 = Writer.addRecord(std::move(Record1));
+ ASSERT_EQ(Result1, instrprof_error::success);
+
+ // Verify counter overflow.
+ InstrProfRecord Record2("foo", 0x1234, {Max});
+ auto Result2 = Writer.addRecord(std::move(Record2));
+ ASSERT_EQ(Result2, instrprof_error::counter_overflow);
+
+ InstrProfRecord Record3(bar, 0x9012, {8});
+ auto Result3 = Writer.addRecord(std::move(Record3));
+ ASSERT_EQ(Result3, instrprof_error::success);
+
+ InstrProfRecord Record4("baz", 0x5678, {3, 4});
+ Record4.reserveSites(IPVK_IndirectCallTarget, 1);
+ InstrProfValueData VD4[] = {{uint64_t(bar), 1}};
+ Record4.addValueData(IPVK_IndirectCallTarget, 0, VD4, 1, nullptr);
+ auto Result4 = Writer.addRecord(std::move(Record4));
+ ASSERT_EQ(Result4, instrprof_error::success);
+
+ // Verify value data counter overflow.
+ InstrProfRecord Record5("baz", 0x5678, {5, 6});
+ Record5.reserveSites(IPVK_IndirectCallTarget, 1);
+ InstrProfValueData VD5[] = {{uint64_t(bar), Max}};
+ Record5.addValueData(IPVK_IndirectCallTarget, 0, VD5, 1, nullptr);
+ auto Result5 = Writer.addRecord(std::move(Record5));
+ ASSERT_EQ(Result5, instrprof_error::counter_overflow);
+
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ // Verify saturation of counts.
+ ErrorOr<InstrProfRecord> ReadRecord1 =
+ Reader->getInstrProfRecord("foo", 0x1234);
+ ASSERT_TRUE(NoError(ReadRecord1.getError()));
+ ASSERT_EQ(Max, ReadRecord1.get().Counts[0]);
+
+ ErrorOr<InstrProfRecord> ReadRecord2 =
+ Reader->getInstrProfRecord("baz", 0x5678);
+ ASSERT_EQ(1U, ReadRecord2.get().getNumValueSites(IPVK_IndirectCallTarget));
+ std::unique_ptr<InstrProfValueData[]> VD =
+ ReadRecord2.get().getValueForSite(IPVK_IndirectCallTarget, 0);
+ ASSERT_EQ(StringRef("bar"), StringRef((const char *)VD[0].Value, 3));
+ ASSERT_EQ(Max, VD[0].Count);
+}
+
+// This test tests that when there are too many values
+// for a given site, the merged results are properly
+// truncated.
+TEST_F(InstrProfTest, get_icall_data_merge_site_trunc) {
+ static const char caller[] = "caller";
+
+ InstrProfRecord Record11(caller, 0x1234, {1, 2});
+ InstrProfRecord Record12(caller, 0x1234, {1, 2});
+
+ // 2 value sites.
+ Record11.reserveSites(IPVK_IndirectCallTarget, 2);
+ InstrProfValueData VD0[255];
+ for (int I = 0; I < 255; I++) {
+ VD0[I].Value = 2 * I;
+ VD0[I].Count = 2 * I + 1000;
+ }
+
+ Record11.addValueData(IPVK_IndirectCallTarget, 0, VD0, 255, nullptr);
+ Record11.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+
+ Record12.reserveSites(IPVK_IndirectCallTarget, 2);
+ InstrProfValueData VD1[255];
+ for (int I = 0; I < 255; I++) {
+ VD1[I].Value = 2 * I + 1;
+ VD1[I].Count = 2 * I + 1001;
+ }
+
+ Record12.addValueData(IPVK_IndirectCallTarget, 0, VD1, 255, nullptr);
+ Record12.addValueData(IPVK_IndirectCallTarget, 1, nullptr, 0, nullptr);
+
+ Writer.addRecord(std::move(Record11));
+ // Merge profile data.
+ Writer.addRecord(std::move(Record12));
+
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ErrorOr<InstrProfRecord> R = Reader->getInstrProfRecord("caller", 0x1234);
+ ASSERT_TRUE(NoError(R.getError()));
+ std::unique_ptr<InstrProfValueData[]> VD(
+ R.get().getValueForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(2U, R.get().getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(255U, R.get().getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ for (unsigned I = 0; I < 255; I++) {
+ ASSERT_EQ(VD[I].Value, 509 - I);
+ ASSERT_EQ(VD[I].Count, 1509 - I);
+ }
+}
+
+// Synthesize runtime value profile data.
+ValueProfNode Site1Values[5] = {{{uint64_t("callee1"), 400}, &Site1Values[1]},
+ {{uint64_t("callee2"), 1000}, &Site1Values[2]},
+ {{uint64_t("callee3"), 500}, &Site1Values[3]},
+ {{uint64_t("callee4"), 300}, &Site1Values[4]},
+ {{uint64_t("callee5"), 100}, 0}};
+
+ValueProfNode Site2Values[4] = {{{uint64_t("callee5"), 800}, &Site2Values[1]},
+ {{uint64_t("callee3"), 1000}, &Site2Values[2]},
+ {{uint64_t("callee2"), 2500}, &Site2Values[3]},
+ {{uint64_t("callee1"), 1300}, 0}};
+
+ValueProfNode Site3Values[3] = {{{uint64_t("callee6"), 800}, &Site3Values[1]},
+ {{uint64_t("callee3"), 1000}, &Site3Values[2]},
+ {{uint64_t("callee4"), 5500}, 0}};
+
+ValueProfNode Site4Values[2] = {{{uint64_t("callee2"), 1800}, &Site4Values[1]},
+ {{uint64_t("callee3"), 2000}, 0}};
+
+static ValueProfNode *ValueProfNodes[5] = {&Site1Values[0], &Site2Values[0],
+ &Site3Values[0], &Site4Values[0], 0};
+static uint16_t NumValueSites[IPVK_Last + 1] = {5};
+TEST_F(InstrProfTest, runtime_value_prof_data_read_write) {
+ ValueProfRuntimeRecord RTRecord;
+ initializeValueProfRuntimeRecord(&RTRecord, &NumValueSites[0],
+ &ValueProfNodes[0]);
+
+ ValueProfData *VPData = serializeValueProfDataFromRT(&RTRecord, nullptr);
+
+ InstrProfRecord Record("caller", 0x1234, {1ULL << 31, 2});
+
+ VPData->deserializeTo(Record, 0);
+
+ // Now read data from Record and sanity check the data
+ ASSERT_EQ(5U, Record.getNumValueSites(IPVK_IndirectCallTarget));
+ ASSERT_EQ(5U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 0));
+ ASSERT_EQ(4U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 1));
+ ASSERT_EQ(3U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 2));
+ ASSERT_EQ(2U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 3));
+ ASSERT_EQ(0U, Record.getNumValueDataForSite(IPVK_IndirectCallTarget, 4));
+
+ auto Cmp = [](const InstrProfValueData &VD1, const InstrProfValueData &VD2) {
+ return VD1.Count > VD2.Count;
+ };
+ std::unique_ptr<InstrProfValueData[]> VD_0(
+ Record.getValueForSite(IPVK_IndirectCallTarget, 0));
+ std::sort(&VD_0[0], &VD_0[5], Cmp);
+ ASSERT_EQ(StringRef((const char *)VD_0[0].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(1000U, VD_0[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_0[1].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(500U, VD_0[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD_0[2].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(400U, VD_0[2].Count);
+ ASSERT_EQ(StringRef((const char *)VD_0[3].Value, 7), StringRef("callee4"));
+ ASSERT_EQ(300U, VD_0[3].Count);
+ ASSERT_EQ(StringRef((const char *)VD_0[4].Value, 7), StringRef("callee5"));
+ ASSERT_EQ(100U, VD_0[4].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_1(
+ Record.getValueForSite(IPVK_IndirectCallTarget, 1));
+ std::sort(&VD_1[0], &VD_1[4], Cmp);
+ ASSERT_EQ(StringRef((const char *)VD_1[0].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(2500U, VD_1[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_1[1].Value, 7), StringRef("callee1"));
+ ASSERT_EQ(1300U, VD_1[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD_1[2].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(1000U, VD_1[2].Count);
+ ASSERT_EQ(StringRef((const char *)VD_1[3].Value, 7), StringRef("callee5"));
+ ASSERT_EQ(800U, VD_1[3].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_2(
+ Record.getValueForSite(IPVK_IndirectCallTarget, 2));
+ std::sort(&VD_2[0], &VD_2[3], Cmp);
+ ASSERT_EQ(StringRef((const char *)VD_2[0].Value, 7), StringRef("callee4"));
+ ASSERT_EQ(5500U, VD_2[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_2[1].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(1000U, VD_2[1].Count);
+ ASSERT_EQ(StringRef((const char *)VD_2[2].Value, 7), StringRef("callee6"));
+ ASSERT_EQ(800U, VD_2[2].Count);
+
+ std::unique_ptr<InstrProfValueData[]> VD_3(
+ Record.getValueForSite(IPVK_IndirectCallTarget, 3));
+ std::sort(&VD_3[0], &VD_3[2], Cmp);
+ ASSERT_EQ(StringRef((const char *)VD_3[0].Value, 7), StringRef("callee3"));
+ ASSERT_EQ(2000U, VD_3[0].Count);
+ ASSERT_EQ(StringRef((const char *)VD_3[1].Value, 7), StringRef("callee2"));
+ ASSERT_EQ(1800U, VD_3[1].Count);
+
+ finalizeValueProfRuntimeRecord(&RTRecord);
+ free(VPData);
+}
+
+TEST_F(InstrProfTest, get_max_function_count) {
+ InstrProfRecord Record1("foo", 0x1234, {1ULL << 31, 2});
+ InstrProfRecord Record2("bar", 0, {1ULL << 63});
+ InstrProfRecord Record3("baz", 0x5678, {0, 0, 0, 0});
+ Writer.addRecord(std::move(Record1));
+ Writer.addRecord(std::move(Record2));
+ Writer.addRecord(std::move(Record3));
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ ASSERT_EQ(1ULL << 63, Reader->getMaximumFunctionCount());
+}
+
+TEST_F(InstrProfTest, get_weighted_function_counts) {
+ InstrProfRecord Record1("foo", 0x1234, {1, 2});
+ InstrProfRecord Record2("foo", 0x1235, {3, 4});
+ Writer.addRecord(std::move(Record1), 3);
+ Writer.addRecord(std::move(Record2), 5);
+ auto Profile = Writer.writeBuffer();
+ readProfile(std::move(Profile));
+
+ std::vector<uint64_t> Counts;
+ ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1234, Counts)));
+ ASSERT_EQ(2U, Counts.size());
+ ASSERT_EQ(3U, Counts[0]);
+ ASSERT_EQ(6U, Counts[1]);
+
+ ASSERT_TRUE(NoError(Reader->getFunctionCounts("foo", 0x1235, Counts)));
+ ASSERT_EQ(2U, Counts.size());
+ ASSERT_EQ(15U, Counts[0]);
+ ASSERT_EQ(20U, Counts[1]);
+}
+
+TEST_F(InstrProfTest, instr_prof_symtab_test) {
+ std::vector<StringRef> FuncNames;
+ FuncNames.push_back("func1");
+ FuncNames.push_back("func2");
+ FuncNames.push_back("func3");
+ FuncNames.push_back("bar1");
+ FuncNames.push_back("bar2");
+ FuncNames.push_back("bar3");
+ InstrProfSymtab Symtab;
+ Symtab.create(FuncNames);
+ StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
+ ASSERT_EQ(StringRef("func1"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
+ ASSERT_EQ(StringRef("func2"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
+ ASSERT_EQ(StringRef("func3"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
+ ASSERT_EQ(StringRef("bar1"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
+ ASSERT_EQ(StringRef("bar2"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
+ ASSERT_EQ(StringRef("bar3"), R);
+
+ // Now incrementally update the symtab
+ Symtab.addFuncName("blah_1");
+ Symtab.addFuncName("blah_2");
+ Symtab.addFuncName("blah_3");
+ // Finalize it
+ Symtab.finalizeSymtab();
+
+ // Check again
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_1"));
+ ASSERT_EQ(StringRef("blah_1"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_2"));
+ ASSERT_EQ(StringRef("blah_2"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("blah_3"));
+ ASSERT_EQ(StringRef("blah_3"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func1"));
+ ASSERT_EQ(StringRef("func1"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func2"));
+ ASSERT_EQ(StringRef("func2"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("func3"));
+ ASSERT_EQ(StringRef("func3"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar1"));
+ ASSERT_EQ(StringRef("bar1"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar2"));
+ ASSERT_EQ(StringRef("bar2"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash("bar3"));
+ ASSERT_EQ(StringRef("bar3"), R);
+}
+
+TEST_F(InstrProfTest, instr_prof_symtab_compression_test) {
+ std::vector<std::string> FuncNames1;
+ std::vector<std::string> FuncNames2;
+ for (int I = 0; I < 10 * 1024; I++) {
+ std::string str;
+ raw_string_ostream OS(str);
+ OS << "func_" << I;
+ FuncNames1.push_back(OS.str());
+ str.clear();
+ OS << "fooooooooooooooo_" << I;
+ FuncNames1.push_back(OS.str());
+ str.clear();
+ OS << "BAR_" << I;
+ FuncNames2.push_back(OS.str());
+ str.clear();
+ OS << "BlahblahBlahblahBar_" << I;
+ FuncNames2.push_back(OS.str());
+ }
+
+ for (int Padding = 0; Padding < 10; Padding++) {
+ for (int DoCompression = 0; DoCompression < 2; DoCompression++) {
+ // Compressing:
+ std::string FuncNameStrings1;
+ collectPGOFuncNameStrings(FuncNames1,
+ (DoCompression != 0 && zlib::isAvailable()),
+ FuncNameStrings1);
+
+ // Compressing:
+ std::string FuncNameStrings2;
+ collectPGOFuncNameStrings(FuncNames2,
+ (DoCompression != 0 && zlib::isAvailable()),
+ FuncNameStrings2);
+
+ // Join with paddings:
+ std::string FuncNameStrings = FuncNameStrings1;
+ for (int P = 0; P < Padding; P++) {
+ FuncNameStrings.push_back('\0');
+ }
+ FuncNameStrings += FuncNameStrings2;
+
+ // Now decompress:
+ InstrProfSymtab Symtab;
+ Symtab.create(StringRef(FuncNameStrings));
+
+ // Now do the checks:
+ // First sampling some data points:
+ StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[0]));
+ ASSERT_EQ(StringRef("func_0"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[1]));
+ ASSERT_EQ(StringRef("fooooooooooooooo_0"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[998]));
+ ASSERT_EQ(StringRef("func_499"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames1[999]));
+ ASSERT_EQ(StringRef("fooooooooooooooo_499"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[100]));
+ ASSERT_EQ(StringRef("BAR_50"), R);
+ R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(FuncNames2[101]));
+ ASSERT_EQ(StringRef("BlahblahBlahblahBar_50"), R);
+ for (int I = 0; I < 10 * 1024; I++) {
+ std::string N[4];
+ N[0] = FuncNames1[2 * I];
+ N[1] = FuncNames1[2 * I + 1];
+ N[2] = FuncNames2[2 * I];
+ N[3] = FuncNames2[2 * I + 1];
+ for (int J = 0; J < 4; J++) {
+ StringRef R = Symtab.getFuncName(IndexedInstrProf::ComputeHash(N[J]));
+ ASSERT_EQ(StringRef(N[J]), R);
+ }
+ }
+ }
+ }
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/ProfileData/Makefile b/gnu/llvm/unittests/ProfileData/Makefile
new file mode 100644
index 00000000000..d017c15c00a
--- /dev/null
+++ b/gnu/llvm/unittests/ProfileData/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/ProfileData/Makefile ----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = ProfileData
+LINK_COMPONENTS := ProfileData Core Support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/ProfileData/SampleProfTest.cpp b/gnu/llvm/unittests/ProfileData/SampleProfTest.cpp
new file mode 100644
index 00000000000..cc3c2f5306e
--- /dev/null
+++ b/gnu/llvm/unittests/ProfileData/SampleProfTest.cpp
@@ -0,0 +1,132 @@
+//===- unittest/ProfileData/SampleProfTest.cpp -------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ProfileData/SampleProfReader.h"
+#include "llvm/ProfileData/SampleProfWriter.h"
+#include "gtest/gtest.h"
+
+#include <cstdarg>
+
+using namespace llvm;
+using namespace sampleprof;
+
+static ::testing::AssertionResult NoError(std::error_code EC) {
+ if (!EC)
+ return ::testing::AssertionSuccess();
+ return ::testing::AssertionFailure() << "error " << EC.value() << ": "
+ << EC.message();
+}
+
+namespace {
+
+struct SampleProfTest : ::testing::Test {
+ std::string Data;
+ std::unique_ptr<raw_ostream> OS;
+ std::unique_ptr<SampleProfileWriter> Writer;
+ std::unique_ptr<SampleProfileReader> Reader;
+
+ SampleProfTest()
+ : Data(), OS(new raw_string_ostream(Data)), Writer(), Reader() {}
+
+ void createWriter(SampleProfileFormat Format) {
+ auto WriterOrErr = SampleProfileWriter::create(OS, Format);
+ ASSERT_TRUE(NoError(WriterOrErr.getError()));
+ Writer = std::move(WriterOrErr.get());
+ }
+
+ void readProfile(std::unique_ptr<MemoryBuffer> &Profile) {
+ auto ReaderOrErr = SampleProfileReader::create(Profile, getGlobalContext());
+ ASSERT_TRUE(NoError(ReaderOrErr.getError()));
+ Reader = std::move(ReaderOrErr.get());
+ }
+
+ void testRoundTrip(SampleProfileFormat Format) {
+ createWriter(Format);
+
+ StringRef FooName("_Z3fooi");
+ FunctionSamples FooSamples;
+ FooSamples.addTotalSamples(7711);
+ FooSamples.addHeadSamples(610);
+ FooSamples.addBodySamples(1, 0, 610);
+
+ StringRef BarName("_Z3bari");
+ FunctionSamples BarSamples;
+ BarSamples.addTotalSamples(20301);
+ BarSamples.addHeadSamples(1437);
+ BarSamples.addBodySamples(1, 0, 1437);
+
+ StringMap<FunctionSamples> Profiles;
+ Profiles[FooName] = std::move(FooSamples);
+ Profiles[BarName] = std::move(BarSamples);
+
+ std::error_code EC;
+ EC = Writer->write(Profiles);
+ ASSERT_TRUE(NoError(EC));
+
+ Writer->getOutputStream().flush();
+
+ auto Profile = MemoryBuffer::getMemBufferCopy(Data);
+ readProfile(Profile);
+
+ EC = Reader->read();
+ ASSERT_TRUE(NoError(EC));
+
+ StringMap<FunctionSamples> &ReadProfiles = Reader->getProfiles();
+ ASSERT_EQ(2u, ReadProfiles.size());
+
+ FunctionSamples &ReadFooSamples = ReadProfiles[FooName];
+ ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples());
+ ASSERT_EQ(610u, ReadFooSamples.getHeadSamples());
+
+ FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
+ ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
+ ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
+ }
+};
+
+TEST_F(SampleProfTest, roundtrip_text_profile) {
+ testRoundTrip(SampleProfileFormat::SPF_Text);
+}
+
+TEST_F(SampleProfTest, roundtrip_binary_profile) {
+ testRoundTrip(SampleProfileFormat::SPF_Binary);
+}
+
+TEST_F(SampleProfTest, sample_overflow_saturation) {
+ const uint64_t Max = std::numeric_limits<uint64_t>::max();
+ sampleprof_error Result;
+
+ StringRef FooName("_Z3fooi");
+ FunctionSamples FooSamples;
+ Result = FooSamples.addTotalSamples(1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addHeadSamples(1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addBodySamples(10, 0, 1);
+ ASSERT_EQ(Result, sampleprof_error::success);
+
+ Result = FooSamples.addTotalSamples(Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ASSERT_EQ(FooSamples.getTotalSamples(), Max);
+
+ Result = FooSamples.addHeadSamples(Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ASSERT_EQ(FooSamples.getHeadSamples(), Max);
+
+ Result = FooSamples.addBodySamples(10, 0, Max);
+ ASSERT_EQ(Result, sampleprof_error::counter_overflow);
+ ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
+ ASSERT_FALSE(BodySamples.getError());
+ ASSERT_EQ(BodySamples.get(), Max);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Support/AlignOfTest.cpp b/gnu/llvm/unittests/Support/AlignOfTest.cpp
new file mode 100644
index 00000000000..be208f7d28e
--- /dev/null
+++ b/gnu/llvm/unittests/Support/AlignOfTest.cpp
@@ -0,0 +1,357 @@
+//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef _MSC_VER
+// Disable warnings about alignment-based structure padding.
+// This must be above the includes to suppress warnings in included templates.
+#pragma warning(disable:4324)
+#endif
+
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/Compiler.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+// Disable warnings about questionable type definitions.
+// We're testing that even questionable types work with the alignment utilities.
+#ifdef _MSC_VER
+#pragma warning(disable:4584)
+#endif
+
+// Suppress direct base '{anonymous}::S1' inaccessible in '{anonymous}::D9'
+// due to ambiguity warning.
+#ifdef __clang__
+#pragma clang diagnostic ignored "-Wunknown-pragmas"
+#pragma clang diagnostic ignored "-Winaccessible-base"
+#elif ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
+// Pragma based warning suppression was introduced in GGC 4.2. Additionally
+// this warning is "enabled by default". The warning still appears if -Wall is
+// suppressed. Apparently GCC suppresses it when -w is specifed, which is odd.
+#pragma GCC diagnostic warning "-w"
+#endif
+
+// Define some fixed alignment types to use in these tests.
+struct LLVM_ALIGNAS(1) A1 {};
+struct LLVM_ALIGNAS(2) A2 {};
+struct LLVM_ALIGNAS(4) A4 {};
+struct LLVM_ALIGNAS(8) A8 {};
+
+struct S1 {};
+struct S2 { char a; };
+struct S3 { int x; };
+struct S4 { double y; };
+struct S5 { A1 a1; A2 a2; A4 a4; A8 a8; };
+struct S6 { double f(); };
+struct D1 : S1 {};
+struct D2 : S6 { float g(); };
+struct D3 : S2 {};
+struct D4 : S2 { int x; };
+struct D5 : S3 { char c; };
+struct D6 : S2, S3 {};
+struct D7 : S1, S3 {};
+struct D8 : S1, D4, D5 { double x[2]; };
+struct D9 : S1, D1 { S1 s1; };
+struct V1 { virtual ~V1(); };
+struct V2 { int x; virtual ~V2(); };
+struct V3 : V1 {
+ ~V3() override;
+};
+struct V4 : virtual V2 { int y;
+ ~V4() override;
+};
+struct V5 : V4, V3 { double z;
+ ~V5() override;
+};
+struct V6 : S1 { virtual ~V6(); };
+struct V7 : virtual V2, virtual V6 {
+ ~V7() override;
+};
+struct V8 : V5, virtual V6, V7 { double zz;
+ ~V8() override;
+};
+
+double S6::f() { return 0.0; }
+float D2::g() { return 0.0f; }
+V1::~V1() {}
+V2::~V2() {}
+V3::~V3() {}
+V4::~V4() {}
+V5::~V5() {}
+V6::~V6() {}
+V7::~V7() {}
+V8::~V8() {}
+
+struct Abstract1 {
+ virtual ~Abstract1() {}
+ virtual void method() = 0;
+
+ char c;
+};
+
+struct Abstract2 : Abstract1 {
+ virtual ~Abstract2() {}
+ double d;
+};
+
+struct Final final : Abstract2 {
+ void method() override {}
+};
+
+// Ensure alignment is a compile-time constant.
+char LLVM_ATTRIBUTE_UNUSED test_arr1
+ [AlignOf<char>::Alignment > 0]
+ [AlignOf<short>::Alignment > 0]
+ [AlignOf<int>::Alignment > 0]
+ [AlignOf<long>::Alignment > 0]
+ [AlignOf<long long>::Alignment > 0]
+ [AlignOf<float>::Alignment > 0]
+ [AlignOf<double>::Alignment > 0]
+ [AlignOf<long double>::Alignment > 0]
+ [AlignOf<void *>::Alignment > 0]
+ [AlignOf<int *>::Alignment > 0]
+ [AlignOf<double (*)(double)>::Alignment > 0]
+ [AlignOf<double (S6::*)()>::Alignment > 0];
+char LLVM_ATTRIBUTE_UNUSED test_arr2
+ [AlignOf<A1>::Alignment > 0]
+ [AlignOf<A2>::Alignment > 0]
+ [AlignOf<A4>::Alignment > 0]
+ [AlignOf<A8>::Alignment > 0];
+char LLVM_ATTRIBUTE_UNUSED test_arr3
+ [AlignOf<S1>::Alignment > 0]
+ [AlignOf<S2>::Alignment > 0]
+ [AlignOf<S3>::Alignment > 0]
+ [AlignOf<S4>::Alignment > 0]
+ [AlignOf<S5>::Alignment > 0]
+ [AlignOf<S6>::Alignment > 0];
+char LLVM_ATTRIBUTE_UNUSED test_arr4
+ [AlignOf<D1>::Alignment > 0]
+ [AlignOf<D2>::Alignment > 0]
+ [AlignOf<D3>::Alignment > 0]
+ [AlignOf<D4>::Alignment > 0]
+ [AlignOf<D5>::Alignment > 0]
+ [AlignOf<D6>::Alignment > 0]
+ [AlignOf<D7>::Alignment > 0]
+ [AlignOf<D8>::Alignment > 0]
+ [AlignOf<D9>::Alignment > 0];
+char LLVM_ATTRIBUTE_UNUSED test_arr5
+ [AlignOf<V1>::Alignment > 0]
+ [AlignOf<V2>::Alignment > 0]
+ [AlignOf<V3>::Alignment > 0]
+ [AlignOf<V4>::Alignment > 0]
+ [AlignOf<V5>::Alignment > 0]
+ [AlignOf<V6>::Alignment > 0]
+ [AlignOf<V7>::Alignment > 0]
+ [AlignOf<V8>::Alignment > 0];
+
+TEST(AlignOfTest, BasicAlignmentInvariants) {
+ EXPECT_LE(1u, alignOf<A1>());
+ EXPECT_LE(2u, alignOf<A2>());
+ EXPECT_LE(4u, alignOf<A4>());
+ EXPECT_LE(8u, alignOf<A8>());
+
+ EXPECT_EQ(1u, alignOf<char>());
+ EXPECT_LE(alignOf<char>(), alignOf<short>());
+ EXPECT_LE(alignOf<short>(), alignOf<int>());
+ EXPECT_LE(alignOf<int>(), alignOf<long>());
+ EXPECT_LE(alignOf<long>(), alignOf<long long>());
+ EXPECT_LE(alignOf<char>(), alignOf<float>());
+ EXPECT_LE(alignOf<float>(), alignOf<double>());
+ EXPECT_LE(alignOf<char>(), alignOf<long double>());
+ EXPECT_LE(alignOf<char>(), alignOf<void *>());
+ EXPECT_EQ(alignOf<void *>(), alignOf<int *>());
+ EXPECT_LE(alignOf<char>(), alignOf<S1>());
+ EXPECT_LE(alignOf<S1>(), alignOf<S2>());
+ EXPECT_LE(alignOf<S1>(), alignOf<S3>());
+ EXPECT_LE(alignOf<S1>(), alignOf<S4>());
+ EXPECT_LE(alignOf<S1>(), alignOf<S5>());
+ EXPECT_LE(alignOf<S1>(), alignOf<S6>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D1>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D2>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D3>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D4>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D5>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D6>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D7>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D8>());
+ EXPECT_LE(alignOf<S1>(), alignOf<D9>());
+ EXPECT_LE(alignOf<S1>(), alignOf<V1>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V2>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V3>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V4>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V5>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V6>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V7>());
+ EXPECT_LE(alignOf<V1>(), alignOf<V8>());
+
+ EXPECT_LE(alignOf<char>(), alignOf<Abstract1>());
+ EXPECT_LE(alignOf<double>(), alignOf<Abstract2>());
+ EXPECT_LE(alignOf<Abstract2>(), alignOf<Final>());
+}
+
+TEST(AlignOfTest, BasicAlignedArray) {
+ EXPECT_LE(1u, alignOf<AlignedCharArrayUnion<A1> >());
+ EXPECT_LE(2u, alignOf<AlignedCharArrayUnion<A2> >());
+ EXPECT_LE(4u, alignOf<AlignedCharArrayUnion<A4> >());
+ EXPECT_LE(8u, alignOf<AlignedCharArrayUnion<A8> >());
+
+ EXPECT_LE(1u, sizeof(AlignedCharArrayUnion<A1>));
+ EXPECT_LE(2u, sizeof(AlignedCharArrayUnion<A2>));
+ EXPECT_LE(4u, sizeof(AlignedCharArrayUnion<A4>));
+ EXPECT_LE(8u, sizeof(AlignedCharArrayUnion<A8>));
+
+ EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<A1> >()));
+ EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<A1, A2> >()));
+ EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<A1, A2, A4> >()));
+ EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<A1, A2, A4, A8> >()));
+
+ EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<A1>));
+ EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<A1, A2>));
+ EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<A1, A2, A4>));
+ EXPECT_EQ(8u, sizeof(AlignedCharArrayUnion<A1, A2, A4, A8>));
+
+ EXPECT_EQ(1u, (alignOf<AlignedCharArrayUnion<A1[1]> >()));
+ EXPECT_EQ(2u, (alignOf<AlignedCharArrayUnion<A1[2], A2[1]> >()));
+ EXPECT_EQ(4u, (alignOf<AlignedCharArrayUnion<A1[42], A2[55],
+ A4[13]> >()));
+ EXPECT_EQ(8u, (alignOf<AlignedCharArrayUnion<A1[2], A2[1],
+ A4, A8> >()));
+
+ EXPECT_EQ(1u, sizeof(AlignedCharArrayUnion<A1[1]>));
+ EXPECT_EQ(2u, sizeof(AlignedCharArrayUnion<A1[2], A2[1]>));
+ EXPECT_EQ(4u, sizeof(AlignedCharArrayUnion<A1[3], A2[2], A4>));
+ EXPECT_EQ(16u, sizeof(AlignedCharArrayUnion<A1, A2[3],
+ A4[3], A8>));
+
+ // For other tests we simply assert that the alignment of the union mathes
+ // that of the fundamental type and hope that we have any weird type
+ // productions that would trigger bugs.
+ EXPECT_EQ(alignOf<char>(), alignOf<AlignedCharArrayUnion<char> >());
+ EXPECT_EQ(alignOf<short>(), alignOf<AlignedCharArrayUnion<short> >());
+ EXPECT_EQ(alignOf<int>(), alignOf<AlignedCharArrayUnion<int> >());
+ EXPECT_EQ(alignOf<long>(), alignOf<AlignedCharArrayUnion<long> >());
+ EXPECT_EQ(alignOf<long long>(),
+ alignOf<AlignedCharArrayUnion<long long> >());
+ EXPECT_EQ(alignOf<float>(), alignOf<AlignedCharArrayUnion<float> >());
+ EXPECT_EQ(alignOf<double>(), alignOf<AlignedCharArrayUnion<double> >());
+ EXPECT_EQ(alignOf<long double>(),
+ alignOf<AlignedCharArrayUnion<long double> >());
+ EXPECT_EQ(alignOf<void *>(), alignOf<AlignedCharArrayUnion<void *> >());
+ EXPECT_EQ(alignOf<int *>(), alignOf<AlignedCharArrayUnion<int *> >());
+ EXPECT_EQ(alignOf<double (*)(double)>(),
+ alignOf<AlignedCharArrayUnion<double (*)(double)> >());
+ EXPECT_EQ(alignOf<double (S6::*)()>(),
+ alignOf<AlignedCharArrayUnion<double (S6::*)()> >());
+ EXPECT_EQ(alignOf<S1>(), alignOf<AlignedCharArrayUnion<S1> >());
+ EXPECT_EQ(alignOf<S2>(), alignOf<AlignedCharArrayUnion<S2> >());
+ EXPECT_EQ(alignOf<S3>(), alignOf<AlignedCharArrayUnion<S3> >());
+ EXPECT_EQ(alignOf<S4>(), alignOf<AlignedCharArrayUnion<S4> >());
+ EXPECT_EQ(alignOf<S5>(), alignOf<AlignedCharArrayUnion<S5> >());
+ EXPECT_EQ(alignOf<S6>(), alignOf<AlignedCharArrayUnion<S6> >());
+ EXPECT_EQ(alignOf<D1>(), alignOf<AlignedCharArrayUnion<D1> >());
+ EXPECT_EQ(alignOf<D2>(), alignOf<AlignedCharArrayUnion<D2> >());
+ EXPECT_EQ(alignOf<D3>(), alignOf<AlignedCharArrayUnion<D3> >());
+ EXPECT_EQ(alignOf<D4>(), alignOf<AlignedCharArrayUnion<D4> >());
+ EXPECT_EQ(alignOf<D5>(), alignOf<AlignedCharArrayUnion<D5> >());
+ EXPECT_EQ(alignOf<D6>(), alignOf<AlignedCharArrayUnion<D6> >());
+ EXPECT_EQ(alignOf<D7>(), alignOf<AlignedCharArrayUnion<D7> >());
+ EXPECT_EQ(alignOf<D8>(), alignOf<AlignedCharArrayUnion<D8> >());
+ EXPECT_EQ(alignOf<D9>(), alignOf<AlignedCharArrayUnion<D9> >());
+ EXPECT_EQ(alignOf<V1>(), alignOf<AlignedCharArrayUnion<V1> >());
+ EXPECT_EQ(alignOf<V2>(), alignOf<AlignedCharArrayUnion<V2> >());
+ EXPECT_EQ(alignOf<V3>(), alignOf<AlignedCharArrayUnion<V3> >());
+ EXPECT_EQ(alignOf<V4>(), alignOf<AlignedCharArrayUnion<V4> >());
+ EXPECT_EQ(alignOf<V5>(), alignOf<AlignedCharArrayUnion<V5> >());
+ EXPECT_EQ(alignOf<V6>(), alignOf<AlignedCharArrayUnion<V6> >());
+ EXPECT_EQ(alignOf<V7>(), alignOf<AlignedCharArrayUnion<V7> >());
+
+ // Some versions of MSVC get this wrong somewhat disturbingly. The failure
+ // appears to be benign: alignOf<V8>() produces a preposterous value: 12
+#ifndef _MSC_VER
+ EXPECT_EQ(alignOf<V8>(), alignOf<AlignedCharArrayUnion<V8> >());
+#endif
+
+ EXPECT_EQ(sizeof(char), sizeof(AlignedCharArrayUnion<char>));
+ EXPECT_EQ(sizeof(char[1]), sizeof(AlignedCharArrayUnion<char[1]>));
+ EXPECT_EQ(sizeof(char[2]), sizeof(AlignedCharArrayUnion<char[2]>));
+ EXPECT_EQ(sizeof(char[3]), sizeof(AlignedCharArrayUnion<char[3]>));
+ EXPECT_EQ(sizeof(char[4]), sizeof(AlignedCharArrayUnion<char[4]>));
+ EXPECT_EQ(sizeof(char[5]), sizeof(AlignedCharArrayUnion<char[5]>));
+ EXPECT_EQ(sizeof(char[8]), sizeof(AlignedCharArrayUnion<char[8]>));
+ EXPECT_EQ(sizeof(char[13]), sizeof(AlignedCharArrayUnion<char[13]>));
+ EXPECT_EQ(sizeof(char[16]), sizeof(AlignedCharArrayUnion<char[16]>));
+ EXPECT_EQ(sizeof(char[21]), sizeof(AlignedCharArrayUnion<char[21]>));
+ EXPECT_EQ(sizeof(char[32]), sizeof(AlignedCharArrayUnion<char[32]>));
+ EXPECT_EQ(sizeof(short), sizeof(AlignedCharArrayUnion<short>));
+ EXPECT_EQ(sizeof(int), sizeof(AlignedCharArrayUnion<int>));
+ EXPECT_EQ(sizeof(long), sizeof(AlignedCharArrayUnion<long>));
+ EXPECT_EQ(sizeof(long long),
+ sizeof(AlignedCharArrayUnion<long long>));
+ EXPECT_EQ(sizeof(float), sizeof(AlignedCharArrayUnion<float>));
+ EXPECT_EQ(sizeof(double), sizeof(AlignedCharArrayUnion<double>));
+ EXPECT_EQ(sizeof(long double),
+ sizeof(AlignedCharArrayUnion<long double>));
+ EXPECT_EQ(sizeof(void *), sizeof(AlignedCharArrayUnion<void *>));
+ EXPECT_EQ(sizeof(int *), sizeof(AlignedCharArrayUnion<int *>));
+ EXPECT_EQ(sizeof(double (*)(double)),
+ sizeof(AlignedCharArrayUnion<double (*)(double)>));
+ EXPECT_EQ(sizeof(double (S6::*)()),
+ sizeof(AlignedCharArrayUnion<double (S6::*)()>));
+ EXPECT_EQ(sizeof(S1), sizeof(AlignedCharArrayUnion<S1>));
+ EXPECT_EQ(sizeof(S2), sizeof(AlignedCharArrayUnion<S2>));
+ EXPECT_EQ(sizeof(S3), sizeof(AlignedCharArrayUnion<S3>));
+ EXPECT_EQ(sizeof(S4), sizeof(AlignedCharArrayUnion<S4>));
+ EXPECT_EQ(sizeof(S5), sizeof(AlignedCharArrayUnion<S5>));
+ EXPECT_EQ(sizeof(S6), sizeof(AlignedCharArrayUnion<S6>));
+ EXPECT_EQ(sizeof(D1), sizeof(AlignedCharArrayUnion<D1>));
+ EXPECT_EQ(sizeof(D2), sizeof(AlignedCharArrayUnion<D2>));
+ EXPECT_EQ(sizeof(D3), sizeof(AlignedCharArrayUnion<D3>));
+ EXPECT_EQ(sizeof(D4), sizeof(AlignedCharArrayUnion<D4>));
+ EXPECT_EQ(sizeof(D5), sizeof(AlignedCharArrayUnion<D5>));
+ EXPECT_EQ(sizeof(D6), sizeof(AlignedCharArrayUnion<D6>));
+ EXPECT_EQ(sizeof(D7), sizeof(AlignedCharArrayUnion<D7>));
+ EXPECT_EQ(sizeof(D8), sizeof(AlignedCharArrayUnion<D8>));
+ EXPECT_EQ(sizeof(D9), sizeof(AlignedCharArrayUnion<D9>));
+ EXPECT_EQ(sizeof(D9[1]), sizeof(AlignedCharArrayUnion<D9[1]>));
+ EXPECT_EQ(sizeof(D9[2]), sizeof(AlignedCharArrayUnion<D9[2]>));
+ EXPECT_EQ(sizeof(D9[3]), sizeof(AlignedCharArrayUnion<D9[3]>));
+ EXPECT_EQ(sizeof(D9[4]), sizeof(AlignedCharArrayUnion<D9[4]>));
+ EXPECT_EQ(sizeof(D9[5]), sizeof(AlignedCharArrayUnion<D9[5]>));
+ EXPECT_EQ(sizeof(D9[8]), sizeof(AlignedCharArrayUnion<D9[8]>));
+ EXPECT_EQ(sizeof(D9[13]), sizeof(AlignedCharArrayUnion<D9[13]>));
+ EXPECT_EQ(sizeof(D9[16]), sizeof(AlignedCharArrayUnion<D9[16]>));
+ EXPECT_EQ(sizeof(D9[21]), sizeof(AlignedCharArrayUnion<D9[21]>));
+ EXPECT_EQ(sizeof(D9[32]), sizeof(AlignedCharArrayUnion<D9[32]>));
+ EXPECT_EQ(sizeof(V1), sizeof(AlignedCharArrayUnion<V1>));
+ EXPECT_EQ(sizeof(V2), sizeof(AlignedCharArrayUnion<V2>));
+ EXPECT_EQ(sizeof(V3), sizeof(AlignedCharArrayUnion<V3>));
+ EXPECT_EQ(sizeof(V4), sizeof(AlignedCharArrayUnion<V4>));
+ EXPECT_EQ(sizeof(V5), sizeof(AlignedCharArrayUnion<V5>));
+ EXPECT_EQ(sizeof(V6), sizeof(AlignedCharArrayUnion<V6>));
+ EXPECT_EQ(sizeof(V7), sizeof(AlignedCharArrayUnion<V7>));
+
+ // Some versions of MSVC also get this wrong. The failure again appears to be
+ // benign: sizeof(V8) is only 52 bytes, but our array reserves 56.
+#ifndef _MSC_VER
+ EXPECT_EQ(sizeof(V8), sizeof(AlignedCharArrayUnion<V8>));
+#endif
+
+ EXPECT_EQ(1u, (alignOf<AlignedCharArray<1, 1> >()));
+ EXPECT_EQ(2u, (alignOf<AlignedCharArray<2, 1> >()));
+ EXPECT_EQ(4u, (alignOf<AlignedCharArray<4, 1> >()));
+ EXPECT_EQ(8u, (alignOf<AlignedCharArray<8, 1> >()));
+ EXPECT_EQ(16u, (alignOf<AlignedCharArray<16, 1> >()));
+
+ EXPECT_EQ(1u, sizeof(AlignedCharArray<1, 1>));
+ EXPECT_EQ(7u, sizeof(AlignedCharArray<1, 7>));
+ EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>));
+ EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>));
+}
+}
diff --git a/gnu/llvm/unittests/Support/AllocatorTest.cpp b/gnu/llvm/unittests/Support/AllocatorTest.cpp
new file mode 100644
index 00000000000..4b544641e9b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/AllocatorTest.cpp
@@ -0,0 +1,188 @@
+//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Allocator.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+namespace {
+
+TEST(AllocatorTest, Basics) {
+ BumpPtrAllocator Alloc;
+ int *a = (int*)Alloc.Allocate(sizeof(int), 1);
+ int *b = (int*)Alloc.Allocate(sizeof(int) * 10, 1);
+ int *c = (int*)Alloc.Allocate(sizeof(int), 1);
+ *a = 1;
+ b[0] = 2;
+ b[9] = 2;
+ *c = 3;
+ EXPECT_EQ(1, *a);
+ EXPECT_EQ(2, b[0]);
+ EXPECT_EQ(2, b[9]);
+ EXPECT_EQ(3, *c);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+
+ BumpPtrAllocator Alloc2 = std::move(Alloc);
+ EXPECT_EQ(0U, Alloc.GetNumSlabs());
+ EXPECT_EQ(1U, Alloc2.GetNumSlabs());
+
+ // Make sure the old pointers still work. These are especially interesting
+ // under ASan or Valgrind.
+ EXPECT_EQ(1, *a);
+ EXPECT_EQ(2, b[0]);
+ EXPECT_EQ(2, b[9]);
+ EXPECT_EQ(3, *c);
+
+ Alloc = std::move(Alloc2);
+ EXPECT_EQ(0U, Alloc2.GetNumSlabs());
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+}
+
+// Allocate enough bytes to create three slabs.
+TEST(AllocatorTest, ThreeSlabs) {
+ BumpPtrAllocator Alloc;
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(2U, Alloc.GetNumSlabs());
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(3U, Alloc.GetNumSlabs());
+}
+
+// Allocate enough bytes to create two slabs, reset the allocator, and do it
+// again.
+TEST(AllocatorTest, TestReset) {
+ BumpPtrAllocator Alloc;
+
+ // Allocate something larger than the SizeThreshold=4096.
+ (void)Alloc.Allocate(5000, 1);
+ Alloc.Reset();
+ // Calling Reset should free all CustomSizedSlabs.
+ EXPECT_EQ(0u, Alloc.GetNumSlabs());
+
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(2U, Alloc.GetNumSlabs());
+ Alloc.Reset();
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+ Alloc.Allocate(3000, 1);
+ EXPECT_EQ(2U, Alloc.GetNumSlabs());
+}
+
+// Test some allocations at varying alignments.
+TEST(AllocatorTest, TestAlignment) {
+ BumpPtrAllocator Alloc;
+ uintptr_t a;
+ a = (uintptr_t)Alloc.Allocate(1, 2);
+ EXPECT_EQ(0U, a & 1);
+ a = (uintptr_t)Alloc.Allocate(1, 4);
+ EXPECT_EQ(0U, a & 3);
+ a = (uintptr_t)Alloc.Allocate(1, 8);
+ EXPECT_EQ(0U, a & 7);
+ a = (uintptr_t)Alloc.Allocate(1, 16);
+ EXPECT_EQ(0U, a & 15);
+ a = (uintptr_t)Alloc.Allocate(1, 32);
+ EXPECT_EQ(0U, a & 31);
+ a = (uintptr_t)Alloc.Allocate(1, 64);
+ EXPECT_EQ(0U, a & 63);
+ a = (uintptr_t)Alloc.Allocate(1, 128);
+ EXPECT_EQ(0U, a & 127);
+}
+
+// Test allocating just over the slab size. This tests a bug where before the
+// allocator incorrectly calculated the buffer end pointer.
+TEST(AllocatorTest, TestOverflow) {
+ BumpPtrAllocator Alloc;
+
+ // Fill the slab right up until the end pointer.
+ Alloc.Allocate(4096, 1);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+
+ // If we don't allocate a new slab, then we will have overflowed.
+ Alloc.Allocate(1, 1);
+ EXPECT_EQ(2U, Alloc.GetNumSlabs());
+}
+
+// Test allocating with a size larger than the initial slab size.
+TEST(AllocatorTest, TestSmallSlabSize) {
+ BumpPtrAllocator Alloc;
+
+ Alloc.Allocate(8000, 1);
+ EXPECT_EQ(1U, Alloc.GetNumSlabs());
+}
+
+// Test requesting alignment that goes past the end of the current slab.
+TEST(AllocatorTest, TestAlignmentPastSlab) {
+ BumpPtrAllocator Alloc;
+ Alloc.Allocate(4095, 1);
+
+ // Aligning the current slab pointer is likely to move it past the end of the
+ // slab, which would confuse any unsigned comparisons with the difference of
+ // the end pointer and the aligned pointer.
+ Alloc.Allocate(1024, 8192);
+
+ EXPECT_EQ(2U, Alloc.GetNumSlabs());
+}
+
+// Mock slab allocator that returns slabs aligned on 4096 bytes. There is no
+// easy portable way to do this, so this is kind of a hack.
+class MockSlabAllocator {
+ static size_t LastSlabSize;
+
+public:
+ ~MockSlabAllocator() { }
+
+ void *Allocate(size_t Size, size_t /*Alignment*/) {
+ // Allocate space for the alignment, the slab, and a void* that goes right
+ // before the slab.
+ size_t Alignment = 4096;
+ void *MemBase = malloc(Size + Alignment - 1 + sizeof(void*));
+
+ // Find the slab start.
+ void *Slab = (void *)alignAddr((char*)MemBase + sizeof(void *), Alignment);
+
+ // Hold a pointer to the base so we can free the whole malloced block.
+ ((void**)Slab)[-1] = MemBase;
+
+ LastSlabSize = Size;
+ return Slab;
+ }
+
+ void Deallocate(void *Slab, size_t Size) {
+ free(((void**)Slab)[-1]);
+ }
+
+ static size_t GetLastSlabSize() { return LastSlabSize; }
+};
+
+size_t MockSlabAllocator::LastSlabSize = 0;
+
+// Allocate a large-ish block with a really large alignment so that the
+// allocator will think that it has space, but after it does the alignment it
+// will not.
+TEST(AllocatorTest, TestBigAlignment) {
+ BumpPtrAllocatorImpl<MockSlabAllocator> Alloc;
+
+ // First allocate a tiny bit to ensure we have to re-align things.
+ (void)Alloc.Allocate(1, 1);
+
+ // Now the big chunk with a big alignment.
+ (void)Alloc.Allocate(3000, 2048);
+
+ // We test that the last slab size is not the default 4096 byte slab, but
+ // rather a custom sized slab that is larger.
+ EXPECT_GT(MockSlabAllocator::GetLastSlabSize(), 4096u);
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/ArrayRecyclerTest.cpp b/gnu/llvm/unittests/Support/ArrayRecyclerTest.cpp
new file mode 100644
index 00000000000..1ff97ba9e2b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ArrayRecyclerTest.cpp
@@ -0,0 +1,109 @@
+//===--- unittest/Support/ArrayRecyclerTest.cpp ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ArrayRecycler.h"
+#include "llvm/Support/Allocator.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+
+namespace {
+
+struct Object {
+ int Num;
+ Object *Other;
+};
+typedef ArrayRecycler<Object> ARO;
+
+TEST(ArrayRecyclerTest, Capacity) {
+ // Capacity size should never be 0.
+ ARO::Capacity Cap = ARO::Capacity::get(0);
+ EXPECT_LT(0u, Cap.getSize());
+
+ size_t PrevSize = Cap.getSize();
+ for (unsigned N = 1; N != 100; ++N) {
+ Cap = ARO::Capacity::get(N);
+ EXPECT_LE(N, Cap.getSize());
+ if (PrevSize >= N)
+ EXPECT_EQ(PrevSize, Cap.getSize());
+ else
+ EXPECT_LT(PrevSize, Cap.getSize());
+ PrevSize = Cap.getSize();
+ }
+
+ // Check that the buckets are monotonically increasing.
+ Cap = ARO::Capacity::get(0);
+ PrevSize = Cap.getSize();
+ for (unsigned N = 0; N != 20; ++N) {
+ Cap = Cap.getNext();
+ EXPECT_LT(PrevSize, Cap.getSize());
+ PrevSize = Cap.getSize();
+ }
+}
+
+TEST(ArrayRecyclerTest, Basics) {
+ BumpPtrAllocator Allocator;
+ ArrayRecycler<Object> DUT;
+
+ ARO::Capacity Cap = ARO::Capacity::get(8);
+ Object *A1 = DUT.allocate(Cap, Allocator);
+ A1[0].Num = 21;
+ A1[7].Num = 17;
+
+ Object *A2 = DUT.allocate(Cap, Allocator);
+ A2[0].Num = 121;
+ A2[7].Num = 117;
+
+ Object *A3 = DUT.allocate(Cap, Allocator);
+ A3[0].Num = 221;
+ A3[7].Num = 217;
+
+ EXPECT_EQ(21, A1[0].Num);
+ EXPECT_EQ(17, A1[7].Num);
+ EXPECT_EQ(121, A2[0].Num);
+ EXPECT_EQ(117, A2[7].Num);
+ EXPECT_EQ(221, A3[0].Num);
+ EXPECT_EQ(217, A3[7].Num);
+
+ DUT.deallocate(Cap, A2);
+
+ // Check that deallocation didn't clobber anything.
+ EXPECT_EQ(21, A1[0].Num);
+ EXPECT_EQ(17, A1[7].Num);
+ EXPECT_EQ(221, A3[0].Num);
+ EXPECT_EQ(217, A3[7].Num);
+
+ // Verify recycling.
+ Object *A2x = DUT.allocate(Cap, Allocator);
+ EXPECT_EQ(A2, A2x);
+
+ DUT.deallocate(Cap, A2x);
+ DUT.deallocate(Cap, A1);
+ DUT.deallocate(Cap, A3);
+
+ // Objects are not required to be recycled in reverse deallocation order, but
+ // that is what the current implementation does.
+ Object *A3x = DUT.allocate(Cap, Allocator);
+ EXPECT_EQ(A3, A3x);
+ Object *A1x = DUT.allocate(Cap, Allocator);
+ EXPECT_EQ(A1, A1x);
+ Object *A2y = DUT.allocate(Cap, Allocator);
+ EXPECT_EQ(A2, A2y);
+
+ // Back to allocation from the BumpPtrAllocator.
+ Object *A4 = DUT.allocate(Cap, Allocator);
+ EXPECT_NE(A1, A4);
+ EXPECT_NE(A2, A4);
+ EXPECT_NE(A3, A4);
+
+ DUT.clear(Allocator);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Support/BlockFrequencyTest.cpp b/gnu/llvm/unittests/Support/BlockFrequencyTest.cpp
new file mode 100644
index 00000000000..c1f5671815b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/BlockFrequencyTest.cpp
@@ -0,0 +1,128 @@
+//===- unittests/Support/BlockFrequencyTest.cpp - BlockFrequency tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BlockFrequency.h"
+#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+#include <climits>
+
+using namespace llvm;
+
+namespace {
+
+TEST(BlockFrequencyTest, OneToZero) {
+ BlockFrequency Freq(1);
+ BranchProbability Prob(UINT32_MAX / 3, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 0u);
+
+ Freq = BlockFrequency(1);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 0u);
+}
+
+TEST(BlockFrequencyTest, OneToOne) {
+ BlockFrequency Freq(1);
+ BranchProbability Prob(UINT32_MAX, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(1);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+}
+
+TEST(BlockFrequencyTest, ThreeToOne) {
+ BlockFrequency Freq(3);
+ BranchProbability Prob(3000000, 9000000);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+
+ Freq = BlockFrequency(3);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 1u);
+}
+
+TEST(BlockFrequencyTest, MaxToHalfMax) {
+ BlockFrequency Freq(UINT64_MAX);
+ BranchProbability Prob(UINT32_MAX / 2, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 9223372036854775807ULL);
+
+ Freq = BlockFrequency(UINT64_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), 9223372036854775807ULL);
+}
+
+TEST(BlockFrequencyTest, BigToBig) {
+ const uint64_t Big = 387246523487234346LL;
+ const uint32_t P = 123456789;
+ BlockFrequency Freq(Big);
+ BranchProbability Prob(P, P);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), Big);
+
+ Freq = BlockFrequency(Big);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), Big);
+}
+
+TEST(BlockFrequencyTest, MaxToMax) {
+ BlockFrequency Freq(UINT64_MAX);
+ BranchProbability Prob(UINT32_MAX, UINT32_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ // This additionally makes sure if we have a value equal to our saturating
+ // value, we do not signal saturation if the result equals said value, but
+ // saturating does not occur.
+ Freq = BlockFrequency(UINT64_MAX);
+ Freq *= Prob;
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+}
+
+TEST(BlockFrequencyTest, Subtract) {
+ BlockFrequency Freq1(0), Freq2(1);
+ EXPECT_EQ((Freq1 - Freq2).getFrequency(), 0u);
+ EXPECT_EQ((Freq2 - Freq1).getFrequency(), 1u);
+}
+
+TEST(BlockFrequency, Divide) {
+ BlockFrequency Freq(0x3333333333333333ULL);
+ Freq /= BranchProbability(1, 2);
+ EXPECT_EQ(Freq.getFrequency(), 0x6666666666666666ULL);
+}
+
+TEST(BlockFrequencyTest, Saturate) {
+ BlockFrequency Freq(0x3333333333333333ULL);
+ Freq /= BranchProbability(100, 300);
+ EXPECT_EQ(Freq.getFrequency(), 0x9999999866666668ULL);
+ Freq /= BranchProbability(1, 2);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ Freq = 0x1000000000000000ULL;
+ Freq /= BranchProbability(10000, 170000);
+ EXPECT_EQ(Freq.getFrequency(), UINT64_MAX);
+
+ // Try to cheat the multiplication overflow check.
+ Freq = 0x00000001f0000001ull;
+ Freq /= BranchProbability(1000, 0xf000000f);
+ EXPECT_EQ(33527736066704712ULL, Freq.getFrequency());
+}
+
+TEST(BlockFrequencyTest, SaturatingRightShift) {
+ BlockFrequency Freq(0x10080ULL);
+ Freq >>= 2;
+ EXPECT_EQ(Freq.getFrequency(), 0x4020ULL);
+ Freq >>= 20;
+ EXPECT_EQ(Freq.getFrequency(), 0x1ULL);
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/BranchProbabilityTest.cpp b/gnu/llvm/unittests/Support/BranchProbabilityTest.cpp
new file mode 100644
index 00000000000..f03b09b66e8
--- /dev/null
+++ b/gnu/llvm/unittests/Support/BranchProbabilityTest.cpp
@@ -0,0 +1,358 @@
+//===- unittest/Support/BranchProbabilityTest.cpp - BranchProbability tests -=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace llvm {
+void PrintTo(BranchProbability P, ::std::ostream *os) {
+ *os << P.getNumerator() << "/" << P.getDenominator();
+}
+}
+namespace {
+
+typedef BranchProbability BP;
+TEST(BranchProbabilityTest, Accessors) {
+ EXPECT_EQ(306783378u, BP(1, 7).getNumerator());
+ EXPECT_EQ(1u << 31, BP(1, 7).getDenominator());
+ EXPECT_EQ(0u, BP::getZero().getNumerator());
+ EXPECT_EQ(1u << 31, BP::getZero().getDenominator());
+ EXPECT_EQ(1u << 31, BP::getOne().getNumerator());
+ EXPECT_EQ(1u << 31, BP::getOne().getDenominator());
+}
+
+TEST(BranchProbabilityTest, Operators) {
+ EXPECT_TRUE(BP(1, 7) < BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) < BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) < BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) < BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) < BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) < BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) < BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) > BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) > BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) > BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) > BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) > BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) > BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) > BP(3, 7));
+
+ EXPECT_TRUE(BP(1, 7) <= BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) <= BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) <= BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) <= BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) <= BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) <= BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) <= BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) >= BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) >= BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) >= BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) >= BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) >= BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) >= BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) >= BP(3, 7));
+
+ EXPECT_FALSE(BP(1, 7) == BP(2, 7));
+ EXPECT_FALSE(BP(1, 7) == BP(1, 4));
+ EXPECT_FALSE(BP(5, 7) == BP(3, 4));
+ EXPECT_TRUE(BP(1, 7) == BP(1, 7));
+ EXPECT_TRUE(BP(1, 7) == BP(2, 14));
+ EXPECT_FALSE(BP(4, 7) == BP(1, 2));
+ EXPECT_FALSE(BP(4, 7) == BP(3, 7));
+
+ EXPECT_TRUE(BP(1, 7) != BP(2, 7));
+ EXPECT_TRUE(BP(1, 7) != BP(1, 4));
+ EXPECT_TRUE(BP(5, 7) != BP(3, 4));
+ EXPECT_FALSE(BP(1, 7) != BP(1, 7));
+ EXPECT_FALSE(BP(1, 7) != BP(2, 14));
+ EXPECT_TRUE(BP(4, 7) != BP(1, 2));
+ EXPECT_TRUE(BP(4, 7) != BP(3, 7));
+
+ EXPECT_TRUE(BP(1, 7) == BP(2, 14));
+ EXPECT_TRUE(BP(1, 7) == BP(3, 21));
+ EXPECT_TRUE(BP(5, 7) == BP(25, 35));
+ EXPECT_TRUE(BP(99999998, 100000000) < BP(99999999, 100000000));
+ EXPECT_TRUE(BP(4, 8) == BP(400000000, 800000000));
+}
+
+TEST(BranchProbabilityTest, MoreOperators) {
+ BP A(4, 5);
+ BP B(4U << 29, 5U << 29);
+ BP C(3, 4);
+
+ EXPECT_TRUE(A == B);
+ EXPECT_FALSE(A != B);
+ EXPECT_FALSE(A < B);
+ EXPECT_FALSE(A > B);
+ EXPECT_TRUE(A <= B);
+ EXPECT_TRUE(A >= B);
+
+ EXPECT_FALSE(B == C);
+ EXPECT_TRUE(B != C);
+ EXPECT_FALSE(B < C);
+ EXPECT_TRUE(B > C);
+ EXPECT_FALSE(B <= C);
+ EXPECT_TRUE(B >= C);
+
+ BP BigZero(0, UINT32_MAX);
+ BP BigOne(UINT32_MAX, UINT32_MAX);
+ EXPECT_FALSE(BigZero == BigOne);
+ EXPECT_TRUE(BigZero != BigOne);
+ EXPECT_TRUE(BigZero < BigOne);
+ EXPECT_FALSE(BigZero > BigOne);
+ EXPECT_TRUE(BigZero <= BigOne);
+ EXPECT_FALSE(BigZero >= BigOne);
+}
+
+TEST(BranchProbabilityTest, getCompl) {
+ EXPECT_EQ(BP(5, 7), BP(2, 7).getCompl());
+ EXPECT_EQ(BP(2, 7), BP(5, 7).getCompl());
+ EXPECT_EQ(BP::getZero(), BP(7, 7).getCompl());
+ EXPECT_EQ(BP::getOne(), BP(0, 7).getCompl());
+}
+
+TEST(BranchProbabilityTest, scale) {
+ // Multiply by 1.0.
+ EXPECT_EQ(UINT64_MAX, BP(1, 1).scale(UINT64_MAX));
+ EXPECT_EQ(UINT64_MAX, BP(7, 7).scale(UINT64_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(1, 1).scale(UINT32_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(7, 7).scale(UINT32_MAX));
+ EXPECT_EQ(0u, BP(1, 1).scale(0));
+ EXPECT_EQ(0u, BP(7, 7).scale(0));
+
+ // Multiply by 0.0.
+ EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
+ EXPECT_EQ(0u, BP(0, 1).scale(UINT64_MAX));
+ EXPECT_EQ(0u, BP(0, 1).scale(0));
+
+ auto Two63 = UINT64_C(1) << 63;
+ auto Two31 = UINT64_C(1) << 31;
+
+ // Multiply by 0.5.
+ EXPECT_EQ(Two63 - 1, BP(1, 2).scale(UINT64_MAX));
+
+ // Big fractions.
+ EXPECT_EQ(1u, BP(Two31, UINT32_MAX).scale(2));
+ EXPECT_EQ(Two31, BP(Two31, UINT32_MAX).scale(Two31 * 2));
+ EXPECT_EQ(9223372036854775807ULL, BP(Two31, UINT32_MAX).scale(UINT64_MAX));
+
+ // High precision.
+ EXPECT_EQ(UINT64_C(9223372045444710399),
+ BP(Two31 + 1, UINT32_MAX - 2).scale(UINT64_MAX));
+}
+
+TEST(BranchProbabilityTest, scaleByInverse) {
+ // Divide by 1.0.
+ EXPECT_EQ(UINT64_MAX, BP(1, 1).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(UINT64_MAX, BP(7, 7).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(1, 1).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(UINT32_MAX, BP(7, 7).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(0u, BP(1, 1).scaleByInverse(0));
+ EXPECT_EQ(0u, BP(7, 7).scaleByInverse(0));
+
+ auto MAX_DENOMINATOR = BP::getDenominator();
+
+ // Divide by something very small.
+ EXPECT_EQ(UINT64_MAX, BP(1, UINT32_MAX).scaleByInverse(UINT64_MAX));
+ EXPECT_EQ(uint64_t(UINT32_MAX) * MAX_DENOMINATOR,
+ BP(1, MAX_DENOMINATOR).scaleByInverse(UINT32_MAX));
+ EXPECT_EQ(MAX_DENOMINATOR, BP(1, MAX_DENOMINATOR).scaleByInverse(1));
+
+ auto Two63 = UINT64_C(1) << 63;
+ auto Two31 = UINT64_C(1) << 31;
+
+ // Divide by 0.5.
+ EXPECT_EQ(UINT64_MAX - 1, BP(1, 2).scaleByInverse(Two63 - 1));
+ EXPECT_EQ(UINT64_MAX, BP(1, 2).scaleByInverse(Two63));
+
+ // Big fractions.
+ EXPECT_EQ(2u, BP(Two31, UINT32_MAX).scaleByInverse(1));
+ EXPECT_EQ(2u, BP(Two31 - 1, UINT32_MAX).scaleByInverse(1));
+ EXPECT_EQ(Two31 * 2, BP(Two31, UINT32_MAX).scaleByInverse(Two31));
+ EXPECT_EQ(Two31 * 2, BP(Two31 - 1, UINT32_MAX).scaleByInverse(Two31));
+ EXPECT_EQ(UINT64_MAX, BP(Two31, UINT32_MAX).scaleByInverse(Two63 + Two31));
+
+ // High precision. The exact answers to these are close to the successors of
+ // the floor. If we were rounding, these would round up.
+ EXPECT_EQ(UINT64_C(18446744060824649767),
+ BP(Two31 + 2, UINT32_MAX - 2)
+ .scaleByInverse(UINT64_C(9223372047592194056)));
+ EXPECT_EQ(UINT64_C(18446744060824649739),
+ BP(Two31 + 1, UINT32_MAX).scaleByInverse(Two63 + Two31));
+}
+
+TEST(BranchProbabilityTest, scaleBruteForce) {
+ struct {
+ uint64_t Num;
+ uint32_t Prob[2];
+ uint64_t Result;
+ } Tests[] = {
+ // Data for scaling that results in <= 64 bit division.
+ { 0x1423e2a50ULL, { 0x64819521, 0x7765dd13 }, 0x10f418888ULL },
+ { 0x35ef14ceULL, { 0x28ade3c7, 0x304532ae }, 0x2d73c33bULL },
+ { 0xd03dbfbe24ULL, { 0x790079, 0xe419f3 }, 0x6e776fc2c4ULL },
+ { 0x21d67410bULL, { 0x302a9dc2, 0x3ddb4442 }, 0x1a5948fd4ULL },
+ { 0x8664aeadULL, { 0x3d523513, 0x403523b1 }, 0x805a04cfULL },
+ { 0x201db0cf4ULL, { 0x35112a7b, 0x79fc0c74 }, 0xdf8b07f8ULL },
+ { 0x13f1e4430aULL, { 0x21c92bf, 0x21e63aae }, 0x13e0cba26ULL },
+ { 0x16c83229ULL, { 0x3793f66f, 0x53180dea }, 0xf3ce7b6ULL },
+ { 0xc62415be8ULL, { 0x9cc4a63, 0x4327ae9b }, 0x1ce8b71c1ULL },
+ { 0x6fac5e434ULL, { 0xe5f9170, 0x1115e10b }, 0x5df23dd4cULL },
+ { 0x1929375f2ULL, { 0x3a851375, 0x76c08456 }, 0xc662b083ULL },
+ { 0x243c89db6ULL, { 0x354ebfc0, 0x450ef197 }, 0x1bf8c1663ULL },
+ { 0x310e9b31aULL, { 0x1b1b8acf, 0x2d3629f0 }, 0x1d69c93f9ULL },
+ { 0xa1fae921dULL, { 0xa7a098c, 0x10469f44 }, 0x684413d6eULL },
+ { 0xc1582d957ULL, { 0x498e061, 0x59856bc }, 0x9edc5f4ecULL },
+ { 0x57cfee75ULL, { 0x1d061dc3, 0x7c8bfc17 }, 0x1476a220ULL },
+ { 0x139220080ULL, { 0x294a6c71, 0x2a2b07c9 }, 0x1329e1c75ULL },
+ { 0x1665d353cULL, { 0x7080db5, 0xde0d75c }, 0xb590d9faULL },
+ { 0xe8f14541ULL, { 0x5188e8b2, 0x736527ef }, 0xa4971be5ULL },
+ { 0x2f4775f29ULL, { 0x254ef0fe, 0x435fcf50 }, 0x1a2e449c1ULL },
+ { 0x27b85d8d7ULL, { 0x304c8220, 0x5de678f2 }, 0x146e3befbULL },
+ { 0x1d362e36bULL, { 0x36c85b12, 0x37a66f55 }, 0x1cc19b8e7ULL },
+ { 0x155fd48c7ULL, { 0xf5894d, 0x1256108 }, 0x11e383604ULL },
+ { 0xb5db2d15ULL, { 0x39bb26c5, 0x5bdcda3e }, 0x72499259ULL },
+ { 0x153990298ULL, { 0x48921c09, 0x706eb817 }, 0xdb3268e7ULL },
+ { 0x28a7c3ed7ULL, { 0x1f776fd7, 0x349f7a70 }, 0x184f73ae2ULL },
+ { 0x724dbeabULL, { 0x1bd149f5, 0x253a085e }, 0x5569c0b3ULL },
+ { 0xd8f0c513ULL, { 0x18c8cc4c, 0x1b72bad0 }, 0xc3e30642ULL },
+ { 0x17ce3dcbULL, { 0x1e4c6260, 0x233b359e }, 0x1478f4afULL },
+ { 0x1ce036ce0ULL, { 0x29e3c8af, 0x5318dd4a }, 0xe8e76195ULL },
+ { 0x1473ae2aULL, { 0x29b897ba, 0x2be29378 }, 0x13718185ULL },
+ { 0x1dd41aa68ULL, { 0x3d0a4441, 0x5a0e8f12 }, 0x1437b6bbfULL },
+ { 0x1b49e4a53ULL, { 0x3430c1fe, 0x5a204aed }, 0xfcd6852fULL },
+ { 0x217941b19ULL, { 0x12ced2bd, 0x21b68310 }, 0x12aca65b1ULL },
+ { 0xac6a4dc8ULL, { 0x3ed68da8, 0x6fdca34c }, 0x60da926dULL },
+ { 0x1c503a4e7ULL, { 0xfcbbd32, 0x11e48d17 }, 0x18fec7d37ULL },
+ { 0x1c885855ULL, { 0x213e919d, 0x25941897 }, 0x193de742ULL },
+ { 0x29b9c168eULL, { 0x2b644aea, 0x45725ee7 }, 0x1a122e5d4ULL },
+ { 0x806a33f2ULL, { 0x30a80a23, 0x5063733a }, 0x4db9a264ULL },
+ { 0x282afc96bULL, { 0x143ae554, 0x1a9863ff }, 0x1e8de5204ULL },
+ // Data for scaling that results in > 64 bit division.
+ { 0x23ca5f2f672ca41cULL, { 0xecbc641, 0x111373f7 }, 0x1f0301e5c76869c6ULL },
+ { 0x5e4f2468142265e3ULL, { 0x1ddf5837, 0x32189233 }, 0x383ca7bad6053ac9ULL },
+ { 0x277a1a6f6b266bf6ULL, { 0x415d81a8, 0x61eb5e1e }, 0x1a5a3e1d1c9e8540ULL },
+ { 0x1bdbb49a237035cbULL, { 0xea5bf17, 0x1d25ffb3 }, 0xdffc51c5cb51cf1ULL },
+ { 0x2bce6d29b64fb8ULL, { 0x3bfd5631, 0x7525c9bb }, 0x166ebedd9581fdULL },
+ { 0x3a02116103df5013ULL, { 0x2ee18a83, 0x3299aea8 }, 0x35be89227276f105ULL },
+ { 0x7b5762390799b18cULL, { 0x12f8e5b9, 0x2563bcd4 }, 0x3e960077695655a3ULL },
+ { 0x69cfd72537021579ULL, { 0x4c35f468, 0x6a40feee }, 0x4be4cb38695a4f30ULL },
+ { 0x49dfdf835120f1c1ULL, { 0x8cb3759, 0x559eb891 }, 0x79663f6e3c8d8f6ULL },
+ { 0x74b5be5c27676381ULL, { 0x47e4c5e0, 0x7c7b19ff }, 0x4367d2dfb22b3265ULL },
+ { 0x4f50f97075e7f431ULL, { 0x9a50a17, 0x11cd1185 }, 0x2af952b30374f382ULL },
+ { 0x2f8b0d712e393be4ULL, { 0x1487e386, 0x15aa356e }, 0x2d0df3649b2b19fcULL },
+ { 0x224c1c75999d3deULL, { 0x3b2df0ea, 0x4523b100 }, 0x1d5b481d160dd8bULL },
+ { 0x2bcbcea22a399a76ULL, { 0x28b58212, 0x48dd013e }, 0x187814d0610c8a56ULL },
+ { 0x1dbfca91257cb2d1ULL, { 0x1a8c04d9, 0x5e92502c }, 0x859cf7d19e83ad0ULL },
+ { 0x7f20039b57cda935ULL, { 0xeccf651, 0x323f476e }, 0x25720cd9054634bdULL },
+ { 0x40512c6a586aa087ULL, { 0x113b0423, 0x398c9eab }, 0x1341c03dbb662054ULL },
+ { 0x63d802693f050a11ULL, { 0xf50cdd6, 0xfce2a44 }, 0x60c0177b667a4feaULL },
+ { 0x2d956b422838de77ULL, { 0xb2d345b, 0x1321e557 }, 0x1aa0ed16b094575cULL },
+ { 0x5a1cdf0c1657bc91ULL, { 0x1d77bb0c, 0x1f991ff1 }, 0x54097ee9907290eaULL },
+ { 0x3801b26d7e00176bULL, { 0xeed25da, 0x1a819d8b }, 0x1f89e96a616b9abeULL },
+ { 0x37655e74338e1e45ULL, { 0x300e170a, 0x5a1595fe }, 0x1d8cfb55ff6a6dbcULL },
+ { 0x7b38703f2a84e6ULL, { 0x66d9053, 0xc79b6b9 }, 0x3f7d4c91b9afb9ULL },
+ { 0x2245063c0acb3215ULL, { 0x30ce2f5b, 0x610e7271 }, 0x113b916455fe2560ULL },
+ { 0x6bc195877b7b8a7eULL, { 0x392004aa, 0x4a24e60c }, 0x530594fabfc81cc3ULL },
+ { 0x40a3fde23c7b43dbULL, { 0x4e712195, 0x6553e56e }, 0x320a799bc205c78dULL },
+ { 0x1d3dfc2866fbccbaULL, { 0x5075b517, 0x5fc42245 }, 0x18917f00745cb781ULL },
+ { 0x19aeb14045a61121ULL, { 0x1bf6edec, 0x707e2f4b }, 0x6626672aa2ba10aULL },
+ { 0x44ff90486c531e9fULL, { 0x66598a, 0x8a90dc }, 0x32f6f2b097001598ULL },
+ { 0x3f3e7121092c5bcbULL, { 0x1c754df7, 0x5951a1b9 }, 0x14267f50d4971583ULL },
+ { 0x60e2dafb7e50a67eULL, { 0x4d96c66e, 0x65bd878d }, 0x49e317155d75e883ULL },
+ { 0x656286667e0e6e29ULL, { 0x9d971a2, 0xacda23b }, 0x5c6ee3159e1deac3ULL },
+ { 0x1114e0974255d507ULL, { 0x1c693, 0x2d6ff }, 0xaae42e4be5f9f8dULL },
+ { 0x508c8baf3a70ff5aULL, { 0x3b26b779, 0x6ad78745 }, 0x2c983876178ed5b1ULL },
+ { 0x5b47bc666bf1f9cfULL, { 0x10a87ed6, 0x187d358a }, 0x3e1767153bea720aULL },
+ { 0x50954e3744460395ULL, { 0x7a42263, 0xcdaa048 }, 0x2fe739f0944a023cULL },
+ { 0x20020b406550dd8fULL, { 0x3318539, 0x42eead0 }, 0x186f326307c0d985ULL },
+ { 0x5bcb0b872439ffd5ULL, { 0x6f61fb2, 0x9af7344 }, 0x41fa1e3c47f0f80dULL },
+ { 0x7a670f365db87a53ULL, { 0x417e102, 0x3bb54c67 }, 0x8642a551d0f41b0ULL },
+ { 0x1ef0db1e7bab1cd0ULL, { 0x2b60cf38, 0x4188f78f }, 0x147ae0d63fc0575aULL }
+ };
+
+ for (const auto &T : Tests) {
+ EXPECT_EQ(T.Result, BP(T.Prob[0], T.Prob[1]).scale(T.Num));
+ }
+}
+
+TEST(BranchProbabilityTest, NormalizeProbabilities) {
+ const auto UnknownProb = BranchProbability::getUnknown();
+ {
+ SmallVector<BranchProbability, 2> Probs{{0, 1}, {0, 1}};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{0, 1}, {1, 1}};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(0u, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator(), Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{1, 100}, {1, 100}};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{1, 1}, {1, 1}};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 3> Probs{{1, 1}, {1, 1}, {1, 1}};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[1].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[2].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{0, 1}, UnknownProb};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(0U, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator(), Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{1, 1}, UnknownProb};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator(), Probs[0].getNumerator());
+ EXPECT_EQ(0U, Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 2> Probs{{1, 2}, UnknownProb};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 2, Probs[1].getNumerator());
+ }
+ {
+ SmallVector<BranchProbability, 4> Probs{
+ {1, 2}, {1, 2}, {1, 2}, UnknownProb};
+ BranchProbability::normalizeProbabilities(Probs.begin(), Probs.end());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[0].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[1].getNumerator());
+ EXPECT_EQ(BranchProbability::getDenominator() / 3 + 1,
+ Probs[2].getNumerator());
+ EXPECT_EQ(0U, Probs[3].getNumerator());
+ }
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/CMakeLists.txt b/gnu/llvm/unittests/Support/CMakeLists.txt
new file mode 100644
index 00000000000..3ab98d58d5f
--- /dev/null
+++ b/gnu/llvm/unittests/Support/CMakeLists.txt
@@ -0,0 +1,59 @@
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Support
+ )
+
+add_llvm_unittest(SupportTests
+ AlignOfTest.cpp
+ AllocatorTest.cpp
+ ArrayRecyclerTest.cpp
+ BlockFrequencyTest.cpp
+ BranchProbabilityTest.cpp
+ Casting.cpp
+ CommandLineTest.cpp
+ CompressionTest.cpp
+ ConvertUTFTest.cpp
+ DataExtractorTest.cpp
+ DwarfTest.cpp
+ EndianStreamTest.cpp
+ EndianTest.cpp
+ ErrorOrTest.cpp
+ FileOutputBufferTest.cpp
+ IteratorTest.cpp
+ LEB128Test.cpp
+ LineIteratorTest.cpp
+ LockFileManagerTest.cpp
+ MD5Test.cpp
+ ManagedStatic.cpp
+ MathExtrasTest.cpp
+ MemoryBufferTest.cpp
+ MemoryTest.cpp
+ Path.cpp
+ ProcessTest.cpp
+ ProgramTest.cpp
+ RegexTest.cpp
+ ReplaceFileTest.cpp
+ ScaledNumberTest.cpp
+ SourceMgrTest.cpp
+ SpecialCaseListTest.cpp
+ StreamingMemoryObject.cpp
+ StringPool.cpp
+ SwapByteOrderTest.cpp
+ TargetRegistry.cpp
+ ThreadLocalTest.cpp
+ ThreadPool.cpp
+ TimerTest.cpp
+ TimeValueTest.cpp
+ TrailingObjectsTest.cpp
+ UnicodeTest.cpp
+ YAMLIOTest.cpp
+ YAMLParserTest.cpp
+ formatted_raw_ostream_test.cpp
+ raw_ostream_test.cpp
+ raw_pwrite_stream_test.cpp
+ )
+
+# ManagedStatic.cpp uses <pthread>.
+if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD)
+ target_link_libraries(SupportTests pthread)
+endif()
diff --git a/gnu/llvm/unittests/Support/Casting.cpp b/gnu/llvm/unittests/Support/Casting.cpp
new file mode 100644
index 00000000000..e6c35fc21eb
--- /dev/null
+++ b/gnu/llvm/unittests/Support/Casting.cpp
@@ -0,0 +1,330 @@
+//===---------- llvm/unittest/Support/Casting.cpp - Casting tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Casting.h"
+#include "llvm/IR/User.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+namespace llvm {
+// Used to test illegal cast. If a cast doesn't match any of the "real" ones,
+// it will match this one.
+struct IllegalCast;
+template <typename T> IllegalCast *cast(...) { return nullptr; }
+
+// set up two example classes
+// with conversion facility
+//
+struct bar {
+ bar() {}
+ struct foo *baz();
+ struct foo *caz();
+ struct foo *daz();
+ struct foo *naz();
+private:
+ bar(const bar &);
+};
+struct foo {
+ void ext() const;
+ /* static bool classof(const bar *X) {
+ cerr << "Classof: " << X << "\n";
+ return true;
+ }*/
+};
+
+template <> struct isa_impl<foo, bar> {
+ static inline bool doit(const bar &Val) {
+ dbgs() << "Classof: " << &Val << "\n";
+ return true;
+ }
+};
+
+foo *bar::baz() {
+ return cast<foo>(this);
+}
+
+foo *bar::caz() {
+ return cast_or_null<foo>(this);
+}
+
+foo *bar::daz() {
+ return dyn_cast<foo>(this);
+}
+
+foo *bar::naz() {
+ return dyn_cast_or_null<foo>(this);
+}
+
+
+bar *fub();
+
+template <> struct simplify_type<foo> {
+ typedef int SimpleType;
+ static SimpleType getSimplifiedValue(foo &Val) { return 0; }
+};
+
+} // End llvm namespace
+
+using namespace llvm;
+
+
+// Test the peculiar behavior of Use in simplify_type.
+static_assert(std::is_same<simplify_type<Use>::SimpleType, Value *>::value,
+ "Use doesn't simplify correctly!");
+static_assert(std::is_same<simplify_type<Use *>::SimpleType, Value *>::value,
+ "Use doesn't simplify correctly!");
+
+// Test that a regular class behaves as expected.
+static_assert(std::is_same<simplify_type<foo>::SimpleType, int>::value,
+ "Unexpected simplify_type result!");
+static_assert(std::is_same<simplify_type<foo *>::SimpleType, foo *>::value,
+ "Unexpected simplify_type result!");
+
+namespace {
+
+const foo *null_foo = nullptr;
+
+bar B;
+extern bar &B1;
+bar &B1 = B;
+extern const bar *B2;
+// test various configurations of const
+const bar &B3 = B1;
+const bar *const B4 = B2;
+
+TEST(CastingTest, isa) {
+ EXPECT_TRUE(isa<foo>(B1));
+ EXPECT_TRUE(isa<foo>(B2));
+ EXPECT_TRUE(isa<foo>(B3));
+ EXPECT_TRUE(isa<foo>(B4));
+}
+
+TEST(CastingTest, cast) {
+ foo &F1 = cast<foo>(B1);
+ EXPECT_NE(&F1, null_foo);
+ const foo *F3 = cast<foo>(B2);
+ EXPECT_NE(F3, null_foo);
+ const foo *F4 = cast<foo>(B2);
+ EXPECT_NE(F4, null_foo);
+ const foo &F5 = cast<foo>(B3);
+ EXPECT_NE(&F5, null_foo);
+ const foo *F6 = cast<foo>(B4);
+ EXPECT_NE(F6, null_foo);
+ // Can't pass null pointer to cast<>.
+ // foo *F7 = cast<foo>(fub());
+ // EXPECT_EQ(F7, null_foo);
+ foo *F8 = B1.baz();
+ EXPECT_NE(F8, null_foo);
+}
+
+TEST(CastingTest, cast_or_null) {
+ const foo *F11 = cast_or_null<foo>(B2);
+ EXPECT_NE(F11, null_foo);
+ const foo *F12 = cast_or_null<foo>(B2);
+ EXPECT_NE(F12, null_foo);
+ const foo *F13 = cast_or_null<foo>(B4);
+ EXPECT_NE(F13, null_foo);
+ const foo *F14 = cast_or_null<foo>(fub()); // Shouldn't print.
+ EXPECT_EQ(F14, null_foo);
+ foo *F15 = B1.caz();
+ EXPECT_NE(F15, null_foo);
+}
+
+TEST(CastingTest, dyn_cast) {
+ const foo *F1 = dyn_cast<foo>(B2);
+ EXPECT_NE(F1, null_foo);
+ const foo *F2 = dyn_cast<foo>(B2);
+ EXPECT_NE(F2, null_foo);
+ const foo *F3 = dyn_cast<foo>(B4);
+ EXPECT_NE(F3, null_foo);
+ // Can't pass null pointer to dyn_cast<>.
+ // foo *F4 = dyn_cast<foo>(fub());
+ // EXPECT_EQ(F4, null_foo);
+ foo *F5 = B1.daz();
+ EXPECT_NE(F5, null_foo);
+}
+
+TEST(CastingTest, dyn_cast_or_null) {
+ const foo *F1 = dyn_cast_or_null<foo>(B2);
+ EXPECT_NE(F1, null_foo);
+ const foo *F2 = dyn_cast_or_null<foo>(B2);
+ EXPECT_NE(F2, null_foo);
+ const foo *F3 = dyn_cast_or_null<foo>(B4);
+ EXPECT_NE(F3, null_foo);
+ foo *F4 = dyn_cast_or_null<foo>(fub());
+ EXPECT_EQ(F4, null_foo);
+ foo *F5 = B1.naz();
+ EXPECT_NE(F5, null_foo);
+}
+
+// These lines are errors...
+//foo *F20 = cast<foo>(B2); // Yields const foo*
+//foo &F21 = cast<foo>(B3); // Yields const foo&
+//foo *F22 = cast<foo>(B4); // Yields const foo*
+//foo &F23 = cast_or_null<foo>(B1);
+//const foo &F24 = cast_or_null<foo>(B3);
+
+const bar *B2 = &B;
+} // anonymous namespace
+
+bar *llvm::fub() { return nullptr; }
+
+namespace {
+namespace inferred_upcasting {
+// This test case verifies correct behavior of inferred upcasts when the
+// types are statically known to be OK to upcast. This is the case when,
+// for example, Derived inherits from Base, and we do `isa<Base>(Derived)`.
+
+// Note: This test will actually fail to compile without inferred
+// upcasting.
+
+class Base {
+public:
+ // No classof. We are testing that the upcast is inferred.
+ Base() {}
+};
+
+class Derived : public Base {
+public:
+ Derived() {}
+};
+
+// Even with no explicit classof() in Base, we should still be able to cast
+// Derived to its base class.
+TEST(CastingTest, UpcastIsInferred) {
+ Derived D;
+ EXPECT_TRUE(isa<Base>(D));
+ Base *BP = dyn_cast<Base>(&D);
+ EXPECT_TRUE(BP != nullptr);
+}
+
+
+// This test verifies that the inferred upcast takes precedence over an
+// explicitly written one. This is important because it verifies that the
+// dynamic check gets optimized away.
+class UseInferredUpcast {
+public:
+ int Dummy;
+ static bool classof(const UseInferredUpcast *) {
+ return false;
+ }
+};
+
+TEST(CastingTest, InferredUpcastTakesPrecedence) {
+ UseInferredUpcast UIU;
+ // Since the explicit classof() returns false, this will fail if the
+ // explicit one is used.
+ EXPECT_TRUE(isa<UseInferredUpcast>(&UIU));
+}
+
+} // end namespace inferred_upcasting
+} // end anonymous namespace
+// Test that we reject casts of temporaries (and so the illegal cast gets used).
+namespace TemporaryCast {
+struct pod {};
+IllegalCast *testIllegalCast() { return cast<foo>(pod()); }
+}
+
+namespace {
+namespace pointer_wrappers {
+
+struct Base {
+ bool IsDerived;
+ Base(bool IsDerived = false) : IsDerived(IsDerived) {}
+};
+
+struct Derived : Base {
+ Derived() : Base(true) {}
+ static bool classof(const Base *B) { return B->IsDerived; }
+};
+
+class PTy {
+ Base *B;
+public:
+ PTy(Base *B) : B(B) {}
+ explicit operator bool() const { return get(); }
+ Base *get() const { return B; }
+};
+
+} // end namespace pointer_wrappers
+} // end namespace
+
+namespace llvm {
+
+template <> struct simplify_type<pointer_wrappers::PTy> {
+ typedef pointer_wrappers::Base *SimpleType;
+ static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) {
+ return P.get();
+ }
+};
+template <> struct simplify_type<const pointer_wrappers::PTy> {
+ typedef pointer_wrappers::Base *SimpleType;
+ static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) {
+ return P.get();
+ }
+};
+
+} // end namespace llvm
+
+namespace {
+namespace pointer_wrappers {
+
+// Some objects.
+pointer_wrappers::Base B;
+pointer_wrappers::Derived D;
+
+// Mutable "smart" pointers.
+pointer_wrappers::PTy MN(nullptr);
+pointer_wrappers::PTy MB(&B);
+pointer_wrappers::PTy MD(&D);
+
+// Const "smart" pointers.
+const pointer_wrappers::PTy CN(nullptr);
+const pointer_wrappers::PTy CB(&B);
+const pointer_wrappers::PTy CD(&D);
+
+TEST(CastingTest, smart_isa) {
+ EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB));
+ EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB));
+ EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD));
+ EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD));
+}
+
+TEST(CastingTest, smart_cast) {
+ EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D);
+ EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D);
+}
+
+TEST(CastingTest, smart_cast_or_null) {
+ EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);
+ EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);
+ EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D);
+ EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D);
+}
+
+TEST(CastingTest, smart_dyn_cast) {
+ EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr);
+ EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr);
+ EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D);
+ EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D);
+}
+
+TEST(CastingTest, smart_dyn_cast_or_null) {
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr);
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr);
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D);
+ EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D);
+}
+
+} // end namespace pointer_wrappers
+} // end namespace
diff --git a/gnu/llvm/unittests/Support/CommandLineTest.cpp b/gnu/llvm/unittests/Support/CommandLineTest.cpp
new file mode 100644
index 00000000000..eac669f467b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/CommandLineTest.cpp
@@ -0,0 +1,268 @@
+//===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine 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 "llvm/Config/config.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/StringSaver.h"
+#include "gtest/gtest.h"
+#include <stdlib.h>
+#include <string>
+
+using namespace llvm;
+
+namespace {
+
+class TempEnvVar {
+ public:
+ TempEnvVar(const char *name, const char *value)
+ : name(name) {
+ const char *old_value = getenv(name);
+ EXPECT_EQ(nullptr, old_value) << old_value;
+#if HAVE_SETENV
+ setenv(name, value, true);
+#else
+# define SKIP_ENVIRONMENT_TESTS
+#endif
+ }
+
+ ~TempEnvVar() {
+#if HAVE_SETENV
+ // Assume setenv and unsetenv come together.
+ unsetenv(name);
+#else
+ (void)name; // Suppress -Wunused-private-field.
+#endif
+ }
+
+ private:
+ const char *const name;
+};
+
+template <typename T>
+class StackOption : public cl::opt<T> {
+ typedef cl::opt<T> Base;
+public:
+ // One option...
+ template<class M0t>
+ explicit StackOption(const M0t &M0) : Base(M0) {}
+
+ // Two options...
+ template<class M0t, class M1t>
+ StackOption(const M0t &M0, const M1t &M1) : Base(M0, M1) {}
+
+ // Three options...
+ template<class M0t, class M1t, class M2t>
+ StackOption(const M0t &M0, const M1t &M1, const M2t &M2) : Base(M0, M1, M2) {}
+
+ // Four options...
+ template<class M0t, class M1t, class M2t, class M3t>
+ StackOption(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3)
+ : Base(M0, M1, M2, M3) {}
+
+ ~StackOption() override { this->removeArgument(); }
+};
+
+
+cl::OptionCategory TestCategory("Test Options", "Description");
+TEST(CommandLineTest, ModifyExisitingOption) {
+ StackOption<int> TestOption("test-option", cl::desc("old description"));
+
+ const char Description[] = "New description";
+ const char ArgString[] = "new-test-option";
+ const char ValueString[] = "Integer";
+
+ StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+
+ ASSERT_TRUE(Map.count("test-option") == 1) <<
+ "Could not find option in map.";
+
+ cl::Option *Retrieved = Map["test-option"];
+ ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
+
+ ASSERT_EQ(&cl::GeneralCategory,Retrieved->Category) <<
+ "Incorrect default option category.";
+
+ Retrieved->setCategory(TestCategory);
+ ASSERT_EQ(&TestCategory,Retrieved->Category) <<
+ "Failed to modify option's option category.";
+
+ Retrieved->setDescription(Description);
+ ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
+ << "Changing option description failed.";
+
+ Retrieved->setArgStr(ArgString);
+ ASSERT_STREQ(ArgString, Retrieved->ArgStr.data())
+ << "Failed to modify option's Argument string.";
+
+ Retrieved->setValueStr(ValueString);
+ ASSERT_STREQ(Retrieved->ValueStr.data(), ValueString)
+ << "Failed to modify option's Value string.";
+
+ Retrieved->setHiddenFlag(cl::Hidden);
+ ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
+ "Failed to modify option's hidden flag.";
+}
+#ifndef SKIP_ENVIRONMENT_TESTS
+
+const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS";
+
+cl::opt<std::string> EnvironmentTestOption("env-test-opt");
+TEST(CommandLineTest, ParseEnvironment) {
+ TempEnvVar TEV(test_env_var, "-env-test-opt=hello");
+ EXPECT_EQ("", EnvironmentTestOption);
+ cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
+ EXPECT_EQ("hello", EnvironmentTestOption);
+}
+
+// This test used to make valgrind complain
+// ("Conditional jump or move depends on uninitialised value(s)")
+//
+// Warning: Do not run any tests after this one that try to gain access to
+// registered command line options because this will likely result in a
+// SEGFAULT. This can occur because the cl::opt in the test below is declared
+// on the stack which will be destroyed after the test completes but the
+// command line system will still hold a pointer to a deallocated cl::Option.
+TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
+ // Put cl::opt on stack to check for proper initialization of fields.
+ StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
+ TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
+ EXPECT_EQ("", EnvironmentTestOptionLocal);
+ cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
+ EXPECT_EQ("hello-local", EnvironmentTestOptionLocal);
+}
+
+#endif // SKIP_ENVIRONMENT_TESTS
+
+TEST(CommandLineTest, UseOptionCategory) {
+ StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
+
+ ASSERT_EQ(&TestCategory,TestOption2.Category) << "Failed to assign Option "
+ "Category.";
+}
+
+typedef void ParserFunction(StringRef Source, StringSaver &Saver,
+ SmallVectorImpl<const char *> &NewArgv,
+ bool MarkEOLs);
+
+void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
+ const char *const Output[], size_t OutputSize) {
+ SmallVector<const char *, 0> Actual;
+ BumpPtrAllocator A;
+ StringSaver Saver(A);
+ parse(Input, Saver, Actual, /*MarkEOLs=*/false);
+ EXPECT_EQ(OutputSize, Actual.size());
+ for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
+ if (I < OutputSize)
+ EXPECT_STREQ(Output[I], Actual[I]);
+ }
+}
+
+TEST(CommandLineTest, TokenizeGNUCommandLine) {
+ const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' "
+ "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\"";
+ const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar",
+ "foobarbaz", "C:\\src\\foo.cpp",
+ "C:\\src\\foo.cpp" };
+ testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
+ array_lengthof(Output));
+}
+
+TEST(CommandLineTest, TokenizeWindowsCommandLine) {
+ const char *Input = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
+ "\"st \\\"u\" \\v";
+ const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
+ "lmn", "o", "pqr", "st \"u", "\\v" };
+ testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
+ array_lengthof(Output));
+}
+
+TEST(CommandLineTest, AliasesWithArguments) {
+ static const size_t ARGC = 3;
+ const char *const Inputs[][ARGC] = {
+ { "-tool", "-actual=x", "-extra" },
+ { "-tool", "-actual", "x" },
+ { "-tool", "-alias=x", "-extra" },
+ { "-tool", "-alias", "x" }
+ };
+
+ for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
+ StackOption<std::string> Actual("actual");
+ StackOption<bool> Extra("extra");
+ StackOption<std::string> Input(cl::Positional);
+
+ cl::alias Alias("alias", llvm::cl::aliasopt(Actual));
+
+ cl::ParseCommandLineOptions(ARGC, Inputs[i]);
+ EXPECT_EQ("x", Actual);
+ EXPECT_EQ(0, Input.getNumOccurrences());
+
+ Alias.removeArgument();
+ }
+}
+
+void testAliasRequired(int argc, const char *const *argv) {
+ StackOption<std::string> Option("option", cl::Required);
+ cl::alias Alias("o", llvm::cl::aliasopt(Option));
+
+ cl::ParseCommandLineOptions(argc, argv);
+ EXPECT_EQ("x", Option);
+ EXPECT_EQ(1, Option.getNumOccurrences());
+
+ Alias.removeArgument();
+}
+
+TEST(CommandLineTest, AliasRequired) {
+ const char *opts1[] = { "-tool", "-option=x" };
+ const char *opts2[] = { "-tool", "-o", "x" };
+ testAliasRequired(array_lengthof(opts1), opts1);
+ testAliasRequired(array_lengthof(opts2), opts2);
+}
+
+TEST(CommandLineTest, HideUnrelatedOptions) {
+ StackOption<int> TestOption1("hide-option-1");
+ StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));
+
+ cl::HideUnrelatedOptions(TestCategory);
+
+ ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
+ << "Failed to hide extra option.";
+ ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
+ << "Hid extra option that should be visable.";
+
+ StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
+ << "Hid default option that should be visable.";
+}
+
+cl::OptionCategory TestCategory2("Test Options set 2", "Description");
+
+TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
+ StackOption<int> TestOption1("multi-hide-option-1");
+ StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory));
+ StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2));
+
+ const cl::OptionCategory *VisibleCategories[] = {&TestCategory,
+ &TestCategory2};
+
+ cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories));
+
+ ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
+ << "Failed to hide extra option.";
+ ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
+ << "Hid extra option that should be visable.";
+ ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
+ << "Hid extra option that should be visable.";
+
+ StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
+ << "Hid default option that should be visable.";
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/CompressionTest.cpp b/gnu/llvm/unittests/Support/CompressionTest.cpp
new file mode 100644
index 00000000000..36b84d85f22
--- /dev/null
+++ b/gnu/llvm/unittests/Support/CompressionTest.cpp
@@ -0,0 +1,70 @@
+//===- llvm/unittest/Support/CompressionTest.cpp - Compression tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements unit tests for the Compression functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Compression.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+#if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ
+
+void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) {
+ SmallString<32> Compressed;
+ SmallString<32> Uncompressed;
+ EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level));
+ // Check that uncompressed buffer is the same as original.
+ EXPECT_EQ(zlib::StatusOK,
+ zlib::uncompress(Compressed, Uncompressed, Input.size()));
+ EXPECT_EQ(Input, Uncompressed);
+ if (Input.size() > 0) {
+ // Uncompression fails if expected length is too short.
+ EXPECT_EQ(zlib::StatusBufferTooShort,
+ zlib::uncompress(Compressed, Uncompressed, Input.size() - 1));
+ }
+}
+
+TEST(CompressionTest, Zlib) {
+ TestZlibCompression("", zlib::DefaultCompression);
+
+ TestZlibCompression("hello, world!", zlib::NoCompression);
+ TestZlibCompression("hello, world!", zlib::BestSizeCompression);
+ TestZlibCompression("hello, world!", zlib::BestSpeedCompression);
+ TestZlibCompression("hello, world!", zlib::DefaultCompression);
+
+ const size_t kSize = 1024;
+ char BinaryData[kSize];
+ for (size_t i = 0; i < kSize; ++i) {
+ BinaryData[i] = i & 255;
+ }
+ StringRef BinaryDataStr(BinaryData, kSize);
+
+ TestZlibCompression(BinaryDataStr, zlib::NoCompression);
+ TestZlibCompression(BinaryDataStr, zlib::BestSizeCompression);
+ TestZlibCompression(BinaryDataStr, zlib::BestSpeedCompression);
+ TestZlibCompression(BinaryDataStr, zlib::DefaultCompression);
+}
+
+TEST(CompressionTest, ZlibCRC32) {
+ EXPECT_EQ(
+ 0x414FA339U,
+ zlib::crc32(StringRef("The quick brown fox jumps over the lazy dog")));
+}
+
+#endif
+
+}
diff --git a/gnu/llvm/unittests/Support/ConvertUTFTest.cpp b/gnu/llvm/unittests/Support/ConvertUTFTest.cpp
new file mode 100644
index 00000000000..d436fc02289
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ConvertUTFTest.cpp
@@ -0,0 +1,1678 @@
+//===- llvm/unittest/Support/ConvertUTFTest.cpp - ConvertUTF tests --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Format.h"
+#include "gtest/gtest.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+TEST(ConvertUTFTest, ConvertUTF16LittleEndianToUTF8String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c";
+ ArrayRef<char> Ref(Src, sizeof(Src) - 1);
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(Ref, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, ConvertUTF16BigEndianToUTF8String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xfe\xff\x0c\xa0\x00_\x0c\xa0";
+ ArrayRef<char> Ref(Src, sizeof(Src) - 1);
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(Ref, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, ConvertUTF8ToUTF16String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0";
+ StringRef Ref(Src, sizeof(Src) - 1);
+ SmallVector<UTF16, 5> Result;
+ bool Success = convertUTF8ToUTF16String(Ref, Result);
+ EXPECT_TRUE(Success);
+ static const UTF16 Expected[] = {0x0CA0, 0x005f, 0x0CA0, 0};
+ ASSERT_EQ(3u, Result.size());
+ for (int I = 0, E = 3; I != E; ++I)
+ EXPECT_EQ(Expected[I], Result[I]);
+}
+
+TEST(ConvertUTFTest, OddLengthInput) {
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(makeArrayRef("xxxxx", 5), Result);
+ EXPECT_FALSE(Success);
+}
+
+TEST(ConvertUTFTest, Empty) {
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(None, Result);
+ EXPECT_TRUE(Success);
+ EXPECT_TRUE(Result.empty());
+}
+
+TEST(ConvertUTFTest, HasUTF16BOM) {
+ bool HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xff\xfe", 2));
+ EXPECT_TRUE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff", 2));
+ EXPECT_TRUE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff ", 3));
+ EXPECT_TRUE(HasBOM); // Don't care about odd lengths.
+ HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe\xff\x00asdf", 6));
+ EXPECT_TRUE(HasBOM);
+
+ HasBOM = hasUTF16ByteOrderMark(None);
+ EXPECT_FALSE(HasBOM);
+ HasBOM = hasUTF16ByteOrderMark(makeArrayRef("\xfe", 1));
+ EXPECT_FALSE(HasBOM);
+}
+
+struct ConvertUTFResultContainer {
+ ConversionResult ErrorCode;
+ std::vector<unsigned> UnicodeScalars;
+
+ ConvertUTFResultContainer(ConversionResult ErrorCode)
+ : ErrorCode(ErrorCode) {}
+
+ ConvertUTFResultContainer
+ withScalars(unsigned US0 = 0x110000, unsigned US1 = 0x110000,
+ unsigned US2 = 0x110000, unsigned US3 = 0x110000,
+ unsigned US4 = 0x110000, unsigned US5 = 0x110000,
+ unsigned US6 = 0x110000, unsigned US7 = 0x110000) {
+ ConvertUTFResultContainer Result(*this);
+ if (US0 != 0x110000)
+ Result.UnicodeScalars.push_back(US0);
+ if (US1 != 0x110000)
+ Result.UnicodeScalars.push_back(US1);
+ if (US2 != 0x110000)
+ Result.UnicodeScalars.push_back(US2);
+ if (US3 != 0x110000)
+ Result.UnicodeScalars.push_back(US3);
+ if (US4 != 0x110000)
+ Result.UnicodeScalars.push_back(US4);
+ if (US5 != 0x110000)
+ Result.UnicodeScalars.push_back(US5);
+ if (US6 != 0x110000)
+ Result.UnicodeScalars.push_back(US6);
+ if (US7 != 0x110000)
+ Result.UnicodeScalars.push_back(US7);
+ return Result;
+ }
+};
+
+std::pair<ConversionResult, std::vector<unsigned>>
+ConvertUTF8ToUnicodeScalarsLenient(StringRef S) {
+ const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(S.data());
+
+ const UTF8 *SourceNext = SourceStart;
+ std::vector<UTF32> Decoded(S.size(), 0);
+ UTF32 *TargetStart = Decoded.data();
+
+ auto ErrorCode =
+ ConvertUTF8toUTF32(&SourceNext, SourceStart + S.size(), &TargetStart,
+ Decoded.data() + Decoded.size(), lenientConversion);
+
+ Decoded.resize(TargetStart - Decoded.data());
+
+ return std::make_pair(ErrorCode, Decoded);
+}
+
+std::pair<ConversionResult, std::vector<unsigned>>
+ConvertUTF8ToUnicodeScalarsPartialLenient(StringRef S) {
+ const UTF8 *SourceStart = reinterpret_cast<const UTF8 *>(S.data());
+
+ const UTF8 *SourceNext = SourceStart;
+ std::vector<UTF32> Decoded(S.size(), 0);
+ UTF32 *TargetStart = Decoded.data();
+
+ auto ErrorCode = ConvertUTF8toUTF32Partial(
+ &SourceNext, SourceStart + S.size(), &TargetStart,
+ Decoded.data() + Decoded.size(), lenientConversion);
+
+ Decoded.resize(TargetStart - Decoded.data());
+
+ return std::make_pair(ErrorCode, Decoded);
+}
+
+::testing::AssertionResult
+CheckConvertUTF8ToUnicodeScalars(ConvertUTFResultContainer Expected,
+ StringRef S, bool Partial = false) {
+ ConversionResult ErrorCode;
+ std::vector<unsigned> Decoded;
+ if (!Partial)
+ std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsLenient(S);
+ else
+ std::tie(ErrorCode, Decoded) = ConvertUTF8ToUnicodeScalarsPartialLenient(S);
+
+ if (Expected.ErrorCode != ErrorCode)
+ return ::testing::AssertionFailure() << "Expected error code "
+ << Expected.ErrorCode << ", actual "
+ << ErrorCode;
+
+ if (Expected.UnicodeScalars != Decoded)
+ return ::testing::AssertionFailure()
+ << "Expected lenient decoded result:\n"
+ << ::testing::PrintToString(Expected.UnicodeScalars) << "\n"
+ << "Actual result:\n" << ::testing::PrintToString(Decoded);
+
+ return ::testing::AssertionSuccess();
+}
+
+TEST(ConvertUTFTest, UTF8ToUTF32Lenient) {
+
+ //
+ // 1-byte sequences
+ //
+
+ // U+0041 LATIN CAPITAL LETTER A
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0041), "\x41"));
+
+ //
+ // 2-byte sequences
+ //
+
+ // U+0283 LATIN SMALL LETTER ESH
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0283),
+ "\xca\x83"));
+
+ // U+03BA GREEK SMALL LETTER KAPPA
+ // U+1F79 GREEK SMALL LETTER OMICRON WITH OXIA
+ // U+03C3 GREEK SMALL LETTER SIGMA
+ // U+03BC GREEK SMALL LETTER MU
+ // U+03B5 GREEK SMALL LETTER EPSILON
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK)
+ .withScalars(0x03ba, 0x1f79, 0x03c3, 0x03bc, 0x03b5),
+ "\xce\xba\xe1\xbd\xb9\xcf\x83\xce\xbc\xce\xb5"));
+
+ //
+ // 3-byte sequences
+ //
+
+ // U+4F8B CJK UNIFIED IDEOGRAPH-4F8B
+ // U+6587 CJK UNIFIED IDEOGRAPH-6587
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x4f8b, 0x6587),
+ "\xe4\xbe\x8b\xe6\x96\x87"));
+
+ // U+D55C HANGUL SYLLABLE HAN
+ // U+AE00 HANGUL SYLLABLE GEUL
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xd55c, 0xae00),
+ "\xed\x95\x9c\xea\xb8\x80"));
+
+ // U+1112 HANGUL CHOSEONG HIEUH
+ // U+1161 HANGUL JUNGSEONG A
+ // U+11AB HANGUL JONGSEONG NIEUN
+ // U+1100 HANGUL CHOSEONG KIYEOK
+ // U+1173 HANGUL JUNGSEONG EU
+ // U+11AF HANGUL JONGSEONG RIEUL
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK)
+ .withScalars(0x1112, 0x1161, 0x11ab, 0x1100, 0x1173, 0x11af),
+ "\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab\xe1\x84\x80\xe1\x85\xb3"
+ "\xe1\x86\xaf"));
+
+ //
+ // 4-byte sequences
+ //
+
+ // U+E0100 VARIATION SELECTOR-17
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x000E0100),
+ "\xf3\xa0\x84\x80"));
+
+ //
+ // First possible sequence of a certain length
+ //
+
+ // U+0000 NULL
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0000),
+ StringRef("\x00", 1)));
+
+ // U+0080 PADDING CHARACTER
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0080),
+ "\xc2\x80"));
+
+ // U+0800 SAMARITAN LETTER ALAF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0800),
+ "\xe0\xa0\x80"));
+
+ // U+10000 LINEAR B SYLLABLE B008 A
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x10000),
+ "\xf0\x90\x80\x80"));
+
+ // U+200000 (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x88\x80\x80\x80"));
+
+ // U+4000000 (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x84\x80\x80\x80\x80"));
+
+ //
+ // Last possible sequence of a certain length
+ //
+
+ // U+007F DELETE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x007f), "\x7f"));
+
+ // U+07FF (unassigned)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x07ff),
+ "\xdf\xbf"));
+
+ // U+FFFF (noncharacter)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xffff),
+ "\xef\xbf\xbf"));
+
+ // U+1FFFFF (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf7\xbf\xbf\xbf"));
+
+ // U+3FFFFFF (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfb\xbf\xbf\xbf\xbf"));
+
+ // U+7FFFFFFF (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfd\xbf\xbf\xbf\xbf\xbf"));
+
+ //
+ // Other boundary conditions
+ //
+
+ // U+D7FF (unassigned)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xd7ff),
+ "\xed\x9f\xbf"));
+
+ // U+E000 (private use)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xe000),
+ "\xee\x80\x80"));
+
+ // U+FFFD REPLACEMENT CHARACTER
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfffd),
+ "\xef\xbf\xbd"));
+
+ // U+10FFFF (noncharacter)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x10ffff),
+ "\xf4\x8f\xbf\xbf"));
+
+ // U+110000 (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf4\x90\x80\x80"));
+
+ //
+ // Unexpected continuation bytes
+ //
+
+ // A sequence of unexpected continuation bytes that don't follow a first
+ // byte, every byte is a maximal subpart.
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\x80\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xbf\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\x80\xbf\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\x80\xbf\x80\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\x80\xbf\x82\xbf\xaa"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xaa\xb0\xbb\xbf\xaa\xa0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xaa\xb0\xbb\xbf\xaa\xa0\x8f"));
+
+ // All continuation bytes (0x80--0xbf).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"
+ "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"));
+
+ //
+ // Lonely start bytes
+ //
+
+ // Start bytes of 2-byte sequences (0xc0--0xdf).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xc0\x20\xc1\x20\xc2\x20\xc3\x20\xc4\x20\xc5\x20\xc6\x20\xc7\x20"
+ "\xc8\x20\xc9\x20\xca\x20\xcb\x20\xcc\x20\xcd\x20\xce\x20\xcf\x20"
+ "\xd0\x20\xd1\x20\xd2\x20\xd3\x20\xd4\x20\xd5\x20\xd6\x20\xd7\x20"
+ "\xd8\x20\xd9\x20\xda\x20\xdb\x20\xdc\x20\xdd\x20\xde\x20\xdf\x20"));
+
+ // Start bytes of 3-byte sequences (0xe0--0xef).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xe0\x20\xe1\x20\xe2\x20\xe3\x20\xe4\x20\xe5\x20\xe6\x20\xe7\x20"
+ "\xe8\x20\xe9\x20\xea\x20\xeb\x20\xec\x20\xed\x20\xee\x20\xef\x20"));
+
+ // Start bytes of 4-byte sequences (0xf0--0xf7).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd,
+ 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xf0\x20\xf1\x20\xf2\x20\xf3\x20\xf4\x20\xf5\x20\xf6\x20\xf7\x20"));
+
+ // Start bytes of 5-byte sequences (0xf8--0xfb).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\xf9\xfa\xfb"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xf8\x20\xf9\x20\xfa\x20\xfb\x20"));
+
+ // Start bytes of 6-byte sequences (0xfc--0xfd).
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfc\xfd"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xfc\x20\xfd\x20"));
+
+ //
+ // Other bytes (0xc0--0xc1, 0xfe--0xff).
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc1"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfe"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xff"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xc0\xc1\xfe\xff"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfe\xfe\xff\xff"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfe\x80\x80\x80\x80\x80"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xff\x80\x80\x80\x80\x80"));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0x0020, 0xfffd, 0x0020,
+ 0xfffd, 0x0020, 0xfffd, 0x0020),
+ "\xc0\x20\xc1\x20\xfe\x20\xff\x20"));
+
+ //
+ // Sequences with one continuation byte missing
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xc2"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xdf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xe0\xa0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xe0\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xe1\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xec\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xed\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xed\x9f"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xee\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xef\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf0\x90\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf0\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf1\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf3\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf4\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf4\x8f\xbf"));
+
+ // Overlong sequences with one trailing byte missing.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xc0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xc1"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xe0\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xe0\x9f"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x8f\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x80\x80\x80\x80"));
+
+ // Sequences that represent surrogates with one trailing byte missing.
+ // High surrogates
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xa0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xac"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xaf"));
+ // Low surrogates
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xb0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xb4"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xed\xbf"));
+
+ // Ill-formed 4-byte sequences.
+ // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+1100xx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf4\x90\x80"));
+ // U+13FBxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf4\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf5\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf6\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf7\x80\x80"));
+ // U+1FFBxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf7\xbf\xbf"));
+
+ // Ill-formed 5-byte sequences.
+ // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+2000xx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x88\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\xbf\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf9\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfa\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfb\x80\x80\x80"));
+ // U+3FFFFxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfb\xbf\xbf\xbf"));
+
+ // Ill-formed 6-byte sequences.
+ // 1111110u 10uuuuuu 10uzzzzz 10zzzyyyy 10yyyyxx 10xxxxxx
+ // U+40000xx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x84\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\xbf\xbf\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfd\x80\x80\x80\x80"));
+ // U+7FFFFFxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfd\xbf\xbf\xbf\xbf"));
+
+ //
+ // Sequences with two continuation bytes missing
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf0\x90"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf0\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf1\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf3\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf4\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd),
+ "\xf4\x8f"));
+
+ // Overlong sequences with two trailing byte missing.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xe0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf0\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf0\x8f"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x80\x80\x80"));
+
+ // Sequences that represent surrogates with two trailing bytes missing.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xed"));
+
+ // Ill-formed 4-byte sequences.
+ // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+110yxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf4\x90"));
+ // U+13Fyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf4\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf5\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf6\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf7\x80"));
+ // U+1FFyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf7\xbf"));
+
+ // Ill-formed 5-byte sequences.
+ // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+200yxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x88\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf8\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xf9\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfa\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfb\x80\x80"));
+ // U+3FFFyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfb\xbf\xbf"));
+
+ // Ill-formed 6-byte sequences.
+ // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+4000yxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x84\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\xbf\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfd\x80\x80\x80"));
+ // U+7FFFFyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfd\xbf\xbf\xbf"));
+
+ //
+ // Sequences with three continuation bytes missing
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf1"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf2"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf3"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf4"));
+
+ // Broken overlong sequences.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf0"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf8\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x80\x80"));
+
+ // Ill-formed 4-byte sequences.
+ // 11110zzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+14yyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf5"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf6"));
+ // U+1Cyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf7"));
+
+ // Ill-formed 5-byte sequences.
+ // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+20yyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf8\x88"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf8\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xf9\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfa\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfb\x80"));
+ // U+3FCyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfb\xbf"));
+
+ // Ill-formed 6-byte sequences.
+ // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+400yyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x84\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfc\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfd\x80\x80"));
+ // U+7FFCyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xfd\xbf\xbf"));
+
+ //
+ // Sequences with four continuation bytes missing
+ //
+
+ // Ill-formed 5-byte sequences.
+ // 111110uu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+uzyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf8"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf9"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfa"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfb"));
+ // U+3zyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfb"));
+
+ // Broken overlong sequences.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xf8"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfc\x80"));
+
+ // Ill-formed 6-byte sequences.
+ // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+uzzyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfc\x84"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfc\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfd\x80"));
+ // U+7Fzzyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xfd\xbf"));
+
+ //
+ // Sequences with five continuation bytes missing
+ //
+
+ // Ill-formed 6-byte sequences.
+ // 1111110u 10uuuuuu 10zzzzzz 10zzyyyy 10yyyyxx 10xxxxxx
+ // U+uzzyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfc"));
+ // U+uuzzyyxx (invalid)
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd), "\xfd"));
+
+ //
+ // Consecutive sequences with trailing bytes missing
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, /**/ 0xfffd, 0xfffd, /**/ 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, /**/ 0xfffd, /**/ 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xc0" "\xe0\x80" "\xf0\x80\x80"
+ "\xf8\x80\x80\x80"
+ "\xfc\x80\x80\x80\x80"
+ "\xdf" "\xef\xbf" "\xf7\xbf\xbf"
+ "\xfb\xbf\xbf\xbf"
+ "\xfd\xbf\xbf\xbf\xbf"));
+
+ //
+ // Overlong UTF-8 sequences
+ //
+
+ // U+002F SOLIDUS
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x002f), "\x2f"));
+
+ // Overlong sequences of the above.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xc0\xaf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xe0\x80\xaf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x80\x80\xaf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x80\x80\x80\xaf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x80\x80\x80\x80\xaf"));
+
+ // U+0000 NULL
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0000),
+ StringRef("\x00", 1)));
+
+ // Overlong sequences of the above.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xc0\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xe0\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x80\x80\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x80\x80\x80\x80\x80"));
+
+ // Other overlong sequences.
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xc0\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xc1\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal).withScalars(0xfffd, 0xfffd),
+ "\xc1\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xe0\x9f\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xa0\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x8f\x80\x80"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf0\x8f\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xf8\x87\xbf\xbf\xbf"));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xfc\x83\xbf\xbf\xbf\xbf"));
+
+ //
+ // Isolated surrogates
+ //
+
+ // Unicode 6.3.0:
+ //
+ // D71. High-surrogate code point: A Unicode code point in the range
+ // U+D800 to U+DBFF.
+ //
+ // D73. Low-surrogate code point: A Unicode code point in the range
+ // U+DC00 to U+DFFF.
+
+ // Note: U+E0100 is <DB40 DD00> in UTF16.
+
+ // High surrogates
+
+ // U+D800
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xa0\x80"));
+
+ // U+DB40
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xac\xa0"));
+
+ // U+DBFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xaf\xbf"));
+
+ // Low surrogates
+
+ // U+DC00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xb0\x80"));
+
+ // U+DD00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xb4\x80"));
+
+ // U+DFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd),
+ "\xed\xbf\xbf"));
+
+ // Surrogate pairs
+
+ // U+D800 U+DC00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xa0\x80\xed\xb0\x80"));
+
+ // U+D800 U+DD00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xa0\x80\xed\xb4\x80"));
+
+ // U+D800 U+DFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xa0\x80\xed\xbf\xbf"));
+
+ // U+DB40 U+DC00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xac\xa0\xed\xb0\x80"));
+
+ // U+DB40 U+DD00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xac\xa0\xed\xb4\x80"));
+
+ // U+DB40 U+DFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xac\xa0\xed\xbf\xbf"));
+
+ // U+DBFF U+DC00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xaf\xbf\xed\xb0\x80"));
+
+ // U+DBFF U+DD00
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xaf\xbf\xed\xb4\x80"));
+
+ // U+DBFF U+DFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceIllegal)
+ .withScalars(0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd, 0xfffd),
+ "\xed\xaf\xbf\xed\xbf\xbf"));
+
+ //
+ // Noncharacters
+ //
+
+ // Unicode 6.3.0:
+ //
+ // D14. Noncharacter: A code point that is permanently reserved for
+ // internal use and that should never be interchanged. Noncharacters
+ // consist of the values U+nFFFE and U+nFFFF (where n is from 0 to 1016)
+ // and the values U+FDD0..U+FDEF.
+
+ // U+FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfffe),
+ "\xef\xbf\xbe"));
+
+ // U+FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xffff),
+ "\xef\xbf\xbf"));
+
+ // U+1FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x1fffe),
+ "\xf0\x9f\xbf\xbe"));
+
+ // U+1FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x1ffff),
+ "\xf0\x9f\xbf\xbf"));
+
+ // U+2FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x2fffe),
+ "\xf0\xaf\xbf\xbe"));
+
+ // U+2FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x2ffff),
+ "\xf0\xaf\xbf\xbf"));
+
+ // U+3FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x3fffe),
+ "\xf0\xbf\xbf\xbe"));
+
+ // U+3FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x3ffff),
+ "\xf0\xbf\xbf\xbf"));
+
+ // U+4FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x4fffe),
+ "\xf1\x8f\xbf\xbe"));
+
+ // U+4FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x4ffff),
+ "\xf1\x8f\xbf\xbf"));
+
+ // U+5FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x5fffe),
+ "\xf1\x9f\xbf\xbe"));
+
+ // U+5FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x5ffff),
+ "\xf1\x9f\xbf\xbf"));
+
+ // U+6FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x6fffe),
+ "\xf1\xaf\xbf\xbe"));
+
+ // U+6FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x6ffff),
+ "\xf1\xaf\xbf\xbf"));
+
+ // U+7FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x7fffe),
+ "\xf1\xbf\xbf\xbe"));
+
+ // U+7FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x7ffff),
+ "\xf1\xbf\xbf\xbf"));
+
+ // U+8FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x8fffe),
+ "\xf2\x8f\xbf\xbe"));
+
+ // U+8FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x8ffff),
+ "\xf2\x8f\xbf\xbf"));
+
+ // U+9FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x9fffe),
+ "\xf2\x9f\xbf\xbe"));
+
+ // U+9FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x9ffff),
+ "\xf2\x9f\xbf\xbf"));
+
+ // U+AFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xafffe),
+ "\xf2\xaf\xbf\xbe"));
+
+ // U+AFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xaffff),
+ "\xf2\xaf\xbf\xbf"));
+
+ // U+BFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xbfffe),
+ "\xf2\xbf\xbf\xbe"));
+
+ // U+BFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xbffff),
+ "\xf2\xbf\xbf\xbf"));
+
+ // U+CFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xcfffe),
+ "\xf3\x8f\xbf\xbe"));
+
+ // U+CFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xcfffF),
+ "\xf3\x8f\xbf\xbf"));
+
+ // U+DFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xdfffe),
+ "\xf3\x9f\xbf\xbe"));
+
+ // U+DFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xdffff),
+ "\xf3\x9f\xbf\xbf"));
+
+ // U+EFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xefffe),
+ "\xf3\xaf\xbf\xbe"));
+
+ // U+EFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xeffff),
+ "\xf3\xaf\xbf\xbf"));
+
+ // U+FFFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xffffe),
+ "\xf3\xbf\xbf\xbe"));
+
+ // U+FFFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfffff),
+ "\xf3\xbf\xbf\xbf"));
+
+ // U+10FFFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x10fffe),
+ "\xf4\x8f\xbf\xbe"));
+
+ // U+10FFFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x10ffff),
+ "\xf4\x8f\xbf\xbf"));
+
+ // U+FDD0
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd0),
+ "\xef\xb7\x90"));
+
+ // U+FDD1
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd1),
+ "\xef\xb7\x91"));
+
+ // U+FDD2
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd2),
+ "\xef\xb7\x92"));
+
+ // U+FDD3
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd3),
+ "\xef\xb7\x93"));
+
+ // U+FDD4
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd4),
+ "\xef\xb7\x94"));
+
+ // U+FDD5
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd5),
+ "\xef\xb7\x95"));
+
+ // U+FDD6
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd6),
+ "\xef\xb7\x96"));
+
+ // U+FDD7
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd7),
+ "\xef\xb7\x97"));
+
+ // U+FDD8
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd8),
+ "\xef\xb7\x98"));
+
+ // U+FDD9
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdd9),
+ "\xef\xb7\x99"));
+
+ // U+FDDA
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdda),
+ "\xef\xb7\x9a"));
+
+ // U+FDDB
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfddb),
+ "\xef\xb7\x9b"));
+
+ // U+FDDC
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfddc),
+ "\xef\xb7\x9c"));
+
+ // U+FDDD
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfddd),
+ "\xef\xb7\x9d"));
+
+ // U+FDDE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdde),
+ "\xef\xb7\x9e"));
+
+ // U+FDDF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfddf),
+ "\xef\xb7\x9f"));
+
+ // U+FDE0
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde0),
+ "\xef\xb7\xa0"));
+
+ // U+FDE1
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde1),
+ "\xef\xb7\xa1"));
+
+ // U+FDE2
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde2),
+ "\xef\xb7\xa2"));
+
+ // U+FDE3
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde3),
+ "\xef\xb7\xa3"));
+
+ // U+FDE4
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde4),
+ "\xef\xb7\xa4"));
+
+ // U+FDE5
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde5),
+ "\xef\xb7\xa5"));
+
+ // U+FDE6
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde6),
+ "\xef\xb7\xa6"));
+
+ // U+FDE7
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde7),
+ "\xef\xb7\xa7"));
+
+ // U+FDE8
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde8),
+ "\xef\xb7\xa8"));
+
+ // U+FDE9
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfde9),
+ "\xef\xb7\xa9"));
+
+ // U+FDEA
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdea),
+ "\xef\xb7\xaa"));
+
+ // U+FDEB
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdeb),
+ "\xef\xb7\xab"));
+
+ // U+FDEC
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdec),
+ "\xef\xb7\xac"));
+
+ // U+FDED
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfded),
+ "\xef\xb7\xad"));
+
+ // U+FDEE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdee),
+ "\xef\xb7\xae"));
+
+ // U+FDEF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdef),
+ "\xef\xb7\xaf"));
+
+ // U+FDF0
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf0),
+ "\xef\xb7\xb0"));
+
+ // U+FDF1
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf1),
+ "\xef\xb7\xb1"));
+
+ // U+FDF2
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf2),
+ "\xef\xb7\xb2"));
+
+ // U+FDF3
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf3),
+ "\xef\xb7\xb3"));
+
+ // U+FDF4
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf4),
+ "\xef\xb7\xb4"));
+
+ // U+FDF5
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf5),
+ "\xef\xb7\xb5"));
+
+ // U+FDF6
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf6),
+ "\xef\xb7\xb6"));
+
+ // U+FDF7
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf7),
+ "\xef\xb7\xb7"));
+
+ // U+FDF8
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf8),
+ "\xef\xb7\xb8"));
+
+ // U+FDF9
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdf9),
+ "\xef\xb7\xb9"));
+
+ // U+FDFA
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdfa),
+ "\xef\xb7\xba"));
+
+ // U+FDFB
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdfb),
+ "\xef\xb7\xbb"));
+
+ // U+FDFC
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdfc),
+ "\xef\xb7\xbc"));
+
+ // U+FDFD
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdfd),
+ "\xef\xb7\xbd"));
+
+ // U+FDFE
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdfe),
+ "\xef\xb7\xbe"));
+
+ // U+FDFF
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0xfdff),
+ "\xef\xb7\xbf"));
+}
+
+TEST(ConvertUTFTest, UTF8ToUTF32PartialLenient) {
+ // U+0041 LATIN CAPITAL LETTER A
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(conversionOK).withScalars(0x0041),
+ "\x41", true));
+
+ //
+ // Sequences with one continuation byte missing
+ //
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xc2", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xdf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xe0\xa0", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xe0\xbf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xe1\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xec\xbf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xed\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xed\x9f", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xee\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xef\xbf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf0\x90\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf0\xbf\xbf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf1\x80\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf3\xbf\xbf", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf4\x80\x80", true));
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted),
+ "\xf4\x8f\xbf", true));
+
+ EXPECT_TRUE(CheckConvertUTF8ToUnicodeScalars(
+ ConvertUTFResultContainer(sourceExhausted).withScalars(0x0041),
+ "\x41\xc2", true));
+}
+
diff --git a/gnu/llvm/unittests/Support/DataExtractorTest.cpp b/gnu/llvm/unittests/Support/DataExtractorTest.cpp
new file mode 100644
index 00000000000..81de983d226
--- /dev/null
+++ b/gnu/llvm/unittests/Support/DataExtractorTest.cpp
@@ -0,0 +1,120 @@
+//===- llvm/unittest/Support/DataExtractorTest.cpp - DataExtractor tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/DataExtractor.h"
+using namespace llvm;
+
+namespace {
+
+const char numberData[] = "\x80\x90\xFF\xFF\x80\x00\x00\x00";
+const char stringData[] = "hellohello\0hello";
+const char leb128data[] = "\xA6\x49";
+const char bigleb128data[] = "\xAA\xA9\xFF\xAA\xFF\xAA\xFF\x4A";
+
+TEST(DataExtractorTest, OffsetOverflow) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ EXPECT_FALSE(DE.isValidOffsetForDataOfSize(-2U, 5));
+}
+
+TEST(DataExtractorTest, UnsignedNumbers) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(0x80U, DE.getU8(&offset));
+ EXPECT_EQ(1U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090U, DE.getU16(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFFU, DE.getU32(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFF80000000ULL, DE.getU64(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+ EXPECT_EQ(0x8090FFFF80000000ULL, DE.getAddress(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+
+ uint32_t data[2];
+ EXPECT_EQ(data, DE.getU32(&offset, data, 2));
+ EXPECT_EQ(0x8090FFFFU, data[0]);
+ EXPECT_EQ(0x80000000U, data[1]);
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+
+ // Now for little endian.
+ DE = DataExtractor(StringRef(numberData, sizeof(numberData)-1), true, 4);
+ EXPECT_EQ(0x9080U, DE.getU16(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(0xFFFF9080U, DE.getU32(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(0x80FFFF9080ULL, DE.getU64(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+ EXPECT_EQ(0xFFFF9080U, DE.getAddress(&offset));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+
+ EXPECT_EQ(data, DE.getU32(&offset, data, 2));
+ EXPECT_EQ(0xFFFF9080U, data[0]);
+ EXPECT_EQ(0x80U, data[1]);
+ EXPECT_EQ(8U, offset);
+}
+
+TEST(DataExtractorTest, SignedNumbers) {
+ DataExtractor DE(StringRef(numberData, sizeof(numberData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(-128, DE.getSigned(&offset, 1));
+ EXPECT_EQ(1U, offset);
+ offset = 0;
+ EXPECT_EQ(-32624, DE.getSigned(&offset, 2));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(-2137980929, DE.getSigned(&offset, 4));
+ EXPECT_EQ(4U, offset);
+ offset = 0;
+ EXPECT_EQ(-9182558167379214336LL, DE.getSigned(&offset, 8));
+ EXPECT_EQ(8U, offset);
+}
+
+TEST(DataExtractorTest, Strings) {
+ DataExtractor DE(StringRef(stringData, sizeof(stringData)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(stringData, DE.getCStr(&offset));
+ EXPECT_EQ(11U, offset);
+ EXPECT_EQ(nullptr, DE.getCStr(&offset));
+ EXPECT_EQ(11U, offset);
+}
+
+TEST(DataExtractorTest, LEB128) {
+ DataExtractor DE(StringRef(leb128data, sizeof(leb128data)-1), false, 8);
+ uint32_t offset = 0;
+
+ EXPECT_EQ(9382ULL, DE.getULEB128(&offset));
+ EXPECT_EQ(2U, offset);
+ offset = 0;
+ EXPECT_EQ(-7002LL, DE.getSLEB128(&offset));
+ EXPECT_EQ(2U, offset);
+
+ DataExtractor BDE(StringRef(bigleb128data, sizeof(bigleb128data)-1), false,8);
+ offset = 0;
+ EXPECT_EQ(42218325750568106ULL, BDE.getULEB128(&offset));
+ EXPECT_EQ(8U, offset);
+ offset = 0;
+ EXPECT_EQ(-29839268287359830LL, BDE.getSLEB128(&offset));
+ EXPECT_EQ(8U, offset);
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/DwarfTest.cpp b/gnu/llvm/unittests/Support/DwarfTest.cpp
new file mode 100644
index 00000000000..74fcc989b45
--- /dev/null
+++ b/gnu/llvm/unittests/Support/DwarfTest.cpp
@@ -0,0 +1,141 @@
+//===- unittest/Support/DwarfTest.cpp - Dwarf support tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Dwarf.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::dwarf;
+
+namespace {
+
+TEST(DwarfTest, TagStringOnInvalid) {
+ // This is invalid, so it shouldn't be stringified.
+ EXPECT_EQ(nullptr, TagString(DW_TAG_invalid));
+
+ // These aren't really tags: they describe ranges within tags. They
+ // shouldn't be stringified either.
+ EXPECT_EQ(nullptr, TagString(DW_TAG_lo_user));
+ EXPECT_EQ(nullptr, TagString(DW_TAG_hi_user));
+ EXPECT_EQ(nullptr, TagString(DW_TAG_user_base));
+}
+
+TEST(DwarfTest, getTag) {
+ // A couple of valid tags.
+ EXPECT_EQ(DW_TAG_array_type, getTag("DW_TAG_array_type"));
+ EXPECT_EQ(DW_TAG_module, getTag("DW_TAG_module"));
+
+ // Invalid tags.
+ EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_invalid"));
+ EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_madeuptag"));
+ EXPECT_EQ(DW_TAG_invalid, getTag("something else"));
+
+ // Tag range markers should not be recognized.
+ EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_lo_user"));
+ EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_hi_user"));
+ EXPECT_EQ(DW_TAG_invalid, getTag("DW_TAG_user_base"));
+}
+
+TEST(DwarfTest, getOperationEncoding) {
+ // Some valid ops.
+ EXPECT_EQ(DW_OP_deref, getOperationEncoding("DW_OP_deref"));
+ EXPECT_EQ(DW_OP_bit_piece, getOperationEncoding("DW_OP_bit_piece"));
+
+ // Invalid ops.
+ EXPECT_EQ(0u, getOperationEncoding("DW_OP_otherthings"));
+ EXPECT_EQ(0u, getOperationEncoding("other"));
+
+ // Markers shouldn't be recognized.
+ EXPECT_EQ(0u, getOperationEncoding("DW_OP_lo_user"));
+ EXPECT_EQ(0u, getOperationEncoding("DW_OP_hi_user"));
+}
+
+TEST(DwarfTest, LanguageStringOnInvalid) {
+ // This is invalid, so it shouldn't be stringified.
+ EXPECT_EQ(nullptr, LanguageString(0));
+
+ // These aren't really tags: they describe ranges within tags. They
+ // shouldn't be stringified either.
+ EXPECT_EQ(nullptr, LanguageString(DW_LANG_lo_user));
+ EXPECT_EQ(nullptr, LanguageString(DW_LANG_hi_user));
+}
+
+TEST(DwarfTest, getLanguage) {
+ // A couple of valid languages.
+ EXPECT_EQ(DW_LANG_C89, getLanguage("DW_LANG_C89"));
+ EXPECT_EQ(DW_LANG_C_plus_plus_11, getLanguage("DW_LANG_C_plus_plus_11"));
+ EXPECT_EQ(DW_LANG_OCaml, getLanguage("DW_LANG_OCaml"));
+ EXPECT_EQ(DW_LANG_Mips_Assembler, getLanguage("DW_LANG_Mips_Assembler"));
+
+ // Invalid languages.
+ EXPECT_EQ(0u, getLanguage("DW_LANG_invalid"));
+ EXPECT_EQ(0u, getLanguage("DW_TAG_array_type"));
+ EXPECT_EQ(0u, getLanguage("something else"));
+
+ // Language range markers should not be recognized.
+ EXPECT_EQ(0u, getLanguage("DW_LANG_lo_user"));
+ EXPECT_EQ(0u, getLanguage("DW_LANG_hi_user"));
+}
+
+TEST(DwarfTest, AttributeEncodingStringOnInvalid) {
+ // This is invalid, so it shouldn't be stringified.
+ EXPECT_EQ(nullptr, AttributeEncodingString(0));
+
+ // These aren't really tags: they describe ranges within tags. They
+ // shouldn't be stringified either.
+ EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_lo_user));
+ EXPECT_EQ(nullptr, AttributeEncodingString(DW_ATE_hi_user));
+}
+
+TEST(DwarfTest, getAttributeEncoding) {
+ // A couple of valid languages.
+ EXPECT_EQ(DW_ATE_boolean, getAttributeEncoding("DW_ATE_boolean"));
+ EXPECT_EQ(DW_ATE_imaginary_float,
+ getAttributeEncoding("DW_ATE_imaginary_float"));
+
+ // Invalid languages.
+ EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_invalid"));
+ EXPECT_EQ(0u, getAttributeEncoding("DW_TAG_array_type"));
+ EXPECT_EQ(0u, getAttributeEncoding("something else"));
+
+ // AttributeEncoding range markers should not be recognized.
+ EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_lo_user"));
+ EXPECT_EQ(0u, getAttributeEncoding("DW_ATE_hi_user"));
+}
+
+TEST(DwarfTest, VirtualityString) {
+ EXPECT_EQ(StringRef("DW_VIRTUALITY_none"),
+ VirtualityString(DW_VIRTUALITY_none));
+ EXPECT_EQ(StringRef("DW_VIRTUALITY_virtual"),
+ VirtualityString(DW_VIRTUALITY_virtual));
+ EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"),
+ VirtualityString(DW_VIRTUALITY_pure_virtual));
+
+ // DW_VIRTUALITY_max should be pure virtual.
+ EXPECT_EQ(StringRef("DW_VIRTUALITY_pure_virtual"),
+ VirtualityString(DW_VIRTUALITY_max));
+
+ // Invalid numbers shouldn't be stringified.
+ EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 1));
+ EXPECT_EQ(nullptr, VirtualityString(DW_VIRTUALITY_max + 77));
+}
+
+TEST(DwarfTest, getVirtuality) {
+ EXPECT_EQ(DW_VIRTUALITY_none, getVirtuality("DW_VIRTUALITY_none"));
+ EXPECT_EQ(DW_VIRTUALITY_virtual, getVirtuality("DW_VIRTUALITY_virtual"));
+ EXPECT_EQ(DW_VIRTUALITY_pure_virtual,
+ getVirtuality("DW_VIRTUALITY_pure_virtual"));
+
+ // Invalid strings.
+ EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_invalid"));
+ EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("DW_VIRTUALITY_max"));
+ EXPECT_EQ(DW_VIRTUALITY_invalid, getVirtuality("something else"));
+}
+
+} // end namespace
diff --git a/gnu/llvm/unittests/Support/EndianStreamTest.cpp b/gnu/llvm/unittests/Support/EndianStreamTest.cpp
new file mode 100644
index 00000000000..6a69be55f92
--- /dev/null
+++ b/gnu/llvm/unittests/Support/EndianStreamTest.cpp
@@ -0,0 +1,157 @@
+//===- unittests/Support/EndianStreamTest.cpp - EndianStream.h 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/SmallString.h"
+#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+using namespace llvm;
+using namespace support;
+
+namespace {
+
+TEST(EndianStream, WriteInt32LE) {
+ SmallString<16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<little> LE(OS);
+ LE.write(static_cast<int32_t>(-1362446643));
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xB6);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xCA);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xAE);
+}
+
+TEST(EndianStream, WriteInt32BE) {
+ SmallVector<char, 16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<big> BE(OS);
+ BE.write(static_cast<int32_t>(-1362446643));
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xAE);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xCA);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xB6);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xCD);
+}
+
+
+TEST(EndianStream, WriteFloatLE) {
+ SmallString<16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<little> LE(OS);
+ LE.write(12345.0f);
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x00);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xE4);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0x40);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x46);
+}
+
+TEST(EndianStream, WriteFloatBE) {
+ SmallVector<char, 16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<big> BE(OS);
+ BE.write(12345.0f);
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x46);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x40);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xE4);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x00);
+}
+
+TEST(EndianStream, WriteInt64LE) {
+ SmallString<16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<little> LE(OS);
+ LE.write(static_cast<int64_t>(-136244664332342323));
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xCD);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xAB);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xED);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x1B);
+ EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x33);
+ EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xF6);
+ EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x1B);
+ EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xFE);
+}
+
+TEST(EndianStream, WriteInt64BE) {
+ SmallVector<char, 16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<big> BE(OS);
+ BE.write(static_cast<int64_t>(-136244664332342323));
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xFE);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x1B);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xF6);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x33);
+ EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x1B);
+ EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xED);
+ EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xAB);
+ EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xCD);
+}
+
+TEST(EndianStream, WriteDoubleLE) {
+ SmallString<16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<little> LE(OS);
+ LE.write(-2349214918.58107);
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0x20);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0x98);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0xD2);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0x98);
+ EXPECT_EQ(static_cast<uint8_t>(data[4]), 0xC5);
+ EXPECT_EQ(static_cast<uint8_t>(data[5]), 0x80);
+ EXPECT_EQ(static_cast<uint8_t>(data[6]), 0xE1);
+ EXPECT_EQ(static_cast<uint8_t>(data[7]), 0xC1);
+}
+
+TEST(EndianStream, WriteDoubleBE) {
+ SmallVector<char, 16> data;
+
+ {
+ raw_svector_ostream OS(data);
+ endian::Writer<big> BE(OS);
+ BE.write(-2349214918.58107);
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(data[0]), 0xC1);
+ EXPECT_EQ(static_cast<uint8_t>(data[1]), 0xE1);
+ EXPECT_EQ(static_cast<uint8_t>(data[2]), 0x80);
+ EXPECT_EQ(static_cast<uint8_t>(data[3]), 0xC5);
+ EXPECT_EQ(static_cast<uint8_t>(data[4]), 0x98);
+ EXPECT_EQ(static_cast<uint8_t>(data[5]), 0xD2);
+ EXPECT_EQ(static_cast<uint8_t>(data[6]), 0x98);
+ EXPECT_EQ(static_cast<uint8_t>(data[7]), 0x20);
+}
+
+
+} // end anon namespace
diff --git a/gnu/llvm/unittests/Support/EndianTest.cpp b/gnu/llvm/unittests/Support/EndianTest.cpp
new file mode 100644
index 00000000000..c2b5572e574
--- /dev/null
+++ b/gnu/llvm/unittests/Support/EndianTest.cpp
@@ -0,0 +1,204 @@
+//===- unittests/Support/EndianTest.cpp - Endian.h tests ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+#include <ctime>
+using namespace llvm;
+using namespace support;
+
+#undef max
+
+namespace {
+
+TEST(Endian, Read) {
+ // These are 5 bytes so we can be sure at least one of the reads is unaligned.
+ unsigned char bigval[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+ unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01};
+ int32_t BigAsHost = 0x00010203;
+ EXPECT_EQ(BigAsHost, (endian::read<int32_t, big, unaligned>(bigval)));
+ int32_t LittleAsHost = 0x02030400;
+ EXPECT_EQ(LittleAsHost,(endian::read<int32_t, little, unaligned>(littleval)));
+
+ EXPECT_EQ((endian::read<int32_t, big, unaligned>(bigval + 1)),
+ (endian::read<int32_t, little, unaligned>(littleval + 1)));
+}
+
+TEST(Endian, ReadBitAligned) {
+ // Simple test to make sure we properly pull out the 0x0 word.
+ unsigned char littleval[] = {0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff};
+ unsigned char bigval[] = {0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0};
+ EXPECT_EQ(
+ (endian::readAtBitAlignment<int, little, unaligned>(&littleval[0], 6)),
+ 0x0);
+ EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval[0], 6)),
+ 0x0);
+ // Test to make sure that signed right shift of 0xf0000000 is masked
+ // properly.
+ unsigned char littleval2[] = {0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00};
+ unsigned char bigval2[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ EXPECT_EQ(
+ (endian::readAtBitAlignment<int, little, unaligned>(&littleval2[0], 4)),
+ 0x0f000000);
+ EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval2[0], 4)),
+ 0x0f000000);
+ // Test to make sure left shift of start bit doesn't overflow.
+ EXPECT_EQ(
+ (endian::readAtBitAlignment<int, little, unaligned>(&littleval2[0], 1)),
+ 0x78000000);
+ EXPECT_EQ((endian::readAtBitAlignment<int, big, unaligned>(&bigval2[0], 1)),
+ 0x78000000);
+ // Test to make sure 64-bit int doesn't overflow.
+ unsigned char littleval3[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ unsigned char bigval3[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+ EXPECT_EQ((endian::readAtBitAlignment<int64_t, little, unaligned>(
+ &littleval3[0], 4)),
+ 0x0f00000000000000);
+ EXPECT_EQ(
+ (endian::readAtBitAlignment<int64_t, big, unaligned>(&bigval3[0], 4)),
+ 0x0f00000000000000);
+}
+
+TEST(Endian, WriteBitAligned) {
+ // This test ensures that signed right shift of 0xffffaa is masked
+ // properly.
+ unsigned char bigval[8] = {0x00};
+ endian::writeAtBitAlignment<int32_t, big, unaligned>(bigval, (int)0xffffaaaa,
+ 4);
+ EXPECT_EQ(bigval[0], 0xff);
+ EXPECT_EQ(bigval[1], 0xfa);
+ EXPECT_EQ(bigval[2], 0xaa);
+ EXPECT_EQ(bigval[3], 0xa0);
+ EXPECT_EQ(bigval[4], 0x00);
+ EXPECT_EQ(bigval[5], 0x00);
+ EXPECT_EQ(bigval[6], 0x00);
+ EXPECT_EQ(bigval[7], 0x0f);
+
+ unsigned char littleval[8] = {0x00};
+ endian::writeAtBitAlignment<int32_t, little, unaligned>(littleval,
+ (int)0xffffaaaa, 4);
+ EXPECT_EQ(littleval[0], 0xa0);
+ EXPECT_EQ(littleval[1], 0xaa);
+ EXPECT_EQ(littleval[2], 0xfa);
+ EXPECT_EQ(littleval[3], 0xff);
+ EXPECT_EQ(littleval[4], 0x0f);
+ EXPECT_EQ(littleval[5], 0x00);
+ EXPECT_EQ(littleval[6], 0x00);
+ EXPECT_EQ(littleval[7], 0x00);
+
+ // This test makes sure 1<<31 doesn't overflow.
+ // Test to make sure left shift of start bit doesn't overflow.
+ unsigned char bigval2[8] = {0x00};
+ endian::writeAtBitAlignment<int32_t, big, unaligned>(bigval2, (int)0xffffffff,
+ 1);
+ EXPECT_EQ(bigval2[0], 0xff);
+ EXPECT_EQ(bigval2[1], 0xff);
+ EXPECT_EQ(bigval2[2], 0xff);
+ EXPECT_EQ(bigval2[3], 0xfe);
+ EXPECT_EQ(bigval2[4], 0x00);
+ EXPECT_EQ(bigval2[5], 0x00);
+ EXPECT_EQ(bigval2[6], 0x00);
+ EXPECT_EQ(bigval2[7], 0x01);
+
+ unsigned char littleval2[8] = {0x00};
+ endian::writeAtBitAlignment<int32_t, little, unaligned>(littleval2,
+ (int)0xffffffff, 1);
+ EXPECT_EQ(littleval2[0], 0xfe);
+ EXPECT_EQ(littleval2[1], 0xff);
+ EXPECT_EQ(littleval2[2], 0xff);
+ EXPECT_EQ(littleval2[3], 0xff);
+ EXPECT_EQ(littleval2[4], 0x01);
+ EXPECT_EQ(littleval2[5], 0x00);
+ EXPECT_EQ(littleval2[6], 0x00);
+ EXPECT_EQ(littleval2[7], 0x00);
+
+ // Test to make sure 64-bit int doesn't overflow.
+ unsigned char bigval64[16] = {0x00};
+ endian::writeAtBitAlignment<int64_t, big, unaligned>(
+ bigval64, (int64_t)0xffffffffffffffff, 1);
+ EXPECT_EQ(bigval64[0], 0xff);
+ EXPECT_EQ(bigval64[1], 0xff);
+ EXPECT_EQ(bigval64[2], 0xff);
+ EXPECT_EQ(bigval64[3], 0xff);
+ EXPECT_EQ(bigval64[4], 0xff);
+ EXPECT_EQ(bigval64[5], 0xff);
+ EXPECT_EQ(bigval64[6], 0xff);
+ EXPECT_EQ(bigval64[7], 0xfe);
+ EXPECT_EQ(bigval64[8], 0x00);
+ EXPECT_EQ(bigval64[9], 0x00);
+ EXPECT_EQ(bigval64[10], 0x00);
+ EXPECT_EQ(bigval64[11], 0x00);
+ EXPECT_EQ(bigval64[12], 0x00);
+ EXPECT_EQ(bigval64[13], 0x00);
+ EXPECT_EQ(bigval64[14], 0x00);
+ EXPECT_EQ(bigval64[15], 0x01);
+
+ unsigned char littleval64[16] = {0x00};
+ endian::writeAtBitAlignment<int64_t, little, unaligned>(
+ littleval64, (int64_t)0xffffffffffffffff, 1);
+ EXPECT_EQ(littleval64[0], 0xfe);
+ EXPECT_EQ(littleval64[1], 0xff);
+ EXPECT_EQ(littleval64[2], 0xff);
+ EXPECT_EQ(littleval64[3], 0xff);
+ EXPECT_EQ(littleval64[4], 0xff);
+ EXPECT_EQ(littleval64[5], 0xff);
+ EXPECT_EQ(littleval64[6], 0xff);
+ EXPECT_EQ(littleval64[7], 0xff);
+ EXPECT_EQ(littleval64[8], 0x01);
+ EXPECT_EQ(littleval64[9], 0x00);
+ EXPECT_EQ(littleval64[10], 0x00);
+ EXPECT_EQ(littleval64[11], 0x00);
+ EXPECT_EQ(littleval64[12], 0x00);
+ EXPECT_EQ(littleval64[13], 0x00);
+ EXPECT_EQ(littleval64[14], 0x00);
+ EXPECT_EQ(littleval64[15], 0x00);
+}
+
+TEST(Endian, Write) {
+ unsigned char data[5];
+ endian::write<int32_t, big, unaligned>(data, -1362446643);
+ EXPECT_EQ(data[0], 0xAE);
+ EXPECT_EQ(data[1], 0xCA);
+ EXPECT_EQ(data[2], 0xB6);
+ EXPECT_EQ(data[3], 0xCD);
+ endian::write<int32_t, big, unaligned>(data + 1, -1362446643);
+ EXPECT_EQ(data[1], 0xAE);
+ EXPECT_EQ(data[2], 0xCA);
+ EXPECT_EQ(data[3], 0xB6);
+ EXPECT_EQ(data[4], 0xCD);
+
+ endian::write<int32_t, little, unaligned>(data, -1362446643);
+ EXPECT_EQ(data[0], 0xCD);
+ EXPECT_EQ(data[1], 0xB6);
+ EXPECT_EQ(data[2], 0xCA);
+ EXPECT_EQ(data[3], 0xAE);
+ endian::write<int32_t, little, unaligned>(data + 1, -1362446643);
+ EXPECT_EQ(data[1], 0xCD);
+ EXPECT_EQ(data[2], 0xB6);
+ EXPECT_EQ(data[3], 0xCA);
+ EXPECT_EQ(data[4], 0xAE);
+}
+
+TEST(Endian, PackedEndianSpecificIntegral) {
+ // These are 5 bytes so we can be sure at least one of the reads is unaligned.
+ unsigned char big[] = {0x00, 0x01, 0x02, 0x03, 0x04};
+ unsigned char little[] = {0x00, 0x04, 0x03, 0x02, 0x01};
+ big32_t *big_val =
+ reinterpret_cast<big32_t *>(big + 1);
+ little32_t *little_val =
+ reinterpret_cast<little32_t *>(little + 1);
+
+ EXPECT_EQ(*big_val, *little_val);
+}
+
+} // end anon namespace
diff --git a/gnu/llvm/unittests/Support/ErrorOrTest.cpp b/gnu/llvm/unittests/Support/ErrorOrTest.cpp
new file mode 100644
index 00000000000..73d0e3f2bb7
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ErrorOrTest.cpp
@@ -0,0 +1,100 @@
+//===- unittests/ErrorOrTest.cpp - ErrorOr.h tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/Errc.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+ErrorOr<int> t1() {return 1;}
+ErrorOr<int> t2() { return errc::invalid_argument; }
+
+TEST(ErrorOr, SimpleValue) {
+ ErrorOr<int> a = t1();
+ // FIXME: This is probably a bug in gtest. EXPECT_TRUE should expand to
+ // include the !! to make it friendly to explicit bool operators.
+ EXPECT_TRUE(!!a);
+ EXPECT_EQ(1, *a);
+
+ ErrorOr<int> b = a;
+ EXPECT_EQ(1, *b);
+
+ a = t2();
+ EXPECT_FALSE(a);
+ EXPECT_EQ(a.getError(), errc::invalid_argument);
+#ifdef EXPECT_DEBUG_DEATH
+ EXPECT_DEBUG_DEATH(*a, "Cannot get value when an error exists");
+#endif
+}
+
+ErrorOr<std::unique_ptr<int> > t3() {
+ return std::unique_ptr<int>(new int(3));
+}
+
+TEST(ErrorOr, Types) {
+ int x;
+ ErrorOr<int&> a(x);
+ *a = 42;
+ EXPECT_EQ(42, x);
+
+ // Move only types.
+ EXPECT_EQ(3, **t3());
+}
+
+struct B {};
+struct D : B {};
+
+TEST(ErrorOr, Covariant) {
+ ErrorOr<B*> b(ErrorOr<D*>(nullptr));
+ b = ErrorOr<D*>(nullptr);
+
+ ErrorOr<std::unique_ptr<B> > b1(ErrorOr<std::unique_ptr<D> >(nullptr));
+ b1 = ErrorOr<std::unique_ptr<D> >(nullptr);
+
+ ErrorOr<std::unique_ptr<int>> b2(ErrorOr<int *>(nullptr));
+ ErrorOr<int *> b3(nullptr);
+ ErrorOr<std::unique_ptr<int>> b4(b3);
+}
+
+TEST(ErrorOr, Comparison) {
+ ErrorOr<int> x(errc::no_such_file_or_directory);
+ EXPECT_EQ(x, errc::no_such_file_or_directory);
+}
+
+// ErrorOr<int*> x(nullptr);
+// ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion
+static_assert(
+ !std::is_convertible<const ErrorOr<int *> &,
+ ErrorOr<std::unique_ptr<int>>>::value,
+ "do not invoke explicit ctors in implicit conversion from lvalue");
+
+// ErrorOr<std::unique_ptr<int>> y = ErrorOr<int*>(nullptr); // invalid
+// // conversion
+static_assert(
+ !std::is_convertible<ErrorOr<int *> &&,
+ ErrorOr<std::unique_ptr<int>>>::value,
+ "do not invoke explicit ctors in implicit conversion from rvalue");
+
+// ErrorOr<int*> x(nullptr);
+// ErrorOr<std::unique_ptr<int>> y;
+// y = x; // invalid conversion
+static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>,
+ const ErrorOr<int *> &>::value,
+ "do not invoke explicit ctors in assignment");
+
+// ErrorOr<std::unique_ptr<int>> x;
+// x = ErrorOr<int*>(nullptr); // invalid conversion
+static_assert(!std::is_assignable<ErrorOr<std::unique_ptr<int>>,
+ ErrorOr<int *> &&>::value,
+ "do not invoke explicit ctors in assignment");
+} // end anon namespace
diff --git a/gnu/llvm/unittests/Support/FileOutputBufferTest.cpp b/gnu/llvm/unittests/Support/FileOutputBufferTest.cpp
new file mode 100644
index 00000000000..090c476e35c
--- /dev/null
+++ b/gnu/llvm/unittests/Support/FileOutputBufferTest.cpp
@@ -0,0 +1,121 @@
+//===- llvm/unittest/Support/FileOutputBuffer.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/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::sys;
+
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ errs() << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ } else { \
+ }
+
+namespace {
+TEST(FileOutputBuffer, Test) {
+ // Create unique temporary directory for these tests
+ SmallString<128> TestDirectory;
+ {
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("FileOutputBuffer-test", TestDirectory));
+ }
+
+ // TEST 1: Verify commit case.
+ SmallString<128> File1(TestDirectory);
+ File1.append("/file1");
+ {
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(File1, 8192);
+ ASSERT_NO_ERROR(BufferOrErr.getError());
+ std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
+ // Start buffer with special header.
+ memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Write to end of buffer to verify it is writable.
+ memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Commit buffer.
+ ASSERT_NO_ERROR(Buffer->commit());
+ }
+
+ // Verify file is correct size.
+ uint64_t File1Size;
+ ASSERT_NO_ERROR(fs::file_size(Twine(File1), File1Size));
+ ASSERT_EQ(File1Size, 8192ULL);
+ ASSERT_NO_ERROR(fs::remove(File1.str()));
+
+ // TEST 2: Verify abort case.
+ SmallString<128> File2(TestDirectory);
+ File2.append("/file2");
+ {
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr =
+ FileOutputBuffer::create(File2, 8192);
+ ASSERT_NO_ERROR(Buffer2OrErr.getError());
+ std::unique_ptr<FileOutputBuffer> &Buffer2 = *Buffer2OrErr;
+ // Fill buffer with special header.
+ memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Do *not* commit buffer.
+ }
+ // Verify file does not exist (because buffer not committed).
+ ASSERT_EQ(fs::access(Twine(File2), fs::AccessMode::Exist),
+ errc::no_such_file_or_directory);
+ ASSERT_NO_ERROR(fs::remove(File2.str()));
+
+ // TEST 3: Verify sizing down case.
+ SmallString<128> File3(TestDirectory);
+ File3.append("/file3");
+ {
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(File3, 8192000);
+ ASSERT_NO_ERROR(BufferOrErr.getError());
+ std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
+ // Start buffer with special header.
+ memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Write to end of buffer to verify it is writable.
+ memcpy(Buffer->getBufferEnd() - 20, "AABBCCDDEEFFGGHHIIJJ", 20);
+ ASSERT_NO_ERROR(Buffer->commit());
+ }
+
+ // Verify file is correct size.
+ uint64_t File3Size;
+ ASSERT_NO_ERROR(fs::file_size(Twine(File3), File3Size));
+ ASSERT_EQ(File3Size, 8192000ULL);
+ ASSERT_NO_ERROR(fs::remove(File3.str()));
+
+ // TEST 4: Verify file can be made executable.
+ SmallString<128> File4(TestDirectory);
+ File4.append("/file4");
+ {
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(File4, 8192, FileOutputBuffer::F_executable);
+ ASSERT_NO_ERROR(BufferOrErr.getError());
+ std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;
+ // Start buffer with special header.
+ memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);
+ // Commit buffer.
+ ASSERT_NO_ERROR(Buffer->commit());
+ }
+ // Verify file exists and is executable.
+ fs::file_status Status;
+ ASSERT_NO_ERROR(fs::status(Twine(File4), Status));
+ bool IsExecutable = (Status.permissions() & fs::owner_exe);
+ EXPECT_TRUE(IsExecutable);
+ ASSERT_NO_ERROR(fs::remove(File4.str()));
+
+ // Clean up.
+ ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
+}
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/IteratorTest.cpp b/gnu/llvm/unittests/Support/IteratorTest.cpp
new file mode 100644
index 00000000000..83848328c0c
--- /dev/null
+++ b/gnu/llvm/unittests/Support/IteratorTest.cpp
@@ -0,0 +1,101 @@
+//===- 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/iterator.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+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);
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/LEB128Test.cpp b/gnu/llvm/unittests/Support/LEB128Test.cpp
new file mode 100644
index 00000000000..76b63e5a838
--- /dev/null
+++ b/gnu/llvm/unittests/Support/LEB128Test.cpp
@@ -0,0 +1,348 @@
+//===- llvm/unittest/Support/LEB128Test.cpp - LEB128 function tests -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+using namespace llvm;
+
+namespace {
+
+TEST(LEB128Test, EncodeSLEB128) {
+#define EXPECT_SLEB128_EQ(EXPECTED, VALUE) \
+ do { \
+ /* encodeSLEB128(uint64_t, raw_ostream &) */ \
+ std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \
+ std::string Actual; \
+ raw_string_ostream Stream(Actual); \
+ encodeSLEB128(VALUE, Stream); \
+ Stream.flush(); \
+ EXPECT_EQ(Expected, Actual); \
+ } while (0)
+
+ // Encode SLEB128
+ EXPECT_SLEB128_EQ("\x00", 0);
+ EXPECT_SLEB128_EQ("\x01", 1);
+ EXPECT_SLEB128_EQ("\x7f", -1);
+ EXPECT_SLEB128_EQ("\x3f", 63);
+ EXPECT_SLEB128_EQ("\x41", -63);
+ EXPECT_SLEB128_EQ("\x40", -64);
+ EXPECT_SLEB128_EQ("\xbf\x7f", -65);
+ EXPECT_SLEB128_EQ("\xc0\x00", 64);
+
+#undef EXPECT_SLEB128_EQ
+}
+
+TEST(LEB128Test, EncodeULEB128) {
+#define EXPECT_ULEB128_EQ(EXPECTED, VALUE, PAD) \
+ do { \
+ std::string Expected(EXPECTED, sizeof(EXPECTED) - 1); \
+ \
+ /* encodeULEB128(uint64_t, raw_ostream &, unsigned) */ \
+ std::string Actual1; \
+ raw_string_ostream Stream(Actual1); \
+ encodeULEB128(VALUE, Stream, PAD); \
+ Stream.flush(); \
+ EXPECT_EQ(Expected, Actual1); \
+ \
+ /* encodeULEB128(uint64_t, uint8_t *, unsigned) */ \
+ uint8_t Buffer[32]; \
+ unsigned Size = encodeULEB128(VALUE, Buffer, PAD); \
+ std::string Actual2(reinterpret_cast<const char *>(Buffer), Size); \
+ EXPECT_EQ(Expected, Actual2); \
+ } while (0)
+
+ // Encode ULEB128
+ EXPECT_ULEB128_EQ("\x00", 0, 0);
+ EXPECT_ULEB128_EQ("\x01", 1, 0);
+ EXPECT_ULEB128_EQ("\x3f", 63, 0);
+ EXPECT_ULEB128_EQ("\x40", 64, 0);
+ EXPECT_ULEB128_EQ("\x7f", 0x7f, 0);
+ EXPECT_ULEB128_EQ("\x80\x01", 0x80, 0);
+ EXPECT_ULEB128_EQ("\x81\x01", 0x81, 0);
+ EXPECT_ULEB128_EQ("\x90\x01", 0x90, 0);
+ EXPECT_ULEB128_EQ("\xff\x01", 0xff, 0);
+ EXPECT_ULEB128_EQ("\x80\x02", 0x100, 0);
+ EXPECT_ULEB128_EQ("\x81\x02", 0x101, 0);
+
+ // Encode ULEB128 with some extra padding bytes
+ EXPECT_ULEB128_EQ("\x80\x00", 0, 1);
+ EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 2);
+ EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 1);
+ EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 2);
+ EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 1);
+ EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 2);
+
+#undef EXPECT_ULEB128_EQ
+}
+
+TEST(LEB128Test, DecodeULEB128) {
+#define EXPECT_DECODE_ULEB128_EQ(EXPECTED, VALUE) \
+ do { \
+ unsigned ActualSize = 0; \
+ uint64_t Actual = decodeULEB128(reinterpret_cast<const uint8_t *>(VALUE), \
+ &ActualSize); \
+ EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \
+ EXPECT_EQ(EXPECTED, Actual); \
+ } while (0)
+
+ // Decode ULEB128
+ EXPECT_DECODE_ULEB128_EQ(0u, "\x00");
+ EXPECT_DECODE_ULEB128_EQ(1u, "\x01");
+ EXPECT_DECODE_ULEB128_EQ(63u, "\x3f");
+ EXPECT_DECODE_ULEB128_EQ(64u, "\x40");
+ EXPECT_DECODE_ULEB128_EQ(0x7fu, "\x7f");
+ EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x01");
+ EXPECT_DECODE_ULEB128_EQ(0x81u, "\x81\x01");
+ EXPECT_DECODE_ULEB128_EQ(0x90u, "\x90\x01");
+ EXPECT_DECODE_ULEB128_EQ(0xffu, "\xff\x01");
+ EXPECT_DECODE_ULEB128_EQ(0x100u, "\x80\x02");
+ EXPECT_DECODE_ULEB128_EQ(0x101u, "\x81\x02");
+ EXPECT_DECODE_ULEB128_EQ(4294975616ULL, "\x80\xc1\x80\x80\x10");
+
+ // Decode ULEB128 with extra padding bytes
+ EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x00");
+ EXPECT_DECODE_ULEB128_EQ(0u, "\x80\x80\x00");
+ EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x00");
+ EXPECT_DECODE_ULEB128_EQ(0x7fu, "\xff\x80\x00");
+ EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x00");
+ EXPECT_DECODE_ULEB128_EQ(0x80u, "\x80\x81\x80\x00");
+
+#undef EXPECT_DECODE_ULEB128_EQ
+}
+
+TEST(LEB128Test, DecodeSLEB128) {
+#define EXPECT_DECODE_SLEB128_EQ(EXPECTED, VALUE) \
+ do { \
+ unsigned ActualSize = 0; \
+ int64_t Actual = decodeSLEB128(reinterpret_cast<const uint8_t *>(VALUE), \
+ &ActualSize); \
+ EXPECT_EQ(sizeof(VALUE) - 1, ActualSize); \
+ EXPECT_EQ(EXPECTED, Actual); \
+ } while (0)
+
+ // Decode SLEB128
+ EXPECT_DECODE_SLEB128_EQ(0L, "\x00");
+ EXPECT_DECODE_SLEB128_EQ(1L, "\x01");
+ EXPECT_DECODE_SLEB128_EQ(63L, "\x3f");
+ EXPECT_DECODE_SLEB128_EQ(-64L, "\x40");
+ EXPECT_DECODE_SLEB128_EQ(-63L, "\x41");
+ EXPECT_DECODE_SLEB128_EQ(-1L, "\x7f");
+ EXPECT_DECODE_SLEB128_EQ(128L, "\x80\x01");
+ EXPECT_DECODE_SLEB128_EQ(129L, "\x81\x01");
+ EXPECT_DECODE_SLEB128_EQ(-129L, "\xff\x7e");
+ EXPECT_DECODE_SLEB128_EQ(-128L, "\x80\x7f");
+ EXPECT_DECODE_SLEB128_EQ(-127L, "\x81\x7f");
+ EXPECT_DECODE_SLEB128_EQ(64L, "\xc0\x00");
+ EXPECT_DECODE_SLEB128_EQ(-12345L, "\xc7\x9f\x7f");
+
+ // Decode unnormalized SLEB128 with extra padding bytes.
+ EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x00");
+ EXPECT_DECODE_SLEB128_EQ(0L, "\x80\x80\x00");
+ EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x00");
+ EXPECT_DECODE_SLEB128_EQ(0x7fL, "\xff\x80\x00");
+ EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x00");
+ EXPECT_DECODE_SLEB128_EQ(0x80L, "\x80\x81\x80\x00");
+
+#undef EXPECT_DECODE_SLEB128_EQ
+}
+
+TEST(LEB128Test, SLEB128Size) {
+ // Positive Value Testing Plan:
+ // (1) 128 ^ n - 1 ........ need (n+1) bytes
+ // (2) 128 ^ n ............ need (n+1) bytes
+ // (3) 128 ^ n * 63 ....... need (n+1) bytes
+ // (4) 128 ^ n * 64 - 1 ... need (n+1) bytes
+ // (5) 128 ^ n * 64 ....... need (n+2) bytes
+
+ EXPECT_EQ(1u, getSLEB128Size(0x0LL));
+ EXPECT_EQ(1u, getSLEB128Size(0x1LL));
+ EXPECT_EQ(1u, getSLEB128Size(0x3fLL));
+ EXPECT_EQ(1u, getSLEB128Size(0x3fLL));
+ EXPECT_EQ(2u, getSLEB128Size(0x40LL));
+
+ EXPECT_EQ(2u, getSLEB128Size(0x7fLL));
+ EXPECT_EQ(2u, getSLEB128Size(0x80LL));
+ EXPECT_EQ(2u, getSLEB128Size(0x1f80LL));
+ EXPECT_EQ(2u, getSLEB128Size(0x1fffLL));
+ EXPECT_EQ(3u, getSLEB128Size(0x2000LL));
+
+ EXPECT_EQ(3u, getSLEB128Size(0x3fffLL));
+ EXPECT_EQ(3u, getSLEB128Size(0x4000LL));
+ EXPECT_EQ(3u, getSLEB128Size(0xfc000LL));
+ EXPECT_EQ(3u, getSLEB128Size(0xfffffLL));
+ EXPECT_EQ(4u, getSLEB128Size(0x100000LL));
+
+ EXPECT_EQ(4u, getSLEB128Size(0x1fffffLL));
+ EXPECT_EQ(4u, getSLEB128Size(0x200000LL));
+ EXPECT_EQ(4u, getSLEB128Size(0x7e00000LL));
+ EXPECT_EQ(4u, getSLEB128Size(0x7ffffffLL));
+ EXPECT_EQ(5u, getSLEB128Size(0x8000000LL));
+
+ EXPECT_EQ(5u, getSLEB128Size(0xfffffffLL));
+ EXPECT_EQ(5u, getSLEB128Size(0x10000000LL));
+ EXPECT_EQ(5u, getSLEB128Size(0x3f0000000LL));
+ EXPECT_EQ(5u, getSLEB128Size(0x3ffffffffLL));
+ EXPECT_EQ(6u, getSLEB128Size(0x400000000LL));
+
+ EXPECT_EQ(6u, getSLEB128Size(0x7ffffffffLL));
+ EXPECT_EQ(6u, getSLEB128Size(0x800000000LL));
+ EXPECT_EQ(6u, getSLEB128Size(0x1f800000000LL));
+ EXPECT_EQ(6u, getSLEB128Size(0x1ffffffffffLL));
+ EXPECT_EQ(7u, getSLEB128Size(0x20000000000LL));
+
+ EXPECT_EQ(7u, getSLEB128Size(0x3ffffffffffLL));
+ EXPECT_EQ(7u, getSLEB128Size(0x40000000000LL));
+ EXPECT_EQ(7u, getSLEB128Size(0xfc0000000000LL));
+ EXPECT_EQ(7u, getSLEB128Size(0xffffffffffffLL));
+ EXPECT_EQ(8u, getSLEB128Size(0x1000000000000LL));
+
+ EXPECT_EQ(8u, getSLEB128Size(0x1ffffffffffffLL));
+ EXPECT_EQ(8u, getSLEB128Size(0x2000000000000LL));
+ EXPECT_EQ(8u, getSLEB128Size(0x7e000000000000LL));
+ EXPECT_EQ(8u, getSLEB128Size(0x7fffffffffffffLL));
+ EXPECT_EQ(9u, getSLEB128Size(0x80000000000000LL));
+
+ EXPECT_EQ(9u, getSLEB128Size(0xffffffffffffffLL));
+ EXPECT_EQ(9u, getSLEB128Size(0x100000000000000LL));
+ EXPECT_EQ(9u, getSLEB128Size(0x3f00000000000000LL));
+ EXPECT_EQ(9u, getSLEB128Size(0x3fffffffffffffffLL));
+ EXPECT_EQ(10u, getSLEB128Size(0x4000000000000000LL));
+
+ EXPECT_EQ(10u, getSLEB128Size(0x7fffffffffffffffLL));
+ EXPECT_EQ(10u, getSLEB128Size(INT64_MAX));
+
+ // Negative Value Testing Plan:
+ // (1) - 128 ^ n - 1 ........ need (n+1) bytes
+ // (2) - 128 ^ n ............ need (n+1) bytes
+ // (3) - 128 ^ n * 63 ....... need (n+1) bytes
+ // (4) - 128 ^ n * 64 ....... need (n+1) bytes (different from positive one)
+ // (5) - 128 ^ n * 65 - 1 ... need (n+2) bytes (if n > 0)
+ // (6) - 128 ^ n * 65 ....... need (n+2) bytes
+
+ EXPECT_EQ(1u, getSLEB128Size(0x0LL));
+ EXPECT_EQ(1u, getSLEB128Size(-0x1LL));
+ EXPECT_EQ(1u, getSLEB128Size(-0x3fLL));
+ EXPECT_EQ(1u, getSLEB128Size(-0x40LL));
+ EXPECT_EQ(1u, getSLEB128Size(-0x40LL)); // special case
+ EXPECT_EQ(2u, getSLEB128Size(-0x41LL));
+
+ EXPECT_EQ(2u, getSLEB128Size(-0x7fLL));
+ EXPECT_EQ(2u, getSLEB128Size(-0x80LL));
+ EXPECT_EQ(2u, getSLEB128Size(-0x1f80LL));
+ EXPECT_EQ(2u, getSLEB128Size(-0x2000LL));
+ EXPECT_EQ(3u, getSLEB128Size(-0x207fLL));
+ EXPECT_EQ(3u, getSLEB128Size(-0x2080LL));
+
+ EXPECT_EQ(3u, getSLEB128Size(-0x3fffLL));
+ EXPECT_EQ(3u, getSLEB128Size(-0x4000LL));
+ EXPECT_EQ(3u, getSLEB128Size(-0xfc000LL));
+ EXPECT_EQ(3u, getSLEB128Size(-0x100000LL));
+ EXPECT_EQ(4u, getSLEB128Size(-0x103fffLL));
+ EXPECT_EQ(4u, getSLEB128Size(-0x104000LL));
+
+ EXPECT_EQ(4u, getSLEB128Size(-0x1fffffLL));
+ EXPECT_EQ(4u, getSLEB128Size(-0x200000LL));
+ EXPECT_EQ(4u, getSLEB128Size(-0x7e00000LL));
+ EXPECT_EQ(4u, getSLEB128Size(-0x8000000LL));
+ EXPECT_EQ(5u, getSLEB128Size(-0x81fffffLL));
+ EXPECT_EQ(5u, getSLEB128Size(-0x8200000LL));
+
+ EXPECT_EQ(5u, getSLEB128Size(-0xfffffffLL));
+ EXPECT_EQ(5u, getSLEB128Size(-0x10000000LL));
+ EXPECT_EQ(5u, getSLEB128Size(-0x3f0000000LL));
+ EXPECT_EQ(5u, getSLEB128Size(-0x400000000LL));
+ EXPECT_EQ(6u, getSLEB128Size(-0x40fffffffLL));
+ EXPECT_EQ(6u, getSLEB128Size(-0x410000000LL));
+
+ EXPECT_EQ(6u, getSLEB128Size(-0x7ffffffffLL));
+ EXPECT_EQ(6u, getSLEB128Size(-0x800000000LL));
+ EXPECT_EQ(6u, getSLEB128Size(-0x1f800000000LL));
+ EXPECT_EQ(6u, getSLEB128Size(-0x20000000000LL));
+ EXPECT_EQ(7u, getSLEB128Size(-0x207ffffffffLL));
+ EXPECT_EQ(7u, getSLEB128Size(-0x20800000000LL));
+
+ EXPECT_EQ(7u, getSLEB128Size(-0x3ffffffffffLL));
+ EXPECT_EQ(7u, getSLEB128Size(-0x40000000000LL));
+ EXPECT_EQ(7u, getSLEB128Size(-0xfc0000000000LL));
+ EXPECT_EQ(7u, getSLEB128Size(-0x1000000000000LL));
+ EXPECT_EQ(8u, getSLEB128Size(-0x103ffffffffffLL));
+ EXPECT_EQ(8u, getSLEB128Size(-0x1040000000000LL));
+
+ EXPECT_EQ(8u, getSLEB128Size(-0x1ffffffffffffLL));
+ EXPECT_EQ(8u, getSLEB128Size(-0x2000000000000LL));
+ EXPECT_EQ(8u, getSLEB128Size(-0x7e000000000000LL));
+ EXPECT_EQ(8u, getSLEB128Size(-0x80000000000000LL));
+ EXPECT_EQ(9u, getSLEB128Size(-0x81ffffffffffffLL));
+ EXPECT_EQ(9u, getSLEB128Size(-0x82000000000000LL));
+
+ EXPECT_EQ(9u, getSLEB128Size(-0xffffffffffffffLL));
+ EXPECT_EQ(9u, getSLEB128Size(-0x100000000000000LL));
+ EXPECT_EQ(9u, getSLEB128Size(-0x3f00000000000000LL));
+ EXPECT_EQ(9u, getSLEB128Size(-0x4000000000000000LL));
+ EXPECT_EQ(10u, getSLEB128Size(-0x40ffffffffffffffLL));
+ EXPECT_EQ(10u, getSLEB128Size(-0x4100000000000000LL));
+
+ EXPECT_EQ(10u, getSLEB128Size(-0x7fffffffffffffffLL));
+ EXPECT_EQ(10u, getSLEB128Size(-0x8000000000000000LL));
+ EXPECT_EQ(10u, getSLEB128Size(INT64_MIN));
+}
+
+TEST(LEB128Test, ULEB128Size) {
+ // Testing Plan:
+ // (1) 128 ^ n ............ need (n+1) bytes
+ // (2) 128 ^ n * 64 ....... need (n+1) bytes
+ // (3) 128 ^ (n+1) - 1 .... need (n+1) bytes
+
+ EXPECT_EQ(1u, getULEB128Size(0)); // special case
+
+ EXPECT_EQ(1u, getULEB128Size(0x1ULL));
+ EXPECT_EQ(1u, getULEB128Size(0x40ULL));
+ EXPECT_EQ(1u, getULEB128Size(0x7fULL));
+
+ EXPECT_EQ(2u, getULEB128Size(0x80ULL));
+ EXPECT_EQ(2u, getULEB128Size(0x2000ULL));
+ EXPECT_EQ(2u, getULEB128Size(0x3fffULL));
+
+ EXPECT_EQ(3u, getULEB128Size(0x4000ULL));
+ EXPECT_EQ(3u, getULEB128Size(0x100000ULL));
+ EXPECT_EQ(3u, getULEB128Size(0x1fffffULL));
+
+ EXPECT_EQ(4u, getULEB128Size(0x200000ULL));
+ EXPECT_EQ(4u, getULEB128Size(0x8000000ULL));
+ EXPECT_EQ(4u, getULEB128Size(0xfffffffULL));
+
+ EXPECT_EQ(5u, getULEB128Size(0x10000000ULL));
+ EXPECT_EQ(5u, getULEB128Size(0x400000000ULL));
+ EXPECT_EQ(5u, getULEB128Size(0x7ffffffffULL));
+
+ EXPECT_EQ(6u, getULEB128Size(0x800000000ULL));
+ EXPECT_EQ(6u, getULEB128Size(0x20000000000ULL));
+ EXPECT_EQ(6u, getULEB128Size(0x3ffffffffffULL));
+
+ EXPECT_EQ(7u, getULEB128Size(0x40000000000ULL));
+ EXPECT_EQ(7u, getULEB128Size(0x1000000000000ULL));
+ EXPECT_EQ(7u, getULEB128Size(0x1ffffffffffffULL));
+
+ EXPECT_EQ(8u, getULEB128Size(0x2000000000000ULL));
+ EXPECT_EQ(8u, getULEB128Size(0x80000000000000ULL));
+ EXPECT_EQ(8u, getULEB128Size(0xffffffffffffffULL));
+
+ EXPECT_EQ(9u, getULEB128Size(0x100000000000000ULL));
+ EXPECT_EQ(9u, getULEB128Size(0x4000000000000000ULL));
+ EXPECT_EQ(9u, getULEB128Size(0x7fffffffffffffffULL));
+
+ EXPECT_EQ(10u, getULEB128Size(0x8000000000000000ULL));
+
+ EXPECT_EQ(10u, getULEB128Size(UINT64_MAX));
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/LineIteratorTest.cpp b/gnu/llvm/unittests/Support/LineIteratorTest.cpp
new file mode 100644
index 00000000000..67f9d977736
--- /dev/null
+++ b/gnu/llvm/unittests/Support/LineIteratorTest.cpp
@@ -0,0 +1,193 @@
+//===- LineIterator.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/Support/LineIterator.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::sys;
+
+namespace {
+
+TEST(LineIteratorTest, Basic) {
+ std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("line 1\n"
+ "line 2\n"
+ "line 3");
+
+ line_iterator I = line_iterator(*Buffer), E;
+
+ EXPECT_FALSE(I.is_at_eof());
+ EXPECT_NE(E, I);
+
+ EXPECT_EQ("line 1", *I);
+ EXPECT_EQ(1, I.line_number());
+ ++I;
+ EXPECT_EQ("line 2", *I);
+ EXPECT_EQ(2, I.line_number());
+ ++I;
+ EXPECT_EQ("line 3", *I);
+ EXPECT_EQ(3, I.line_number());
+ ++I;
+
+ EXPECT_TRUE(I.is_at_eof());
+ EXPECT_EQ(E, I);
+}
+
+TEST(LineIteratorTest, CommentAndBlankSkipping) {
+ std::unique_ptr<MemoryBuffer> Buffer(
+ MemoryBuffer::getMemBuffer("line 1\n"
+ "line 2\n"
+ "# Comment 1\n"
+ "\n"
+ "line 5\n"
+ "\n"
+ "# Comment 2"));
+
+ line_iterator I = line_iterator(*Buffer, true, '#'), E;
+
+ EXPECT_FALSE(I.is_at_eof());
+ EXPECT_NE(E, I);
+
+ EXPECT_EQ("line 1", *I);
+ EXPECT_EQ(1, I.line_number());
+ ++I;
+ EXPECT_EQ("line 2", *I);
+ EXPECT_EQ(2, I.line_number());
+ ++I;
+ EXPECT_EQ("line 5", *I);
+ EXPECT_EQ(5, I.line_number());
+ ++I;
+
+ EXPECT_TRUE(I.is_at_eof());
+ EXPECT_EQ(E, I);
+}
+
+TEST(LineIteratorTest, CommentSkippingKeepBlanks) {
+ std::unique_ptr<MemoryBuffer> Buffer(
+ MemoryBuffer::getMemBuffer("line 1\n"
+ "line 2\n"
+ "# Comment 1\n"
+ "# Comment 2\n"
+ "\n"
+ "line 6\n"
+ "\n"
+ "# Comment 3"));
+
+ line_iterator I = line_iterator(*Buffer, false, '#'), E;
+
+ EXPECT_FALSE(I.is_at_eof());
+ EXPECT_NE(E, I);
+
+ EXPECT_EQ("line 1", *I);
+ EXPECT_EQ(1, I.line_number());
+ ++I;
+ EXPECT_EQ("line 2", *I);
+ EXPECT_EQ(2, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(5, I.line_number());
+ ++I;
+ EXPECT_EQ("line 6", *I);
+ EXPECT_EQ(6, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(7, I.line_number());
+ ++I;
+
+ EXPECT_TRUE(I.is_at_eof());
+ EXPECT_EQ(E, I);
+}
+
+
+TEST(LineIteratorTest, BlankSkipping) {
+ std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n\n"
+ "line 1\n"
+ "\n\n\n"
+ "line 2\n"
+ "\n\n\n");
+
+ line_iterator I = line_iterator(*Buffer), E;
+
+ EXPECT_FALSE(I.is_at_eof());
+ EXPECT_NE(E, I);
+
+ EXPECT_EQ("line 1", *I);
+ EXPECT_EQ(4, I.line_number());
+ ++I;
+ EXPECT_EQ("line 2", *I);
+ EXPECT_EQ(8, I.line_number());
+ ++I;
+
+ EXPECT_TRUE(I.is_at_eof());
+ EXPECT_EQ(E, I);
+}
+
+TEST(LineIteratorTest, BlankKeeping) {
+ std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("\n\n"
+ "line 3\n"
+ "\n"
+ "line 5\n"
+ "\n\n");
+ line_iterator I = line_iterator(*Buffer, false), E;
+
+ EXPECT_FALSE(I.is_at_eof());
+ EXPECT_NE(E, I);
+
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(1, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(2, I.line_number());
+ ++I;
+ EXPECT_EQ("line 3", *I);
+ EXPECT_EQ(3, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(4, I.line_number());
+ ++I;
+ EXPECT_EQ("line 5", *I);
+ EXPECT_EQ(5, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(6, I.line_number());
+ ++I;
+ EXPECT_EQ("", *I);
+ EXPECT_EQ(7, I.line_number());
+ ++I;
+
+ EXPECT_TRUE(I.is_at_eof());
+ EXPECT_EQ(E, I);
+}
+
+TEST(LineIteratorTest, EmptyBuffers) {
+ std::unique_ptr<MemoryBuffer> Buffer = MemoryBuffer::getMemBuffer("");
+ EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());
+ EXPECT_EQ(line_iterator(), line_iterator(*Buffer));
+ EXPECT_TRUE(line_iterator(*Buffer, false).is_at_eof());
+ EXPECT_EQ(line_iterator(), line_iterator(*Buffer, false));
+
+ Buffer = MemoryBuffer::getMemBuffer("\n\n\n");
+ EXPECT_TRUE(line_iterator(*Buffer).is_at_eof());
+ EXPECT_EQ(line_iterator(), line_iterator(*Buffer));
+
+ Buffer = MemoryBuffer::getMemBuffer("# foo\n"
+ "\n"
+ "# bar");
+ EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof());
+ EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#'));
+
+ Buffer = MemoryBuffer::getMemBuffer("\n"
+ "# baz\n"
+ "\n");
+ EXPECT_TRUE(line_iterator(*Buffer, true, '#').is_at_eof());
+ EXPECT_EQ(line_iterator(), line_iterator(*Buffer, true, '#'));
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/LockFileManagerTest.cpp b/gnu/llvm/unittests/Support/LockFileManagerTest.cpp
new file mode 100644
index 00000000000..efe3c3088b3
--- /dev/null
+++ b/gnu/llvm/unittests/Support/LockFileManagerTest.cpp
@@ -0,0 +1,127 @@
+//===- unittests/LockFileManagerTest.cpp - LockFileManager tests ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LockFileManager.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+TEST(LockFileManagerTest, Basic) {
+ SmallString<64> TmpDir;
+ std::error_code EC;
+ EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
+ ASSERT_FALSE(EC);
+
+ SmallString<64> LockedFile(TmpDir);
+ sys::path::append(LockedFile, "file.lock");
+
+ {
+ // The lock file should not exist, so we should successfully acquire it.
+ LockFileManager Locked1(LockedFile);
+ EXPECT_EQ(LockFileManager::LFS_Owned, Locked1.getState());
+
+ // Attempting to reacquire the lock should fail. Waiting on it would cause
+ // deadlock, so don't try that.
+ LockFileManager Locked2(LockedFile);
+ EXPECT_NE(LockFileManager::LFS_Owned, Locked2.getState());
+ }
+
+ // Now that the lock is out of scope, the file should be gone.
+ EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile)));
+
+ EC = sys::fs::remove(StringRef(TmpDir));
+ ASSERT_FALSE(EC);
+}
+
+TEST(LockFileManagerTest, LinkLockExists) {
+ SmallString<64> TmpDir;
+ std::error_code EC;
+ EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
+ ASSERT_FALSE(EC);
+
+ SmallString<64> LockedFile(TmpDir);
+ sys::path::append(LockedFile, "file");
+
+ SmallString<64> FileLocK(TmpDir);
+ sys::path::append(FileLocK, "file.lock");
+
+ SmallString<64> TmpFileLock(TmpDir);
+ sys::path::append(TmpFileLock, "file.lock-000");
+
+ int FD;
+ EC = sys::fs::openFileForWrite(StringRef(TmpFileLock), FD, sys::fs::F_None);
+ ASSERT_FALSE(EC);
+
+ int Ret = close(FD);
+ ASSERT_EQ(Ret, 0);
+
+ EC = sys::fs::create_link(TmpFileLock.str(), FileLocK.str());
+ ASSERT_FALSE(EC);
+
+ EC = sys::fs::remove(StringRef(TmpFileLock));
+ ASSERT_FALSE(EC);
+
+ {
+ // The lock file doesn't point to a real file, so we should successfully
+ // acquire it.
+ LockFileManager Locked(LockedFile);
+ EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState());
+ }
+
+ // Now that the lock is out of scope, the file should be gone.
+ EXPECT_FALSE(sys::fs::exists(StringRef(LockedFile)));
+
+ EC = sys::fs::remove(StringRef(TmpDir));
+ ASSERT_FALSE(EC);
+}
+
+
+TEST(LockFileManagerTest, RelativePath) {
+ SmallString<64> TmpDir;
+ std::error_code EC;
+ EC = sys::fs::createUniqueDirectory("LockFileManagerTestDir", TmpDir);
+ ASSERT_FALSE(EC);
+
+ char PathBuf[1024];
+ const char *OrigPath = getcwd(PathBuf, 1024);
+ ASSERT_FALSE(chdir(TmpDir.c_str()));
+
+ sys::fs::create_directory("inner");
+ SmallString<64> LockedFile("inner");
+ sys::path::append(LockedFile, "file");
+
+ SmallString<64> FileLock(LockedFile);
+ FileLock += ".lock";
+
+ {
+ // The lock file should not exist, so we should successfully acquire it.
+ LockFileManager Locked(LockedFile);
+ EXPECT_EQ(LockFileManager::LFS_Owned, Locked.getState());
+ EXPECT_TRUE(sys::fs::exists(FileLock.str()));
+ }
+
+ // Now that the lock is out of scope, the file should be gone.
+ EXPECT_FALSE(sys::fs::exists(LockedFile.str()));
+ EXPECT_FALSE(sys::fs::exists(FileLock.str()));
+
+ EC = sys::fs::remove("inner");
+ ASSERT_FALSE(EC);
+
+ ASSERT_FALSE(chdir(OrigPath));
+
+ EC = sys::fs::remove(StringRef(TmpDir));
+ ASSERT_FALSE(EC);
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Support/MD5Test.cpp b/gnu/llvm/unittests/Support/MD5Test.cpp
new file mode 100644
index 00000000000..c4fa5cd92c1
--- /dev/null
+++ b/gnu/llvm/unittests/Support/MD5Test.cpp
@@ -0,0 +1,60 @@
+//===- llvm/unittest/Support/MD5Test.cpp - MD5 tests ----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements unit tests for the MD5 functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/MD5.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+/// \brief Tests an arbitrary set of bytes passed as \p Input.
+void TestMD5Sum(ArrayRef<uint8_t> Input, StringRef Final) {
+ MD5 Hash;
+ Hash.update(Input);
+ MD5::MD5Result MD5Res;
+ Hash.final(MD5Res);
+ SmallString<32> Res;
+ MD5::stringifyResult(MD5Res, Res);
+ EXPECT_EQ(Res, Final);
+}
+
+void TestMD5Sum(StringRef Input, StringRef Final) {
+ MD5 Hash;
+ Hash.update(Input);
+ MD5::MD5Result MD5Res;
+ Hash.final(MD5Res);
+ SmallString<32> Res;
+ MD5::stringifyResult(MD5Res, Res);
+ EXPECT_EQ(Res, Final);
+}
+
+TEST(MD5Test, MD5) {
+ TestMD5Sum(makeArrayRef((const uint8_t *)"", (size_t) 0),
+ "d41d8cd98f00b204e9800998ecf8427e");
+ TestMD5Sum(makeArrayRef((const uint8_t *)"a", (size_t) 1),
+ "0cc175b9c0f1b6a831c399e269772661");
+ TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz",
+ (size_t) 26),
+ "c3fcd3d76192e4007dfb496cca67e13b");
+ TestMD5Sum(makeArrayRef((const uint8_t *)"\0", (size_t) 1),
+ "93b885adfe0da089cdf634904fd59f71");
+ TestMD5Sum(makeArrayRef((const uint8_t *)"a\0", (size_t) 2),
+ "4144e195f46de78a3623da7364d04f11");
+ TestMD5Sum(makeArrayRef((const uint8_t *)"abcdefghijklmnopqrstuvwxyz\0",
+ (size_t) 27),
+ "81948d1f1554f58cd1a56ebb01f808cb");
+ TestMD5Sum("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b");
+}
+}
diff --git a/gnu/llvm/unittests/Support/Makefile b/gnu/llvm/unittests/Support/Makefile
new file mode 100644
index 00000000000..21657f12e3d
--- /dev/null
+++ b/gnu/llvm/unittests/Support/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Support/Makefile --------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+TESTNAME = Support
+LINK_COMPONENTS := all-targets core support
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Support/ManagedStatic.cpp b/gnu/llvm/unittests/Support/ManagedStatic.cpp
new file mode 100644
index 00000000000..153884ba429
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ManagedStatic.cpp
@@ -0,0 +1,60 @@
+//===- llvm/unittest/Support/ManagedStatic.cpp - ManagedStatic tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Threading.h"
+#ifdef HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+#if LLVM_ENABLE_THREADS != 0 && defined(HAVE_PTHREAD_H) && \
+ !__has_feature(memory_sanitizer)
+namespace test1 {
+ llvm::ManagedStatic<int> ms;
+ void *helper(void*) {
+ *ms;
+ return nullptr;
+ }
+
+ // Valgrind's leak checker complains glibc's stack allocation.
+ // To appease valgrind, we provide our own stack for each thread.
+ void *allocate_stack(pthread_attr_t &a, size_t n = 65536) {
+ void *stack = malloc(n);
+ pthread_attr_init(&a);
+#if defined(__linux__)
+ pthread_attr_setstack(&a, stack, n);
+#endif
+ return stack;
+ }
+}
+
+TEST(Initialize, MultipleThreads) {
+ // Run this test under tsan: http://code.google.com/p/data-race-test/
+
+ pthread_attr_t a1, a2;
+ void *p1 = test1::allocate_stack(a1);
+ void *p2 = test1::allocate_stack(a2);
+
+ pthread_t t1, t2;
+ pthread_create(&t1, &a1, test1::helper, nullptr);
+ pthread_create(&t2, &a2, test1::helper, nullptr);
+ pthread_join(t1, nullptr);
+ pthread_join(t2, nullptr);
+ free(p1);
+ free(p2);
+}
+#endif
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/MathExtrasTest.cpp b/gnu/llvm/unittests/Support/MathExtrasTest.cpp
new file mode 100644
index 00000000000..97309f8d31f
--- /dev/null
+++ b/gnu/llvm/unittests/Support/MathExtrasTest.cpp
@@ -0,0 +1,361 @@
+//===- unittests/Support/MathExtrasTest.cpp - math utils tests ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(MathExtras, countTrailingZeros) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(8u, countTrailingZeros(Z8));
+ EXPECT_EQ(16u, countTrailingZeros(Z16));
+ EXPECT_EQ(32u, countTrailingZeros(Z32));
+ EXPECT_EQ(64u, countTrailingZeros(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(1u, countTrailingZeros(NZ8));
+ EXPECT_EQ(1u, countTrailingZeros(NZ16));
+ EXPECT_EQ(1u, countTrailingZeros(NZ32));
+ EXPECT_EQ(1u, countTrailingZeros(NZ64));
+}
+
+TEST(MathExtras, countLeadingZeros) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(8u, countLeadingZeros(Z8));
+ EXPECT_EQ(16u, countLeadingZeros(Z16));
+ EXPECT_EQ(32u, countLeadingZeros(Z32));
+ EXPECT_EQ(64u, countLeadingZeros(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(2u, countLeadingZeros(NZ8));
+ EXPECT_EQ(10u, countLeadingZeros(NZ16));
+ EXPECT_EQ(26u, countLeadingZeros(NZ32));
+ EXPECT_EQ(58u, countLeadingZeros(NZ64));
+
+ EXPECT_EQ(8u, countLeadingZeros(0x00F000FFu));
+ EXPECT_EQ(8u, countLeadingZeros(0x00F12345u));
+ for (unsigned i = 0; i <= 30; ++i) {
+ EXPECT_EQ(31 - i, countLeadingZeros(1u << i));
+ }
+
+ EXPECT_EQ(8u, countLeadingZeros(0x00F1234500F12345ULL));
+ EXPECT_EQ(1u, countLeadingZeros(1ULL << 62));
+ for (unsigned i = 0; i <= 62; ++i) {
+ EXPECT_EQ(63 - i, countLeadingZeros(1ULL << i));
+ }
+}
+
+TEST(MathExtras, findFirstSet) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(0xFFULL, findFirstSet(Z8));
+ EXPECT_EQ(0xFFFFULL, findFirstSet(Z16));
+ EXPECT_EQ(0xFFFFFFFFULL, findFirstSet(Z32));
+ EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findFirstSet(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(1u, findFirstSet(NZ8));
+ EXPECT_EQ(1u, findFirstSet(NZ16));
+ EXPECT_EQ(1u, findFirstSet(NZ32));
+ EXPECT_EQ(1u, findFirstSet(NZ64));
+}
+
+TEST(MathExtras, findLastSet) {
+ uint8_t Z8 = 0;
+ uint16_t Z16 = 0;
+ uint32_t Z32 = 0;
+ uint64_t Z64 = 0;
+ EXPECT_EQ(0xFFULL, findLastSet(Z8));
+ EXPECT_EQ(0xFFFFULL, findLastSet(Z16));
+ EXPECT_EQ(0xFFFFFFFFULL, findLastSet(Z32));
+ EXPECT_EQ(0xFFFFFFFFFFFFFFFFULL, findLastSet(Z64));
+
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(5u, findLastSet(NZ8));
+ EXPECT_EQ(5u, findLastSet(NZ16));
+ EXPECT_EQ(5u, findLastSet(NZ32));
+ EXPECT_EQ(5u, findLastSet(NZ64));
+}
+
+TEST(MathExtras, reverseBits) {
+ uint8_t NZ8 = 42;
+ uint16_t NZ16 = 42;
+ uint32_t NZ32 = 42;
+ uint64_t NZ64 = 42;
+ EXPECT_EQ(0x54ULL, reverseBits(NZ8));
+ EXPECT_EQ(0x5400ULL, reverseBits(NZ16));
+ EXPECT_EQ(0x54000000ULL, reverseBits(NZ32));
+ EXPECT_EQ(0x5400000000000000ULL, reverseBits(NZ64));
+}
+
+TEST(MathExtras, isPowerOf2_32) {
+ EXPECT_TRUE(isPowerOf2_32(1 << 6));
+ EXPECT_TRUE(isPowerOf2_32(1 << 12));
+ EXPECT_FALSE(isPowerOf2_32((1 << 19) + 3));
+ EXPECT_FALSE(isPowerOf2_32(0xABCDEF0));
+}
+
+TEST(MathExtras, isPowerOf2_64) {
+ EXPECT_TRUE(isPowerOf2_64(1LL << 46));
+ EXPECT_TRUE(isPowerOf2_64(1LL << 12));
+ EXPECT_FALSE(isPowerOf2_64((1LL << 53) + 3));
+ EXPECT_FALSE(isPowerOf2_64(0xABCDEF0ABCDEF0LL));
+}
+
+TEST(MathExtras, ByteSwap_32) {
+ EXPECT_EQ(0x44332211u, ByteSwap_32(0x11223344));
+ EXPECT_EQ(0xDDCCBBAAu, ByteSwap_32(0xAABBCCDD));
+}
+
+TEST(MathExtras, ByteSwap_64) {
+ EXPECT_EQ(0x8877665544332211ULL, ByteSwap_64(0x1122334455667788LL));
+ EXPECT_EQ(0x1100FFEEDDCCBBAAULL, ByteSwap_64(0xAABBCCDDEEFF0011LL));
+}
+
+TEST(MathExtras, countLeadingOnes) {
+ for (int i = 30; i >= 0; --i) {
+ // Start with all ones and unset some bit.
+ EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i)));
+ }
+ for (int i = 62; i >= 0; --i) {
+ // Start with all ones and unset some bit.
+ EXPECT_EQ(63u - i, countLeadingOnes(0xFFFFFFFFFFFFFFFFULL ^ (1LL << i)));
+ }
+ for (int i = 30; i >= 0; --i) {
+ // Start with all ones and unset some bit.
+ EXPECT_EQ(31u - i, countLeadingOnes(0xFFFFFFFF ^ (1 << i)));
+ }
+}
+
+TEST(MathExtras, FloatBits) {
+ static const float kValue = 5632.34f;
+ EXPECT_FLOAT_EQ(kValue, BitsToFloat(FloatToBits(kValue)));
+}
+
+TEST(MathExtras, DoubleBits) {
+ static const double kValue = 87987234.983498;
+ EXPECT_FLOAT_EQ(kValue, BitsToDouble(DoubleToBits(kValue)));
+}
+
+TEST(MathExtras, MinAlign) {
+ EXPECT_EQ(1u, MinAlign(2, 3));
+ EXPECT_EQ(2u, MinAlign(2, 4));
+ EXPECT_EQ(1u, MinAlign(17, 64));
+ EXPECT_EQ(256u, MinAlign(256, 512));
+}
+
+TEST(MathExtras, NextPowerOf2) {
+ EXPECT_EQ(4u, NextPowerOf2(3));
+ EXPECT_EQ(16u, NextPowerOf2(15));
+ EXPECT_EQ(256u, NextPowerOf2(128));
+}
+
+TEST(MathExtras, RoundUpToAlignment) {
+ EXPECT_EQ(8u, RoundUpToAlignment(5, 8));
+ EXPECT_EQ(24u, RoundUpToAlignment(17, 8));
+ EXPECT_EQ(0u, RoundUpToAlignment(~0LL, 8));
+
+ EXPECT_EQ(7u, RoundUpToAlignment(5, 8, 7));
+ EXPECT_EQ(17u, RoundUpToAlignment(17, 8, 1));
+ EXPECT_EQ(3u, RoundUpToAlignment(~0LL, 8, 3));
+ EXPECT_EQ(552u, RoundUpToAlignment(321, 255, 42));
+}
+
+template<typename T>
+void SaturatingAddTestHelper()
+{
+ const T Max = std::numeric_limits<T>::max();
+ bool ResultOverflowed;
+
+ EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2)));
+ EXPECT_EQ(T(3), SaturatingAdd(T(1), T(2), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingAdd(Max, T(1)));
+ EXPECT_EQ(Max, SaturatingAdd(Max, T(1), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1)));
+ EXPECT_EQ(Max, SaturatingAdd(T(1), T(Max - 1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingAdd(T(1), Max));
+ EXPECT_EQ(Max, SaturatingAdd(T(1), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingAdd(Max, Max));
+ EXPECT_EQ(Max, SaturatingAdd(Max, Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+}
+
+TEST(MathExtras, SaturatingAdd) {
+ SaturatingAddTestHelper<uint8_t>();
+ SaturatingAddTestHelper<uint16_t>();
+ SaturatingAddTestHelper<uint32_t>();
+ SaturatingAddTestHelper<uint64_t>();
+}
+
+template<typename T>
+void SaturatingMultiplyTestHelper()
+{
+ const T Max = std::numeric_limits<T>::max();
+ bool ResultOverflowed;
+
+ // Test basic multiplication.
+ EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3)));
+ EXPECT_EQ(T(6), SaturatingMultiply(T(2), T(3), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2)));
+ EXPECT_EQ(T(6), SaturatingMultiply(T(3), T(2), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ // Test multiplication by zero.
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0)));
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0)));
+ EXPECT_EQ(T(0), SaturatingMultiply(T(1), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1)));
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), T(1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0)));
+ EXPECT_EQ(T(0), SaturatingMultiply(Max, T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max));
+ EXPECT_EQ(T(0), SaturatingMultiply(T(0), Max, &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ // Test multiplication by maximum value.
+ EXPECT_EQ(Max, SaturatingMultiply(Max, T(2)));
+ EXPECT_EQ(Max, SaturatingMultiply(Max, T(2), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiply(T(2), Max));
+ EXPECT_EQ(Max, SaturatingMultiply(T(2), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiply(Max, Max));
+ EXPECT_EQ(Max, SaturatingMultiply(Max, Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test interesting boundary conditions for algorithm -
+ // ((1 << A) - 1) * ((1 << B) + K) for K in [-1, 0, 1]
+ // and A + B == std::numeric_limits<T>::digits.
+ // We expect overflow iff A > B and K = 1.
+ const int Digits = std::numeric_limits<T>::digits;
+ for (int A = 1, B = Digits - 1; B >= 1; ++A, --B) {
+ for (int K = -1; K <= 1; ++K) {
+ T X = (T(1) << A) - T(1);
+ T Y = (T(1) << B) + K;
+ bool OverflowExpected = A > B && K == 1;
+
+ if(OverflowExpected) {
+ EXPECT_EQ(Max, SaturatingMultiply(X, Y));
+ EXPECT_EQ(Max, SaturatingMultiply(X, Y, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+ } else {
+ EXPECT_EQ(X * Y, SaturatingMultiply(X, Y));
+ EXPECT_EQ(X * Y, SaturatingMultiply(X, Y, &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+ }
+ }
+ }
+}
+
+TEST(MathExtras, SaturatingMultiply) {
+ SaturatingMultiplyTestHelper<uint8_t>();
+ SaturatingMultiplyTestHelper<uint16_t>();
+ SaturatingMultiplyTestHelper<uint32_t>();
+ SaturatingMultiplyTestHelper<uint64_t>();
+}
+
+template<typename T>
+void SaturatingMultiplyAddTestHelper()
+{
+ const T Max = std::numeric_limits<T>::max();
+ bool ResultOverflowed;
+
+ // Test basic multiply-add.
+ EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10)));
+ EXPECT_EQ(T(16), SaturatingMultiplyAdd(T(2), T(3), T(10), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ // Test multiply overflows, add doesn't overflow
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(0), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply doesn't overflow, add overflows
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply-add with Max as operand
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), T(1), Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(T(1), Max, T(1), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, T(1), &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ EXPECT_EQ(Max, SaturatingMultiplyAdd(Max, Max, Max, &ResultOverflowed));
+ EXPECT_TRUE(ResultOverflowed);
+
+ // Test multiply-add with 0 as operand
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(1), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(1), T(0), T(1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(1), SaturatingMultiplyAdd(T(0), T(0), T(1), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+ EXPECT_EQ(T(0), SaturatingMultiplyAdd(T(0), T(0), T(0), &ResultOverflowed));
+ EXPECT_FALSE(ResultOverflowed);
+
+}
+
+TEST(MathExtras, SaturatingMultiplyAdd) {
+ SaturatingMultiplyAddTestHelper<uint8_t>();
+ SaturatingMultiplyAddTestHelper<uint16_t>();
+ SaturatingMultiplyAddTestHelper<uint32_t>();
+ SaturatingMultiplyAddTestHelper<uint64_t>();
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/MemoryBufferTest.cpp b/gnu/llvm/unittests/Support/MemoryBufferTest.cpp
new file mode 100644
index 00000000000..963dcd91c8b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/MemoryBufferTest.cpp
@@ -0,0 +1,225 @@
+//===- llvm/unittest/Support/MemoryBufferTest.cpp - MemoryBuffer tests ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements unit tests for the MemoryBuffer support class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class MemoryBufferTest : public testing::Test {
+protected:
+ MemoryBufferTest()
+ : data("this is some data")
+ { }
+
+ void SetUp() override {}
+
+ /// Common testing for different modes of getOpenFileSlice.
+ /// Creates a temporary file with known contents, and uses
+ /// MemoryBuffer::getOpenFileSlice to map it.
+ /// If \p Reopen is true, the file is closed after creating and reopened
+ /// anew before using MemoryBuffer.
+ void testGetOpenFileSlice(bool Reopen);
+
+ typedef std::unique_ptr<MemoryBuffer> OwningBuffer;
+
+ std::string data;
+};
+
+TEST_F(MemoryBufferTest, get) {
+ // Default name and null-terminator flag
+ OwningBuffer MB1(MemoryBuffer::getMemBuffer(data));
+ EXPECT_TRUE(nullptr != MB1.get());
+
+ // RequiresNullTerminator = false
+ OwningBuffer MB2(MemoryBuffer::getMemBuffer(data, "one", false));
+ EXPECT_TRUE(nullptr != MB2.get());
+
+ // RequiresNullTerminator = true
+ OwningBuffer MB3(MemoryBuffer::getMemBuffer(data, "two", true));
+ EXPECT_TRUE(nullptr != MB3.get());
+
+ // verify all 3 buffers point to the same address
+ EXPECT_EQ(MB1->getBufferStart(), MB2->getBufferStart());
+ EXPECT_EQ(MB2->getBufferStart(), MB3->getBufferStart());
+
+ // verify the original data is unmodified after deleting the buffers
+ MB1.reset();
+ MB2.reset();
+ MB3.reset();
+ EXPECT_EQ("this is some data", data);
+}
+
+TEST_F(MemoryBufferTest, NullTerminator4K) {
+ // Test that a file with size that is a multiple of the page size can be null
+ // terminated correctly by MemoryBuffer.
+ int TestFD;
+ SmallString<64> TestPath;
+ sys::fs::createTemporaryFile("MemoryBufferTest_NullTerminator4K", "temp",
+ TestFD, TestPath);
+ raw_fd_ostream OF(TestFD, true, /*unbuffered=*/true);
+ for (unsigned i = 0; i < 4096 / 16; ++i) {
+ OF << "0123456789abcdef";
+ }
+ OF.close();
+
+ ErrorOr<OwningBuffer> MB = MemoryBuffer::getFile(TestPath.c_str());
+ std::error_code EC = MB.getError();
+ ASSERT_FALSE(EC);
+
+ const char *BufData = MB.get()->getBufferStart();
+ EXPECT_EQ('f', BufData[4095]);
+ EXPECT_EQ('\0', BufData[4096]);
+}
+
+TEST_F(MemoryBufferTest, copy) {
+ // copy with no name
+ OwningBuffer MBC1(MemoryBuffer::getMemBufferCopy(data));
+ EXPECT_TRUE(nullptr != MBC1.get());
+
+ // copy with a name
+ OwningBuffer MBC2(MemoryBuffer::getMemBufferCopy(data, "copy"));
+ EXPECT_TRUE(nullptr != MBC2.get());
+
+ // verify the two copies do not point to the same place
+ EXPECT_NE(MBC1->getBufferStart(), MBC2->getBufferStart());
+}
+
+TEST_F(MemoryBufferTest, make_new) {
+ // 0-sized buffer
+ OwningBuffer Zero(MemoryBuffer::getNewUninitMemBuffer(0));
+ EXPECT_TRUE(nullptr != Zero.get());
+
+ // uninitialized buffer with no name
+ OwningBuffer One(MemoryBuffer::getNewUninitMemBuffer(321));
+ EXPECT_TRUE(nullptr != One.get());
+
+ // uninitialized buffer with name
+ OwningBuffer Two(MemoryBuffer::getNewUninitMemBuffer(123, "bla"));
+ EXPECT_TRUE(nullptr != Two.get());
+
+ // 0-initialized buffer with no name
+ OwningBuffer Three(MemoryBuffer::getNewMemBuffer(321, data));
+ EXPECT_TRUE(nullptr != Three.get());
+ for (size_t i = 0; i < 321; ++i)
+ EXPECT_EQ(0, Three->getBufferStart()[0]);
+
+ // 0-initialized buffer with name
+ OwningBuffer Four(MemoryBuffer::getNewMemBuffer(123, "zeros"));
+ EXPECT_TRUE(nullptr != Four.get());
+ for (size_t i = 0; i < 123; ++i)
+ EXPECT_EQ(0, Four->getBufferStart()[0]);
+}
+
+void MemoryBufferTest::testGetOpenFileSlice(bool Reopen) {
+ // Test that MemoryBuffer::getOpenFile works properly when no null
+ // terminator is requested and the size is large enough to trigger
+ // the usage of memory mapping.
+ int TestFD;
+ SmallString<64> TestPath;
+ // Create a temporary file and write data into it.
+ sys::fs::createTemporaryFile("prefix", "temp", TestFD, TestPath);
+ // OF is responsible for closing the file; If the file is not
+ // reopened, it will be unbuffered so that the results are
+ // immediately visible through the fd.
+ raw_fd_ostream OF(TestFD, true, !Reopen);
+ for (int i = 0; i < 60000; ++i) {
+ OF << "0123456789";
+ }
+
+ if (Reopen) {
+ OF.close();
+ EXPECT_FALSE(sys::fs::openFileForRead(TestPath.c_str(), TestFD));
+ }
+
+ ErrorOr<OwningBuffer> Buf =
+ MemoryBuffer::getOpenFileSlice(TestFD, TestPath.c_str(),
+ 40000, // Size
+ 80000 // Offset
+ );
+
+ std::error_code EC = Buf.getError();
+ EXPECT_FALSE(EC);
+
+ StringRef BufData = Buf.get()->getBuffer();
+ EXPECT_EQ(BufData.size(), 40000U);
+ EXPECT_EQ(BufData[0], '0');
+ EXPECT_EQ(BufData[9], '9');
+}
+
+TEST_F(MemoryBufferTest, getOpenFileNoReopen) {
+ testGetOpenFileSlice(false);
+}
+
+TEST_F(MemoryBufferTest, getOpenFileReopened) {
+ testGetOpenFileSlice(true);
+}
+
+TEST_F(MemoryBufferTest, reference) {
+ OwningBuffer MB(MemoryBuffer::getMemBuffer(data));
+ MemoryBufferRef MBR(*MB);
+
+ EXPECT_EQ(MB->getBufferStart(), MBR.getBufferStart());
+ EXPECT_EQ(MB->getBufferIdentifier(), MBR.getBufferIdentifier());
+}
+
+TEST_F(MemoryBufferTest, slice) {
+ // Create a file that is six pages long with different data on each page.
+ int FD;
+ SmallString<64> TestPath;
+ sys::fs::createTemporaryFile("MemoryBufferTest_Slice", "temp", FD, TestPath);
+ raw_fd_ostream OF(FD, true, /*unbuffered=*/true);
+ for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+ OF << "12345678";
+ }
+ for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+ OF << "abcdefgh";
+ }
+ for (unsigned i = 0; i < 0x2000 / 8; ++i) {
+ OF << "ABCDEFGH";
+ }
+ OF.close();
+
+ // Try offset of one page.
+ ErrorOr<OwningBuffer> MB = MemoryBuffer::getFileSlice(TestPath.str(),
+ 0x4000, 0x1000);
+ std::error_code EC = MB.getError();
+ ASSERT_FALSE(EC);
+ EXPECT_EQ(0x4000UL, MB.get()->getBufferSize());
+
+ StringRef BufData = MB.get()->getBuffer();
+ EXPECT_TRUE(BufData.substr(0x0000,8).equals("12345678"));
+ EXPECT_TRUE(BufData.substr(0x0FF8,8).equals("12345678"));
+ EXPECT_TRUE(BufData.substr(0x1000,8).equals("abcdefgh"));
+ EXPECT_TRUE(BufData.substr(0x2FF8,8).equals("abcdefgh"));
+ EXPECT_TRUE(BufData.substr(0x3000,8).equals("ABCDEFGH"));
+ EXPECT_TRUE(BufData.substr(0x3FF8,8).equals("ABCDEFGH"));
+
+ // Try non-page aligned.
+ ErrorOr<OwningBuffer> MB2 = MemoryBuffer::getFileSlice(TestPath.str(),
+ 0x3000, 0x0800);
+ EC = MB2.getError();
+ ASSERT_FALSE(EC);
+ EXPECT_EQ(0x3000UL, MB2.get()->getBufferSize());
+
+ StringRef BufData2 = MB2.get()->getBuffer();
+ EXPECT_TRUE(BufData2.substr(0x0000,8).equals("12345678"));
+ EXPECT_TRUE(BufData2.substr(0x17F8,8).equals("12345678"));
+ EXPECT_TRUE(BufData2.substr(0x1800,8).equals("abcdefgh"));
+ EXPECT_TRUE(BufData2.substr(0x2FF8,8).equals("abcdefgh"));
+}
+}
diff --git a/gnu/llvm/unittests/Support/MemoryTest.cpp b/gnu/llvm/unittests/Support/MemoryTest.cpp
new file mode 100644
index 00000000000..f439cb2af9b
--- /dev/null
+++ b/gnu/llvm/unittests/Support/MemoryTest.cpp
@@ -0,0 +1,365 @@
+//===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/Process.h"
+#include "gtest/gtest.h"
+#include <cstdlib>
+
+using namespace llvm;
+using namespace sys;
+
+namespace {
+
+class MappedMemoryTest : public ::testing::TestWithParam<unsigned> {
+public:
+ MappedMemoryTest() {
+ Flags = GetParam();
+ PageSize = sys::Process::getPageSize();
+ }
+
+protected:
+ // Adds RW flags to permit testing of the resulting memory
+ unsigned getTestableEquivalent(unsigned RequestedFlags) {
+ switch (RequestedFlags) {
+ case Memory::MF_READ:
+ case Memory::MF_WRITE:
+ case Memory::MF_READ|Memory::MF_WRITE:
+ return Memory::MF_READ|Memory::MF_WRITE;
+ case Memory::MF_READ|Memory::MF_EXEC:
+ case Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC:
+ case Memory::MF_EXEC:
+ return Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC;
+ }
+ // Default in case values are added to the enum, as required by some compilers
+ return Memory::MF_READ|Memory::MF_WRITE;
+ }
+
+ // Returns true if the memory blocks overlap
+ bool doesOverlap(MemoryBlock M1, MemoryBlock M2) {
+ if (M1.base() == M2.base())
+ return true;
+
+ if (M1.base() > M2.base())
+ return (unsigned char *)M2.base() + M2.size() > M1.base();
+
+ return (unsigned char *)M1.base() + M1.size() > M2.base();
+ }
+
+ unsigned Flags;
+ size_t PageSize;
+};
+
+TEST_P(MappedMemoryTest, AllocAndRelease) {
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(sizeof(int), M1.size());
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+}
+
+TEST_P(MappedMemoryTest, MultipleAllocAndRelease) {
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(64, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(32, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(16U, M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(64U, M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(32U, M3.size());
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ EXPECT_NE((void*)nullptr, M4.base());
+ EXPECT_LE(16U, M4.size());
+ EXPECT_FALSE(Memory::releaseMappedMemory(M4));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, BasicWrite) {
+ // This test applies only to readable and writeable combinations
+ if (Flags &&
+ !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
+ return;
+
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(sizeof(int), M1.size());
+
+ int *a = (int*)M1.base();
+ *a = 1;
+ EXPECT_EQ(1, *a);
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+}
+
+TEST_P(MappedMemoryTest, MultipleWrite) {
+ // This test applies only to readable and writeable combinations
+ if (Flags &&
+ !((Flags & Memory::MF_READ) && (Flags & Memory::MF_WRITE)))
+ return;
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(1U * sizeof(int), M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(8U * sizeof(int), M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(4U * sizeof(int), M3.size());
+
+ int *x = (int*)M1.base();
+ *x = 1;
+
+ int *y = (int*)M2.base();
+ for (int i = 0; i < 8; i++) {
+ y[i] = i;
+ }
+
+ int *z = (int*)M3.base();
+ *z = 42;
+
+ EXPECT_EQ(1, *x);
+ EXPECT_EQ(7, y[7]);
+ EXPECT_EQ(42, *z);
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+
+ MemoryBlock M4 = Memory::allocateMappedMemory(64 * sizeof(int), nullptr,
+ Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ EXPECT_NE((void*)nullptr, M4.base());
+ EXPECT_LE(64U * sizeof(int), M4.size());
+ x = (int*)M4.base();
+ *x = 4;
+ EXPECT_EQ(4, *x);
+ EXPECT_FALSE(Memory::releaseMappedMemory(M4));
+
+ // Verify that M2 remains unaffected by other activity
+ for (int i = 0; i < 8; i++) {
+ EXPECT_EQ(i, y[i]);
+ }
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, EnabledWrite) {
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(2 * sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(8 * sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(4 * sizeof(int), nullptr, Flags,
+ EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(2U * sizeof(int), M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(8U * sizeof(int), M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(4U * sizeof(int), M3.size());
+
+ EXPECT_FALSE(Memory::protectMappedMemory(M1, getTestableEquivalent(Flags)));
+ EXPECT_FALSE(Memory::protectMappedMemory(M2, getTestableEquivalent(Flags)));
+ EXPECT_FALSE(Memory::protectMappedMemory(M3, getTestableEquivalent(Flags)));
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ int *x = (int*)M1.base();
+ *x = 1;
+ int *y = (int*)M2.base();
+ for (unsigned int i = 0; i < 8; i++) {
+ y[i] = i;
+ }
+ int *z = (int*)M3.base();
+ *z = 42;
+
+ EXPECT_EQ(1, *x);
+ EXPECT_EQ(7, y[7]);
+ EXPECT_EQ(42, *z);
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ EXPECT_EQ(6, y[6]);
+
+ MemoryBlock M4 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ EXPECT_NE((void*)nullptr, M4.base());
+ EXPECT_LE(16U, M4.size());
+ EXPECT_EQ(std::error_code(),
+ Memory::protectMappedMemory(M4, getTestableEquivalent(Flags)));
+ x = (int*)M4.base();
+ *x = 4;
+ EXPECT_EQ(4, *x);
+ EXPECT_FALSE(Memory::releaseMappedMemory(M4));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, SuccessiveNear) {
+ std::error_code EC;
+ MemoryBlock M1 = Memory::allocateMappedMemory(16, nullptr, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(64, &M1, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(32, &M2, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(16U, M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(64U, M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(32U, M3.size());
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, DuplicateNear) {
+ std::error_code EC;
+ MemoryBlock Near((void*)(3*PageSize), 16);
+ MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(16U, M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(64U, M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(32U, M3.size());
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, ZeroNear) {
+ std::error_code EC;
+ MemoryBlock Near(nullptr, 0);
+ MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(16U, M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(64U, M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(32U, M3.size());
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, ZeroSizeNear) {
+ std::error_code EC;
+ MemoryBlock Near((void*)(4*PageSize), 0);
+ MemoryBlock M1 = Memory::allocateMappedMemory(16, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M2 = Memory::allocateMappedMemory(64, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+ MemoryBlock M3 = Memory::allocateMappedMemory(32, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(16U, M1.size());
+ EXPECT_NE((void*)nullptr, M2.base());
+ EXPECT_LE(64U, M2.size());
+ EXPECT_NE((void*)nullptr, M3.base());
+ EXPECT_LE(32U, M3.size());
+
+ EXPECT_FALSE(doesOverlap(M1, M2));
+ EXPECT_FALSE(doesOverlap(M2, M3));
+ EXPECT_FALSE(doesOverlap(M1, M3));
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M3));
+ EXPECT_FALSE(Memory::releaseMappedMemory(M2));
+}
+
+TEST_P(MappedMemoryTest, UnalignedNear) {
+ std::error_code EC;
+ MemoryBlock Near((void*)(2*PageSize+5), 0);
+ MemoryBlock M1 = Memory::allocateMappedMemory(15, &Near, Flags, EC);
+ EXPECT_EQ(std::error_code(), EC);
+
+ EXPECT_NE((void*)nullptr, M1.base());
+ EXPECT_LE(sizeof(int), M1.size());
+
+ EXPECT_FALSE(Memory::releaseMappedMemory(M1));
+}
+
+// Note that Memory::MF_WRITE is not supported exclusively across
+// operating systems and architectures and can imply MF_READ|MF_WRITE
+unsigned MemoryFlags[] = {
+ Memory::MF_READ,
+ Memory::MF_WRITE,
+ Memory::MF_READ|Memory::MF_WRITE,
+ Memory::MF_EXEC,
+ Memory::MF_READ|Memory::MF_EXEC,
+ Memory::MF_READ|Memory::MF_WRITE|Memory::MF_EXEC
+ };
+
+INSTANTIATE_TEST_CASE_P(AllocationTests,
+ MappedMemoryTest,
+ ::testing::ValuesIn(MemoryFlags));
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/Path.cpp b/gnu/llvm/unittests/Support/Path.cpp
new file mode 100644
index 00000000000..3f626f87888
--- /dev/null
+++ b/gnu/llvm/unittests/Support/Path.cpp
@@ -0,0 +1,950 @@
+//===- llvm/unittest/Support/Path.cpp - Path tests ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Path.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+#ifdef LLVM_ON_WIN32
+#include <windows.h>
+#include <winerror.h>
+#endif
+
+#ifdef LLVM_ON_UNIX
+#include <sys/stat.h>
+#endif
+
+using namespace llvm;
+using namespace llvm::sys;
+
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+
+namespace {
+
+TEST(is_separator, Works) {
+ EXPECT_TRUE(path::is_separator('/'));
+ EXPECT_FALSE(path::is_separator('\0'));
+ EXPECT_FALSE(path::is_separator('-'));
+ EXPECT_FALSE(path::is_separator(' '));
+
+#ifdef LLVM_ON_WIN32
+ EXPECT_TRUE(path::is_separator('\\'));
+#else
+ EXPECT_FALSE(path::is_separator('\\'));
+#endif
+}
+
+TEST(Support, Path) {
+ SmallVector<StringRef, 40> paths;
+ paths.push_back("");
+ paths.push_back(".");
+ paths.push_back("..");
+ paths.push_back("foo");
+ paths.push_back("/");
+ paths.push_back("/foo");
+ paths.push_back("foo/");
+ paths.push_back("/foo/");
+ paths.push_back("foo/bar");
+ paths.push_back("/foo/bar");
+ paths.push_back("//net");
+ paths.push_back("//net/foo");
+ paths.push_back("///foo///");
+ paths.push_back("///foo///bar");
+ paths.push_back("/.");
+ paths.push_back("./");
+ paths.push_back("/..");
+ paths.push_back("../");
+ paths.push_back("foo/.");
+ paths.push_back("foo/..");
+ paths.push_back("foo/./");
+ paths.push_back("foo/./bar");
+ paths.push_back("foo/..");
+ paths.push_back("foo/../");
+ paths.push_back("foo/../bar");
+ paths.push_back("c:");
+ paths.push_back("c:/");
+ paths.push_back("c:foo");
+ paths.push_back("c:/foo");
+ paths.push_back("c:foo/");
+ paths.push_back("c:/foo/");
+ paths.push_back("c:/foo/bar");
+ paths.push_back("prn:");
+ paths.push_back("c:\\");
+ paths.push_back("c:foo");
+ paths.push_back("c:\\foo");
+ paths.push_back("c:foo\\");
+ paths.push_back("c:\\foo\\");
+ paths.push_back("c:\\foo/");
+ paths.push_back("c:/foo\\bar");
+
+ SmallVector<StringRef, 5> ComponentStack;
+ for (SmallVector<StringRef, 40>::const_iterator i = paths.begin(),
+ e = paths.end();
+ i != e;
+ ++i) {
+ for (sys::path::const_iterator ci = sys::path::begin(*i),
+ ce = sys::path::end(*i);
+ ci != ce;
+ ++ci) {
+ ASSERT_FALSE(ci->empty());
+ ComponentStack.push_back(*ci);
+ }
+
+ for (sys::path::reverse_iterator ci = sys::path::rbegin(*i),
+ ce = sys::path::rend(*i);
+ ci != ce;
+ ++ci) {
+ ASSERT_TRUE(*ci == ComponentStack.back());
+ ComponentStack.pop_back();
+ }
+ ASSERT_TRUE(ComponentStack.empty());
+
+ path::has_root_path(*i);
+ path::root_path(*i);
+ path::has_root_name(*i);
+ path::root_name(*i);
+ path::has_root_directory(*i);
+ path::root_directory(*i);
+ path::has_parent_path(*i);
+ path::parent_path(*i);
+ path::has_filename(*i);
+ path::filename(*i);
+ path::has_stem(*i);
+ path::stem(*i);
+ path::has_extension(*i);
+ path::extension(*i);
+ path::is_absolute(*i);
+ path::is_relative(*i);
+
+ SmallString<128> temp_store;
+ temp_store = *i;
+ ASSERT_NO_ERROR(fs::make_absolute(temp_store));
+ temp_store = *i;
+ path::remove_filename(temp_store);
+
+ temp_store = *i;
+ path::replace_extension(temp_store, "ext");
+ StringRef filename(temp_store.begin(), temp_store.size()), stem, ext;
+ stem = path::stem(filename);
+ ext = path::extension(filename);
+ EXPECT_EQ(*sys::path::rbegin(filename), (stem + ext).str());
+
+ path::native(*i, temp_store);
+ }
+
+ SmallString<32> Relative("foo.cpp");
+ ASSERT_NO_ERROR(sys::fs::make_absolute("/root", Relative));
+ Relative[5] = '/'; // Fix up windows paths.
+ ASSERT_EQ("/root/foo.cpp", Relative);
+}
+
+TEST(Support, RelativePathIterator) {
+ SmallString<64> Path(StringRef("c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, '/');
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+TEST(Support, RelativePathDotIterator) {
+ SmallString<64> Path(StringRef(".c/.d/../."));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, '/');
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+TEST(Support, AbsolutePathIterator) {
+ SmallString<64> Path(StringRef("/c/d/e/foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, '/');
+
+ // The root path will also be a component when iterating
+ ExpectedPathComponents[0] = "/";
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+TEST(Support, AbsolutePathDotIterator) {
+ SmallString<64> Path(StringRef("/.c/.d/../."));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, '/');
+
+ // The root path will also be a component when iterating
+ ExpectedPathComponents[0] = "/";
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+
+#ifdef LLVM_ON_WIN32
+TEST(Support, AbsolutePathIteratorWin32) {
+ SmallString<64> Path(StringRef("c:\\c\\e\\foo.txt"));
+ typedef SmallVector<StringRef, 4> PathComponents;
+ PathComponents ExpectedPathComponents;
+ PathComponents ActualPathComponents;
+
+ StringRef(Path).split(ExpectedPathComponents, "\\");
+
+ // The root path (which comes after the drive name) will also be a component
+ // when iterating.
+ ExpectedPathComponents.insert(ExpectedPathComponents.begin()+1, "\\");
+
+ for (path::const_iterator I = path::begin(Path), E = path::end(Path); I != E;
+ ++I) {
+ ActualPathComponents.push_back(*I);
+ }
+
+ ASSERT_EQ(ExpectedPathComponents.size(), ActualPathComponents.size());
+
+ for (size_t i = 0; i <ExpectedPathComponents.size(); ++i) {
+ EXPECT_EQ(ExpectedPathComponents[i].str(), ActualPathComponents[i].str());
+ }
+}
+#endif // LLVM_ON_WIN32
+
+TEST(Support, AbsolutePathIteratorEnd) {
+ // Trailing slashes are converted to '.' unless they are part of the root path.
+ SmallVector<StringRef, 4> Paths;
+ Paths.push_back("/foo/");
+ Paths.push_back("/foo//");
+ Paths.push_back("//net//");
+#ifdef LLVM_ON_WIN32
+ Paths.push_back("c:\\\\");
+#endif
+
+ for (StringRef Path : Paths) {
+ StringRef LastComponent = *path::rbegin(Path);
+ EXPECT_EQ(".", LastComponent);
+ }
+
+ SmallVector<StringRef, 3> RootPaths;
+ RootPaths.push_back("/");
+ RootPaths.push_back("//net/");
+#ifdef LLVM_ON_WIN32
+ RootPaths.push_back("c:\\");
+#endif
+
+ for (StringRef Path : RootPaths) {
+ StringRef LastComponent = *path::rbegin(Path);
+ EXPECT_EQ(1u, LastComponent.size());
+ EXPECT_TRUE(path::is_separator(LastComponent[0]));
+ }
+}
+
+TEST(Support, HomeDirectory) {
+ std::string expected;
+#ifdef LLVM_ON_WIN32
+ if (wchar_t const *path = ::_wgetenv(L"USERPROFILE")) {
+ auto pathLen = ::wcslen(path);
+ ArrayRef<char> ref{reinterpret_cast<char const *>(path),
+ pathLen * sizeof(wchar_t)};
+ convertUTF16ToUTF8String(ref, expected);
+ }
+#else
+ if (char const *path = ::getenv("HOME"))
+ expected = path;
+#endif
+ // Do not try to test it if we don't know what to expect.
+ // On Windows we use something better than env vars.
+ if (!expected.empty()) {
+ SmallString<128> HomeDir;
+ auto status = path::home_directory(HomeDir);
+ EXPECT_TRUE(status);
+ EXPECT_EQ(expected, HomeDir);
+ }
+}
+
+TEST(Support, UserCacheDirectory) {
+ SmallString<13> CacheDir;
+ SmallString<20> CacheDir2;
+ auto Status = path::user_cache_directory(CacheDir, "");
+ EXPECT_TRUE(Status ^ CacheDir.empty());
+
+ if (Status) {
+ EXPECT_TRUE(path::user_cache_directory(CacheDir2, "")); // should succeed
+ EXPECT_EQ(CacheDir, CacheDir2); // and return same paths
+
+ EXPECT_TRUE(path::user_cache_directory(CacheDir, "A", "B", "file.c"));
+ auto It = path::rbegin(CacheDir);
+ EXPECT_EQ("file.c", *It);
+ EXPECT_EQ("B", *++It);
+ EXPECT_EQ("A", *++It);
+ auto ParentDir = *++It;
+
+ // Test Unicode: "<user_cache_dir>/(pi)r^2/aleth.0"
+ EXPECT_TRUE(path::user_cache_directory(CacheDir2, "\xCF\x80r\xC2\xB2",
+ "\xE2\x84\xB5.0"));
+ auto It2 = path::rbegin(CacheDir2);
+ EXPECT_EQ("\xE2\x84\xB5.0", *It2);
+ EXPECT_EQ("\xCF\x80r\xC2\xB2", *++It2);
+ auto ParentDir2 = *++It2;
+
+ EXPECT_EQ(ParentDir, ParentDir2);
+ }
+}
+
+TEST(Support, TempDirectory) {
+ SmallString<32> TempDir;
+ path::system_temp_directory(false, TempDir);
+ EXPECT_TRUE(!TempDir.empty());
+ TempDir.clear();
+ path::system_temp_directory(true, TempDir);
+ EXPECT_TRUE(!TempDir.empty());
+}
+
+#ifdef LLVM_ON_WIN32
+static std::string path2regex(std::string Path) {
+ size_t Pos = 0;
+ while ((Pos = Path.find('\\', Pos)) != std::string::npos) {
+ Path.replace(Pos, 1, "\\\\");
+ Pos += 2;
+ }
+ return Path;
+}
+
+/// Helper for running temp dir test in separated process. See below.
+#define EXPECT_TEMP_DIR(prepare, expected) \
+ EXPECT_EXIT( \
+ { \
+ prepare; \
+ SmallString<300> TempDir; \
+ path::system_temp_directory(true, TempDir); \
+ raw_os_ostream(std::cerr) << TempDir; \
+ std::exit(0); \
+ }, \
+ ::testing::ExitedWithCode(0), path2regex(expected))
+
+TEST(SupportDeathTest, TempDirectoryOnWindows) {
+ // In this test we want to check how system_temp_directory responds to
+ // different values of specific env vars. To prevent corrupting env vars of
+ // the current process all checks are done in separated processes.
+ EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"C:\\OtherFolder"), "C:\\OtherFolder");
+ EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"C:/Unix/Path/Seperators"),
+ "C:\\Unix\\Path\\Seperators");
+ EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"Local Path"), ".+\\Local Path$");
+ EXPECT_TEMP_DIR(_wputenv_s(L"TMP", L"F:\\TrailingSep\\"), "F:\\TrailingSep");
+ EXPECT_TEMP_DIR(
+ _wputenv_s(L"TMP", L"C:\\2\x03C0r-\x00B5\x00B3\\\x2135\x2080"),
+ "C:\\2\xCF\x80r-\xC2\xB5\xC2\xB3\\\xE2\x84\xB5\xE2\x82\x80");
+
+ // Test $TMP empty, $TEMP set.
+ EXPECT_TEMP_DIR(
+ {
+ _wputenv_s(L"TMP", L"");
+ _wputenv_s(L"TEMP", L"C:\\Valid\\Path");
+ },
+ "C:\\Valid\\Path");
+
+ // All related env vars empty
+ EXPECT_TEMP_DIR(
+ {
+ _wputenv_s(L"TMP", L"");
+ _wputenv_s(L"TEMP", L"");
+ _wputenv_s(L"USERPROFILE", L"");
+ },
+ "C:\\Temp");
+
+ // Test evn var / path with 260 chars.
+ SmallString<270> Expected{"C:\\Temp\\AB\\123456789"};
+ while (Expected.size() < 260)
+ Expected.append("\\DirNameWith19Charss");
+ ASSERT_EQ(260, Expected.size());
+ EXPECT_TEMP_DIR(_putenv_s("TMP", Expected.c_str()), Expected.c_str());
+}
+#endif
+
+class FileSystemTest : public testing::Test {
+protected:
+ /// Unique temporary directory in which all created filesystem entities must
+ /// be placed. It is removed at the end of each test (must be empty).
+ SmallString<128> TestDirectory;
+
+ void SetUp() override {
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("file-system-test", TestDirectory));
+ // We don't care about this specific file.
+ errs() << "Test Directory: " << TestDirectory << '\n';
+ errs().flush();
+ }
+
+ void TearDown() override { ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); }
+};
+
+TEST_F(FileSystemTest, Unique) {
+ // Create a temp file.
+ int FileDescriptor;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
+
+ // The same file should return an identical unique id.
+ fs::UniqueID F1, F2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), F2));
+ ASSERT_EQ(F1, F2);
+
+ // Different files should return different unique ids.
+ int FileDescriptor2;
+ SmallString<64> TempPath2;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor2, TempPath2));
+
+ fs::UniqueID D;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D));
+ ASSERT_NE(D, F1);
+ ::close(FileDescriptor2);
+
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
+
+ // Two paths representing the same file on disk should still provide the
+ // same unique id. We can test this by making a hard link.
+ ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2)));
+ fs::UniqueID D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath2), D2));
+ ASSERT_EQ(D2, F1);
+
+ ::close(FileDescriptor);
+
+ SmallString<128> Dir1;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("dir1", Dir1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir1.c_str(), F2));
+ ASSERT_EQ(F1, F2);
+
+ SmallString<128> Dir2;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("dir2", Dir2));
+ ASSERT_NO_ERROR(fs::getUniqueID(Dir2.c_str(), F2));
+ ASSERT_NE(F1, F2);
+}
+
+TEST_F(FileSystemTest, TempFiles) {
+ // Create a temp file.
+ int FileDescriptor;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
+
+ // Make sure it exists.
+ ASSERT_TRUE(sys::fs::exists(Twine(TempPath)));
+
+ // Create another temp tile.
+ int FD2;
+ SmallString<64> TempPath2;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD2, TempPath2));
+ ASSERT_TRUE(TempPath2.endswith(".temp"));
+ ASSERT_NE(TempPath.str(), TempPath2.str());
+
+ fs::file_status A, B;
+ ASSERT_NO_ERROR(fs::status(Twine(TempPath), A));
+ ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B));
+ EXPECT_FALSE(fs::equivalent(A, B));
+
+ ::close(FD2);
+
+ // Remove Temp2.
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
+ ASSERT_EQ(fs::remove(Twine(TempPath2), false),
+ errc::no_such_file_or_directory);
+
+ std::error_code EC = fs::status(TempPath2.c_str(), B);
+ EXPECT_EQ(EC, errc::no_such_file_or_directory);
+ EXPECT_EQ(B.type(), fs::file_type::file_not_found);
+
+ // Make sure Temp2 doesn't exist.
+ ASSERT_EQ(fs::access(Twine(TempPath2), sys::fs::AccessMode::Exist),
+ errc::no_such_file_or_directory);
+
+ SmallString<64> TempPath3;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "", TempPath3));
+ ASSERT_FALSE(TempPath3.endswith("."));
+
+ // Create a hard link to Temp1.
+ ASSERT_NO_ERROR(fs::create_link(Twine(TempPath), Twine(TempPath2)));
+ bool equal;
+ ASSERT_NO_ERROR(fs::equivalent(Twine(TempPath), Twine(TempPath2), equal));
+ EXPECT_TRUE(equal);
+ ASSERT_NO_ERROR(fs::status(Twine(TempPath), A));
+ ASSERT_NO_ERROR(fs::status(Twine(TempPath2), B));
+ EXPECT_TRUE(fs::equivalent(A, B));
+
+ // Remove Temp1.
+ ::close(FileDescriptor);
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath)));
+
+ // Remove the hard link.
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath2)));
+
+ // Make sure Temp1 doesn't exist.
+ ASSERT_EQ(fs::access(Twine(TempPath), sys::fs::AccessMode::Exist),
+ errc::no_such_file_or_directory);
+
+#ifdef LLVM_ON_WIN32
+ // Path name > 260 chars should get an error.
+ const char *Path270 =
+ "abcdefghijklmnopqrstuvwxyz9abcdefghijklmnopqrstuvwxyz8"
+ "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6"
+ "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
+ "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"
+ "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0";
+ EXPECT_EQ(fs::createUniqueFile(Path270, FileDescriptor, TempPath),
+ errc::invalid_argument);
+ // Relative path < 247 chars, no problem.
+ const char *Path216 =
+ "abcdefghijklmnopqrstuvwxyz7abcdefghijklmnopqrstuvwxyz6"
+ "abcdefghijklmnopqrstuvwxyz5abcdefghijklmnopqrstuvwxyz4"
+ "abcdefghijklmnopqrstuvwxyz3abcdefghijklmnopqrstuvwxyz2"
+ "abcdefghijklmnopqrstuvwxyz1abcdefghijklmnopqrstuvwxyz0";
+ ASSERT_NO_ERROR(fs::createTemporaryFile(Path216, "", TempPath));
+ ASSERT_NO_ERROR(fs::remove(Twine(TempPath)));
+#endif
+}
+
+TEST_F(FileSystemTest, CreateDir) {
+ ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo"));
+ ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "foo"));
+ ASSERT_EQ(fs::create_directory(Twine(TestDirectory) + "foo", false),
+ errc::file_exists);
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "foo"));
+
+#ifdef LLVM_ON_UNIX
+ // Set a 0000 umask so that we can test our directory permissions.
+ mode_t OldUmask = ::umask(0000);
+
+ fs::file_status Status;
+ ASSERT_NO_ERROR(
+ fs::create_directory(Twine(TestDirectory) + "baz500", false,
+ fs::perms::owner_read | fs::perms::owner_exe));
+ ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz500", Status));
+ ASSERT_EQ(Status.permissions() & fs::perms::all_all,
+ fs::perms::owner_read | fs::perms::owner_exe);
+ ASSERT_NO_ERROR(fs::create_directory(Twine(TestDirectory) + "baz777", false,
+ fs::perms::all_all));
+ ASSERT_NO_ERROR(fs::status(Twine(TestDirectory) + "baz777", Status));
+ ASSERT_EQ(Status.permissions() & fs::perms::all_all, fs::perms::all_all);
+
+ // Restore umask to be safe.
+ ::umask(OldUmask);
+#endif
+
+#ifdef LLVM_ON_WIN32
+ // Prove that create_directories() can handle a pathname > 248 characters,
+ // which is the documented limit for CreateDirectory().
+ // (248 is MAX_PATH subtracting room for an 8.3 filename.)
+ // Generate a directory path guaranteed to fall into that range.
+ size_t TmpLen = TestDirectory.size();
+ const char *OneDir = "\\123456789";
+ size_t OneDirLen = strlen(OneDir);
+ ASSERT_LT(OneDirLen, 12U);
+ size_t NLevels = ((248 - TmpLen) / OneDirLen) + 1;
+ SmallString<260> LongDir(TestDirectory);
+ for (size_t I = 0; I < NLevels; ++I)
+ LongDir.append(OneDir);
+ ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir)));
+ ASSERT_NO_ERROR(fs::create_directories(Twine(LongDir)));
+ ASSERT_EQ(fs::create_directories(Twine(LongDir), false),
+ errc::file_exists);
+ // Tidy up, "recursively" removing the directories.
+ StringRef ThisDir(LongDir);
+ for (size_t J = 0; J < NLevels; ++J) {
+ ASSERT_NO_ERROR(fs::remove(ThisDir));
+ ThisDir = path::parent_path(ThisDir);
+ }
+
+ // Similarly for a relative pathname. Need to set the current directory to
+ // TestDirectory so that the one we create ends up in the right place.
+ char PreviousDir[260];
+ size_t PreviousDirLen = ::GetCurrentDirectoryA(260, PreviousDir);
+ ASSERT_GT(PreviousDirLen, 0U);
+ ASSERT_LT(PreviousDirLen, 260U);
+ ASSERT_NE(::SetCurrentDirectoryA(TestDirectory.c_str()), 0);
+ LongDir.clear();
+ // Generate a relative directory name with absolute length > 248.
+ size_t LongDirLen = 249 - TestDirectory.size();
+ LongDir.assign(LongDirLen, 'a');
+ ASSERT_NO_ERROR(fs::create_directory(Twine(LongDir)));
+ // While we're here, prove that .. and . handling works in these long paths.
+ const char *DotDotDirs = "\\..\\.\\b";
+ LongDir.append(DotDotDirs);
+ ASSERT_NO_ERROR(fs::create_directory("b"));
+ ASSERT_EQ(fs::create_directory(Twine(LongDir), false), errc::file_exists);
+ // And clean up.
+ ASSERT_NO_ERROR(fs::remove("b"));
+ ASSERT_NO_ERROR(fs::remove(
+ Twine(LongDir.substr(0, LongDir.size() - strlen(DotDotDirs)))));
+ ASSERT_NE(::SetCurrentDirectoryA(PreviousDir), 0);
+#endif
+}
+
+TEST_F(FileSystemTest, DirectoryIteration) {
+ std::error_code ec;
+ for (fs::directory_iterator i(".", ec), e; i != e; i.increment(ec))
+ ASSERT_NO_ERROR(ec);
+
+ // Create a known hierarchy to recurse over.
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/recursive/a0/aa1"));
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/recursive/a0/ab1"));
+ ASSERT_NO_ERROR(fs::create_directories(Twine(TestDirectory) +
+ "/recursive/dontlookhere/da1"));
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/recursive/z0/za1"));
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/recursive/pop/p1"));
+ typedef std::vector<std::string> v_t;
+ v_t visited;
+ for (fs::recursive_directory_iterator i(Twine(TestDirectory)
+ + "/recursive", ec), e; i != e; i.increment(ec)){
+ ASSERT_NO_ERROR(ec);
+ if (path::filename(i->path()) == "p1") {
+ i.pop();
+ // FIXME: recursive_directory_iterator should be more robust.
+ if (i == e) break;
+ }
+ if (path::filename(i->path()) == "dontlookhere")
+ i.no_push();
+ visited.push_back(path::filename(i->path()));
+ }
+ v_t::const_iterator a0 = std::find(visited.begin(), visited.end(), "a0");
+ v_t::const_iterator aa1 = std::find(visited.begin(), visited.end(), "aa1");
+ v_t::const_iterator ab1 = std::find(visited.begin(), visited.end(), "ab1");
+ v_t::const_iterator dontlookhere = std::find(visited.begin(), visited.end(),
+ "dontlookhere");
+ v_t::const_iterator da1 = std::find(visited.begin(), visited.end(), "da1");
+ v_t::const_iterator z0 = std::find(visited.begin(), visited.end(), "z0");
+ v_t::const_iterator za1 = std::find(visited.begin(), visited.end(), "za1");
+ v_t::const_iterator pop = std::find(visited.begin(), visited.end(), "pop");
+ v_t::const_iterator p1 = std::find(visited.begin(), visited.end(), "p1");
+
+ // Make sure that each path was visited correctly.
+ ASSERT_NE(a0, visited.end());
+ ASSERT_NE(aa1, visited.end());
+ ASSERT_NE(ab1, visited.end());
+ ASSERT_NE(dontlookhere, visited.end());
+ ASSERT_EQ(da1, visited.end()); // Not visited.
+ ASSERT_NE(z0, visited.end());
+ ASSERT_NE(za1, visited.end());
+ ASSERT_NE(pop, visited.end());
+ ASSERT_EQ(p1, visited.end()); // Not visited.
+
+ // Make sure that parents were visited before children. No other ordering
+ // guarantees can be made across siblings.
+ ASSERT_LT(a0, aa1);
+ ASSERT_LT(a0, ab1);
+ ASSERT_LT(z0, za1);
+
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/aa1"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0/ab1"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/a0"));
+ ASSERT_NO_ERROR(
+ fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere/da1"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/dontlookhere"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop/p1"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/pop"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0/za1"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive/z0"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/recursive"));
+}
+
+const char archive[] = "!<arch>\x0A";
+const char bitcode[] = "\xde\xc0\x17\x0b";
+const char coff_object[] = "\x00\x00......";
+const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......"
+ "\xc7\xa1\xba\xd1\xee\xba\xa9\x4b\xaf\x20\xfa\xf6\x6a\xa4\xdc\xb8";
+const char coff_import_library[] = "\x00\x00\xff\xff....";
+const char elf_relocatable[] = { 0x7f, 'E', 'L', 'F', 1, 2, 1, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1 };
+const char macho_universal_binary[] = "\xca\xfe\xba\xbe...\0x00";
+const char macho_object[] = "\xfe\xed\xfa\xce..........\x00\x01";
+const char macho_executable[] = "\xfe\xed\xfa\xce..........\x00\x02";
+const char macho_fixed_virtual_memory_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x03";
+const char macho_core[] = "\xfe\xed\xfa\xce..........\x00\x04";
+const char macho_preload_executable[] = "\xfe\xed\xfa\xce..........\x00\x05";
+const char macho_dynamically_linked_shared_lib[] =
+ "\xfe\xed\xfa\xce..........\x00\x06";
+const char macho_dynamic_linker[] = "\xfe\xed\xfa\xce..........\x00\x07";
+const char macho_bundle[] = "\xfe\xed\xfa\xce..........\x00\x08";
+const char macho_dsym_companion[] = "\xfe\xed\xfa\xce..........\x00\x0a";
+const char macho_kext_bundle[] = "\xfe\xed\xfa\xce..........\x00\x0b";
+const char windows_resource[] = "\x00\x00\x00\x00\x020\x00\x00\x00\xff";
+const char macho_dynamically_linked_shared_lib_stub[] =
+ "\xfe\xed\xfa\xce..........\x00\x09";
+
+TEST_F(FileSystemTest, Magic) {
+ struct type {
+ const char *filename;
+ const char *magic_str;
+ size_t magic_str_len;
+ fs::file_magic magic;
+ } types[] = {
+#define DEFINE(magic) \
+ { #magic, magic, sizeof(magic), fs::file_magic::magic }
+ DEFINE(archive),
+ DEFINE(bitcode),
+ DEFINE(coff_object),
+ { "coff_bigobj", coff_bigobj, sizeof(coff_bigobj), fs::file_magic::coff_object },
+ DEFINE(coff_import_library),
+ DEFINE(elf_relocatable),
+ DEFINE(macho_universal_binary),
+ DEFINE(macho_object),
+ DEFINE(macho_executable),
+ DEFINE(macho_fixed_virtual_memory_shared_lib),
+ DEFINE(macho_core),
+ DEFINE(macho_preload_executable),
+ DEFINE(macho_dynamically_linked_shared_lib),
+ DEFINE(macho_dynamic_linker),
+ DEFINE(macho_bundle),
+ DEFINE(macho_dynamically_linked_shared_lib_stub),
+ DEFINE(macho_dsym_companion),
+ DEFINE(macho_kext_bundle),
+ DEFINE(windows_resource)
+#undef DEFINE
+ };
+
+ // Create some files filled with magic.
+ for (type *i = types, *e = types + (sizeof(types) / sizeof(type)); i != e;
+ ++i) {
+ SmallString<128> file_pathname(TestDirectory);
+ path::append(file_pathname, i->filename);
+ std::error_code EC;
+ raw_fd_ostream file(file_pathname, EC, sys::fs::F_None);
+ ASSERT_FALSE(file.has_error());
+ StringRef magic(i->magic_str, i->magic_str_len);
+ file << magic;
+ file.close();
+ EXPECT_EQ(i->magic, fs::identify_magic(magic));
+ ASSERT_NO_ERROR(fs::remove(Twine(file_pathname)));
+ }
+}
+
+#ifdef LLVM_ON_WIN32
+TEST_F(FileSystemTest, CarriageReturn) {
+ SmallString<128> FilePathname(TestDirectory);
+ std::error_code EC;
+ path::append(FilePathname, "test");
+
+ {
+ raw_fd_ostream File(FilePathname, EC, sys::fs::F_Text);
+ ASSERT_NO_ERROR(EC);
+ File << '\n';
+ }
+ {
+ auto Buf = MemoryBuffer::getFile(FilePathname.str());
+ EXPECT_TRUE((bool)Buf);
+ EXPECT_EQ(Buf.get()->getBuffer(), "\r\n");
+ }
+
+ {
+ raw_fd_ostream File(FilePathname, EC, sys::fs::F_None);
+ ASSERT_NO_ERROR(EC);
+ File << '\n';
+ }
+ {
+ auto Buf = MemoryBuffer::getFile(FilePathname.str());
+ EXPECT_TRUE((bool)Buf);
+ EXPECT_EQ(Buf.get()->getBuffer(), "\n");
+ }
+ ASSERT_NO_ERROR(fs::remove(Twine(FilePathname)));
+}
+#endif
+
+TEST_F(FileSystemTest, Resize) {
+ int FD;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(fs::createTemporaryFile("prefix", "temp", FD, TempPath));
+ ASSERT_NO_ERROR(fs::resize_file(FD, 123));
+ fs::file_status Status;
+ ASSERT_NO_ERROR(fs::status(FD, Status));
+ ASSERT_EQ(Status.getSize(), 123U);
+}
+
+TEST_F(FileSystemTest, FileMapping) {
+ // Create a temp file.
+ int FileDescriptor;
+ SmallString<64> TempPath;
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("prefix", "temp", FileDescriptor, TempPath));
+ unsigned Size = 4096;
+ ASSERT_NO_ERROR(fs::resize_file(FileDescriptor, Size));
+
+ // Map in temp file and add some content
+ std::error_code EC;
+ StringRef Val("hello there");
+ {
+ fs::mapped_file_region mfr(FileDescriptor,
+ fs::mapped_file_region::readwrite, Size, 0, EC);
+ ASSERT_NO_ERROR(EC);
+ std::copy(Val.begin(), Val.end(), mfr.data());
+ // Explicitly add a 0.
+ mfr.data()[Val.size()] = 0;
+ // Unmap temp file
+ }
+
+ // Map it back in read-only
+ int FD;
+ EC = fs::openFileForRead(Twine(TempPath), FD);
+ ASSERT_NO_ERROR(EC);
+ fs::mapped_file_region mfr(FD, fs::mapped_file_region::readonly, Size, 0, EC);
+ ASSERT_NO_ERROR(EC);
+
+ // Verify content
+ EXPECT_EQ(StringRef(mfr.const_data()), Val);
+
+ // Unmap temp file
+ fs::mapped_file_region m(FD, fs::mapped_file_region::readonly, Size, 0, EC);
+ ASSERT_NO_ERROR(EC);
+ ASSERT_EQ(close(FD), 0);
+}
+
+TEST(Support, NormalizePath) {
+#if defined(LLVM_ON_WIN32)
+#define EXPECT_PATH_IS(path__, windows__, not_windows__) \
+ EXPECT_EQ(path__, windows__);
+#else
+#define EXPECT_PATH_IS(path__, windows__, not_windows__) \
+ EXPECT_EQ(path__, not_windows__);
+#endif
+
+ SmallString<64> Path1("a");
+ SmallString<64> Path2("a/b");
+ SmallString<64> Path3("a\\b");
+ SmallString<64> Path4("a\\\\b");
+ SmallString<64> Path5("\\a");
+ SmallString<64> Path6("a\\");
+
+ path::native(Path1);
+ EXPECT_PATH_IS(Path1, "a", "a");
+
+ path::native(Path2);
+ EXPECT_PATH_IS(Path2, "a\\b", "a/b");
+
+ path::native(Path3);
+ EXPECT_PATH_IS(Path3, "a\\b", "a/b");
+
+ path::native(Path4);
+ EXPECT_PATH_IS(Path4, "a\\\\b", "a\\\\b");
+
+ path::native(Path5);
+ EXPECT_PATH_IS(Path5, "\\a", "/a");
+
+ path::native(Path6);
+ EXPECT_PATH_IS(Path6, "a\\", "a/");
+
+#undef EXPECT_PATH_IS
+}
+
+TEST(Support, RemoveLeadingDotSlash) {
+ StringRef Path1("././/foolz/wat");
+ StringRef Path2("./////");
+
+ Path1 = path::remove_leading_dotslash(Path1);
+ EXPECT_EQ(Path1, "foolz/wat");
+ Path2 = path::remove_leading_dotslash(Path2);
+ EXPECT_EQ(Path2, "");
+}
+
+static std::string remove_dots(StringRef path,
+ bool remove_dot_dot) {
+ SmallString<256> buffer(path);
+ path::remove_dots(buffer, remove_dot_dot);
+ return buffer.str();
+}
+
+TEST(Support, RemoveDots) {
+#if defined(LLVM_ON_WIN32)
+ EXPECT_EQ("foolz\\wat", remove_dots(".\\.\\\\foolz\\wat", false));
+ EXPECT_EQ("", remove_dots(".\\\\\\\\\\", false));
+
+ EXPECT_EQ("a\\..\\b\\c", remove_dots(".\\a\\..\\b\\c", false));
+ EXPECT_EQ("b\\c", remove_dots(".\\a\\..\\b\\c", true));
+ EXPECT_EQ("c", remove_dots(".\\.\\c", true));
+
+ SmallString<64> Path1(".\\.\\c");
+ EXPECT_TRUE(path::remove_dots(Path1, true));
+ EXPECT_EQ("c", Path1);
+#else
+ EXPECT_EQ("foolz/wat", remove_dots("././/foolz/wat", false));
+ EXPECT_EQ("", remove_dots("./////", false));
+
+ EXPECT_EQ("a/../b/c", remove_dots("./a/../b/c", false));
+ EXPECT_EQ("b/c", remove_dots("./a/../b/c", true));
+ EXPECT_EQ("c", remove_dots("././c", true));
+
+ SmallString<64> Path1("././c");
+ EXPECT_TRUE(path::remove_dots(Path1, true));
+ EXPECT_EQ("c", Path1);
+#endif
+}
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/ProcessTest.cpp b/gnu/llvm/unittests/Support/ProcessTest.cpp
new file mode 100644
index 00000000000..298a0a37323
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ProcessTest.cpp
@@ -0,0 +1,57 @@
+//===- unittest/Support/ProcessTest.cpp -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Process.h"
+#include "gtest/gtest.h"
+
+#ifdef LLVM_ON_WIN32
+#include <windows.h>
+#endif
+
+namespace {
+
+using namespace llvm;
+using namespace sys;
+
+TEST(ProcessTest, GetRandomNumberTest) {
+ const unsigned r1 = Process::GetRandomNumber();
+ const unsigned r2 = Process::GetRandomNumber();
+ // It should be extremely unlikely that both r1 and r2 are 0.
+ EXPECT_NE((r1 | r2), 0u);
+}
+
+#ifdef _MSC_VER
+#define setenv(name, var, ignore) _putenv_s(name, var)
+#endif
+
+#if HAVE_SETENV || _MSC_VER
+TEST(ProcessTest, Basic) {
+ setenv("__LLVM_TEST_ENVIRON_VAR__", "abc", true);
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abc", val->c_str());
+}
+
+TEST(ProcessTest, None) {
+ Optional<std::string> val(
+ Process::GetEnv("__LLVM_TEST_ENVIRON_NO_SUCH_VAR__"));
+ EXPECT_FALSE(val.hasValue());
+}
+#endif
+
+#ifdef LLVM_ON_WIN32
+TEST(ProcessTest, Wchar) {
+ SetEnvironmentVariableW(L"__LLVM_TEST_ENVIRON_VAR__", L"abcdefghijklmnopqrs");
+ Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__"));
+ EXPECT_TRUE(val.hasValue());
+ EXPECT_STREQ("abcdefghijklmnopqrs", val->c_str());
+}
+#endif
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Support/ProgramTest.cpp b/gnu/llvm/unittests/Support/ProgramTest.cpp
new file mode 100644
index 00000000000..47a3dbb5fb1
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ProgramTest.cpp
@@ -0,0 +1,355 @@
+//===- unittest/Support/ProgramTest.cpp -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+#include "gtest/gtest.h"
+#include <stdlib.h>
+#if defined(__APPLE__)
+# include <crt_externs.h>
+#elif !defined(_MSC_VER)
+// Forward declare environ in case it's not provided by stdlib.h.
+extern char **environ;
+#endif
+
+#if defined(LLVM_ON_UNIX)
+#include <unistd.h>
+void sleep_for(unsigned int seconds) {
+ sleep(seconds);
+}
+#elif defined(LLVM_ON_WIN32)
+#include <windows.h>
+void sleep_for(unsigned int seconds) {
+ Sleep(seconds * 1000);
+}
+#else
+#error sleep_for is not implemented on your platform.
+#endif
+
+#define ASSERT_NO_ERROR(x) \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ SmallString<128> MessageStorage; \
+ raw_svector_ostream Message(MessageStorage); \
+ Message << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ GTEST_FATAL_FAILURE_(MessageStorage.c_str()); \
+ } else { \
+ }
+// From TestMain.cpp.
+extern const char *TestMainArgv0;
+
+namespace {
+
+using namespace llvm;
+using namespace sys;
+
+static cl::opt<std::string>
+ProgramTestStringArg1("program-test-string-arg1");
+static cl::opt<std::string>
+ProgramTestStringArg2("program-test-string-arg2");
+
+class ProgramEnvTest : public testing::Test {
+ std::vector<const char *> EnvTable;
+ std::vector<std::string> EnvStorage;
+
+protected:
+ void SetUp() override {
+ auto EnvP = [] {
+#if defined(LLVM_ON_WIN32)
+ _wgetenv(L"TMP"); // Populate _wenviron, initially is null
+ return _wenviron;
+#elif defined(__APPLE__)
+ return *_NSGetEnviron();
+#else
+ return environ;
+#endif
+ }();
+ ASSERT_TRUE(EnvP);
+
+ auto prepareEnvVar = [this](decltype(*EnvP) Var) {
+#if defined(LLVM_ON_WIN32)
+ // On Windows convert UTF16 encoded variable to UTF8
+ auto Len = wcslen(Var);
+ ArrayRef<char> Ref{reinterpret_cast<char const *>(Var),
+ Len * sizeof(*Var)};
+ EnvStorage.emplace_back();
+ auto convStatus = convertUTF16ToUTF8String(Ref, EnvStorage.back());
+ EXPECT_TRUE(convStatus);
+ return EnvStorage.back().c_str();
+#else
+ return Var;
+#endif
+ };
+
+ while (*EnvP != nullptr) {
+ EnvTable.emplace_back(prepareEnvVar(*EnvP));
+ ++EnvP;
+ }
+ }
+
+ void TearDown() override {
+ EnvTable.clear();
+ EnvStorage.clear();
+ }
+
+ void addEnvVar(const char *Var) {
+ ASSERT_TRUE(EnvTable.empty() || EnvTable.back()) << "Env table sealed";
+ EnvTable.emplace_back(Var);
+ }
+
+ const char **getEnviron() {
+ if (EnvTable.back() != nullptr)
+ EnvTable.emplace_back(nullptr); // Seal table.
+ return &EnvTable[0];
+ }
+};
+
+#ifdef LLVM_ON_WIN32
+TEST_F(ProgramEnvTest, CreateProcessLongPath) {
+ if (getenv("LLVM_PROGRAM_TEST_LONG_PATH"))
+ exit(0);
+
+ // getMainExecutable returns an absolute path; prepend the long-path prefix.
+ std::string MyAbsExe =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ std::string MyExe;
+ if (!StringRef(MyAbsExe).startswith("\\\\?\\"))
+ MyExe.append("\\\\?\\");
+ MyExe.append(MyAbsExe);
+
+ const char *ArgV[] = {
+ MyExe.c_str(),
+ "--gtest_filter=ProgramEnvTest.CreateProcessLongPath",
+ nullptr
+ };
+
+ // Add LLVM_PROGRAM_TEST_LONG_PATH to the environment of the child.
+ addEnvVar("LLVM_PROGRAM_TEST_LONG_PATH=1");
+
+ // Redirect stdout to a long path.
+ SmallString<128> TestDirectory;
+ ASSERT_NO_ERROR(
+ fs::createUniqueDirectory("program-redirect-test", TestDirectory));
+ SmallString<256> LongPath(TestDirectory);
+ LongPath.push_back('\\');
+ // MAX_PATH = 260
+ LongPath.append(260 - TestDirectory.size(), 'a');
+ StringRef LongPathRef(LongPath);
+
+ std::string Error;
+ bool ExecutionFailed;
+ const StringRef *Redirects[] = { nullptr, &LongPathRef, nullptr };
+ int RC = ExecuteAndWait(MyExe, ArgV, getEnviron(), Redirects,
+ /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error,
+ &ExecutionFailed);
+ EXPECT_FALSE(ExecutionFailed) << Error;
+ EXPECT_EQ(0, RC);
+
+ // Remove the long stdout.
+ ASSERT_NO_ERROR(fs::remove(Twine(LongPath)));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory)));
+}
+#endif
+
+TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) {
+ if (getenv("LLVM_PROGRAM_TEST_CHILD")) {
+ if (ProgramTestStringArg1 == "has\\\\ trailing\\" &&
+ ProgramTestStringArg2 == "has\\\\ trailing\\") {
+ exit(0); // Success! The arguments were passed and parsed.
+ }
+ exit(1);
+ }
+
+ std::string my_exe =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ const char *argv[] = {
+ my_exe.c_str(),
+ "--gtest_filter=ProgramEnvTest.CreateProcessTrailingSlash",
+ "-program-test-string-arg1", "has\\\\ trailing\\",
+ "-program-test-string-arg2", "has\\\\ trailing\\",
+ nullptr
+ };
+
+ // Add LLVM_PROGRAM_TEST_CHILD to the environment of the child.
+ addEnvVar("LLVM_PROGRAM_TEST_CHILD=1");
+
+ std::string error;
+ bool ExecutionFailed;
+ // Redirect stdout and stdin to NUL, but let stderr through.
+#ifdef LLVM_ON_WIN32
+ StringRef nul("NUL");
+#else
+ StringRef nul("/dev/null");
+#endif
+ const StringRef *redirects[] = { &nul, &nul, nullptr };
+ int rc = ExecuteAndWait(my_exe, argv, getEnviron(), redirects,
+ /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error,
+ &ExecutionFailed);
+ EXPECT_FALSE(ExecutionFailed) << error;
+ EXPECT_EQ(0, rc);
+}
+
+TEST_F(ProgramEnvTest, TestExecuteNoWait) {
+ using namespace llvm::sys;
+
+ if (getenv("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT")) {
+ sleep_for(/*seconds*/ 1);
+ exit(0);
+ }
+
+ std::string Executable =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ const char *argv[] = {
+ Executable.c_str(),
+ "--gtest_filter=ProgramEnvTest.TestExecuteNoWait",
+ nullptr
+ };
+
+ // Add LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT to the environment of the child.
+ addEnvVar("LLVM_PROGRAM_TEST_EXECUTE_NO_WAIT=1");
+
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0,
+ &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI1.Pid, 0) << "Invalid process id";
+
+ unsigned LoopCount = 0;
+
+ // Test that Wait() with WaitUntilTerminates=true works. In this case,
+ // LoopCount should only be incremented once.
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI1.Pid)
+ break;
+ }
+
+ EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1";
+
+ ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0,
+ &Error, &ExecutionFailed);
+ ASSERT_FALSE(ExecutionFailed) << Error;
+ ASSERT_NE(PI2.Pid, 0) << "Invalid process id";
+
+ // Test that Wait() with SecondsToWait=0 performs a non-blocking wait. In this
+ // cse, LoopCount should be greater than 1 (more than one increment occurs).
+ while (true) {
+ ++LoopCount;
+ ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
+ ASSERT_TRUE(Error.empty());
+ if (WaitResult.Pid == PI2.Pid)
+ break;
+ }
+
+ ASSERT_GT(LoopCount, 1u) << "LoopCount should be >1";
+}
+
+TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) {
+ using namespace llvm::sys;
+
+ if (getenv("LLVM_PROGRAM_TEST_TIMEOUT")) {
+ sleep_for(/*seconds*/ 10);
+ exit(0);
+ }
+
+ std::string Executable =
+ sys::fs::getMainExecutable(TestMainArgv0, &ProgramTestStringArg1);
+ const char *argv[] = {
+ Executable.c_str(),
+ "--gtest_filter=ProgramEnvTest.TestExecuteAndWaitTimeout",
+ nullptr
+ };
+
+ // Add LLVM_PROGRAM_TEST_TIMEOUT to the environment of the child.
+ addEnvVar("LLVM_PROGRAM_TEST_TIMEOUT=1");
+
+ std::string Error;
+ bool ExecutionFailed;
+ int RetCode =
+ ExecuteAndWait(Executable, argv, getEnviron(), nullptr, /*secondsToWait=*/1, 0,
+ &Error, &ExecutionFailed);
+ ASSERT_EQ(-2, RetCode);
+}
+
+TEST(ProgramTest, TestExecuteNegative) {
+ std::string Executable = "i_dont_exist";
+ const char *argv[] = { Executable.c_str(), nullptr };
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ int RetCode = ExecuteAndWait(Executable, argv, nullptr, nullptr, 0, 0,
+ &Error, &ExecutionFailed);
+ ASSERT_TRUE(RetCode < 0) << "On error ExecuteAndWait should return 0 or "
+ "positive value indicating the result code";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+ {
+ std::string Error;
+ bool ExecutionFailed;
+ ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0,
+ &Error, &ExecutionFailed);
+ ASSERT_EQ(PI.Pid, 0)
+ << "On error ExecuteNoWait should return an invalid ProcessInfo";
+ ASSERT_TRUE(ExecutionFailed);
+ ASSERT_FALSE(Error.empty());
+ }
+
+}
+
+#ifdef LLVM_ON_WIN32
+const char utf16le_text[] =
+ "\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61\x00";
+const char utf16be_text[] =
+ "\x00\x6c\x00\x69\x00\x6e\x00\x67\x00\xfc\x00\x69\x00\xe7\x00\x61";
+#endif
+const char utf8_text[] = "\x6c\x69\x6e\x67\xc3\xbc\x69\xc3\xa7\x61";
+
+TEST(ProgramTest, TestWriteWithSystemEncoding) {
+ SmallString<128> TestDirectory;
+ ASSERT_NO_ERROR(fs::createUniqueDirectory("program-test", TestDirectory));
+ errs() << "Test Directory: " << TestDirectory << '\n';
+ errs().flush();
+ SmallString<128> file_pathname(TestDirectory);
+ path::append(file_pathname, "international-file.txt");
+ // Only on Windows we should encode in UTF16. For other systems, use UTF8
+ ASSERT_NO_ERROR(sys::writeFileWithEncoding(file_pathname.c_str(), utf8_text,
+ sys::WEM_UTF16));
+ int fd = 0;
+ ASSERT_NO_ERROR(fs::openFileForRead(file_pathname.c_str(), fd));
+#if defined(LLVM_ON_WIN32)
+ char buf[18];
+ ASSERT_EQ(::read(fd, buf, 18), 18);
+ if (strncmp(buf, "\xfe\xff", 2) == 0) { // UTF16-BE
+ ASSERT_EQ(strncmp(&buf[2], utf16be_text, 16), 0);
+ } else if (strncmp(buf, "\xff\xfe", 2) == 0) { // UTF16-LE
+ ASSERT_EQ(strncmp(&buf[2], utf16le_text, 16), 0);
+ } else {
+ FAIL() << "Invalid BOM in UTF-16 file";
+ }
+#else
+ char buf[10];
+ ASSERT_EQ(::read(fd, buf, 10), 10);
+ ASSERT_EQ(strncmp(buf, utf8_text, 10), 0);
+#endif
+ ::close(fd);
+ ASSERT_NO_ERROR(fs::remove(file_pathname.str()));
+ ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
+}
+
+} // end anonymous namespace
diff --git a/gnu/llvm/unittests/Support/RegexTest.cpp b/gnu/llvm/unittests/Support/RegexTest.cpp
new file mode 100644
index 00000000000..c045c49bc3d
--- /dev/null
+++ b/gnu/llvm/unittests/Support/RegexTest.cpp
@@ -0,0 +1,156 @@
+//===- llvm/unittest/Support/RegexTest.cpp - Regex tests --===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Regex.h"
+#include "llvm/ADT/SmallVector.h"
+#include "gtest/gtest.h"
+#include <cstring>
+
+using namespace llvm;
+namespace {
+
+class RegexTest : public ::testing::Test {
+};
+
+TEST_F(RegexTest, Basics) {
+ Regex r1("^[0-9]+$");
+ EXPECT_TRUE(r1.match("916"));
+ EXPECT_TRUE(r1.match("9"));
+ EXPECT_FALSE(r1.match("9a"));
+
+ SmallVector<StringRef, 1> Matches;
+ Regex r2("[0-9]+");
+ EXPECT_TRUE(r2.match("aa216b", &Matches));
+ EXPECT_EQ(1u, Matches.size());
+ EXPECT_EQ("216", Matches[0].str());
+
+ Regex r3("[0-9]+([a-f])?:([0-9]+)");
+ EXPECT_TRUE(r3.match("9a:513b", &Matches));
+ EXPECT_EQ(3u, Matches.size());
+ EXPECT_EQ("9a:513", Matches[0].str());
+ EXPECT_EQ("a", Matches[1].str());
+ EXPECT_EQ("513", Matches[2].str());
+
+ EXPECT_TRUE(r3.match("9:513b", &Matches));
+ EXPECT_EQ(3u, Matches.size());
+ EXPECT_EQ("9:513", Matches[0].str());
+ EXPECT_EQ("", Matches[1].str());
+ EXPECT_EQ("513", Matches[2].str());
+
+ Regex r4("a[^b]+b");
+ std::string String="axxb";
+ String[2] = '\0';
+ EXPECT_FALSE(r4.match("abb"));
+ EXPECT_TRUE(r4.match(String, &Matches));
+ EXPECT_EQ(1u, Matches.size());
+ EXPECT_EQ(String, Matches[0].str());
+
+ std::string NulPattern="X[0-9]+X([a-f])?:([0-9]+)";
+ String="YX99a:513b";
+ NulPattern[7] = '\0';
+ Regex r5(NulPattern);
+ EXPECT_FALSE(r5.match(String));
+ EXPECT_FALSE(r5.match("X9"));
+ String[3]='\0';
+ EXPECT_TRUE(r5.match(String));
+}
+
+TEST_F(RegexTest, Backreferences) {
+ Regex r1("([a-z]+)_\\1");
+ SmallVector<StringRef, 4> Matches;
+ EXPECT_TRUE(r1.match("abc_abc", &Matches));
+ EXPECT_EQ(2u, Matches.size());
+ EXPECT_FALSE(r1.match("abc_ab", &Matches));
+
+ Regex r2("a([0-9])b\\1c\\1");
+ EXPECT_TRUE(r2.match("a4b4c4", &Matches));
+ EXPECT_EQ(2u, Matches.size());
+ EXPECT_EQ("4", Matches[1].str());
+ EXPECT_FALSE(r2.match("a2b2c3"));
+
+ Regex r3("a([0-9])([a-z])b\\1\\2");
+ EXPECT_TRUE(r3.match("a6zb6z", &Matches));
+ EXPECT_EQ(3u, Matches.size());
+ EXPECT_EQ("6", Matches[1].str());
+ EXPECT_EQ("z", Matches[2].str());
+ EXPECT_FALSE(r3.match("a6zb6y"));
+ EXPECT_FALSE(r3.match("a6zb7z"));
+}
+
+TEST_F(RegexTest, Substitution) {
+ std::string Error;
+
+ EXPECT_EQ("aNUMber", Regex("[0-9]+").sub("NUM", "a1234ber"));
+
+ // Standard Escapes
+ EXPECT_EQ("a\\ber", Regex("[0-9]+").sub("\\\\", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+ EXPECT_EQ("a\nber", Regex("[0-9]+").sub("\\n", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+ EXPECT_EQ("a\tber", Regex("[0-9]+").sub("\\t", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+ EXPECT_EQ("ajber", Regex("[0-9]+").sub("\\j", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+
+ EXPECT_EQ("aber", Regex("[0-9]+").sub("\\", "a1234ber", &Error));
+ EXPECT_EQ(Error, "replacement string contained trailing backslash");
+
+ // Backreferences
+ EXPECT_EQ("aa1234bber", Regex("a[0-9]+b").sub("a\\0b", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+
+ EXPECT_EQ("a1234ber", Regex("a([0-9]+)b").sub("a\\1b", "a1234ber", &Error));
+ EXPECT_EQ("", Error);
+
+ EXPECT_EQ("aber", Regex("a[0-9]+b").sub("a\\100b", "a1234ber", &Error));
+ EXPECT_EQ(Error, "invalid backreference string '100'");
+}
+
+TEST_F(RegexTest, IsLiteralERE) {
+ EXPECT_TRUE(Regex::isLiteralERE("abc"));
+ EXPECT_FALSE(Regex::isLiteralERE("a(bc)"));
+ EXPECT_FALSE(Regex::isLiteralERE("^abc"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc$"));
+ EXPECT_FALSE(Regex::isLiteralERE("a|bc"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc*"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc+"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc?"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc."));
+ EXPECT_FALSE(Regex::isLiteralERE("a[bc]"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc\\1"));
+ EXPECT_FALSE(Regex::isLiteralERE("abc{1,2}"));
+}
+
+TEST_F(RegexTest, Escape) {
+ EXPECT_EQ("a\\[bc\\]", Regex::escape("a[bc]"));
+ EXPECT_EQ("abc\\{1\\\\,2\\}", Regex::escape("abc{1\\,2}"));
+}
+
+TEST_F(RegexTest, IsValid) {
+ std::string Error;
+ EXPECT_FALSE(Regex("(foo").isValid(Error));
+ EXPECT_EQ("parentheses not balanced", Error);
+ EXPECT_FALSE(Regex("a[b-").isValid(Error));
+ EXPECT_EQ("invalid character range", Error);
+}
+
+TEST_F(RegexTest, MoveConstruct) {
+ Regex r1("^[0-9]+$");
+ Regex r2(std::move(r1));
+ EXPECT_TRUE(r2.match("916"));
+}
+
+TEST_F(RegexTest, MoveAssign) {
+ Regex r1("^[0-9]+$");
+ Regex r2("abc");
+ r2 = std::move(r1);
+ EXPECT_TRUE(r2.match("916"));
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/ReplaceFileTest.cpp b/gnu/llvm/unittests/Support/ReplaceFileTest.cpp
new file mode 100644
index 00000000000..8b16daf3233
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ReplaceFileTest.cpp
@@ -0,0 +1,113 @@
+//===- llvm/unittest/Support/ReplaceFileTest.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/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::sys;
+
+#define ASSERT_NO_ERROR(x) \
+ do { \
+ if (std::error_code ASSERT_NO_ERROR_ec = x) { \
+ errs() << #x ": did not return errc::success.\n" \
+ << "error number: " << ASSERT_NO_ERROR_ec.value() << "\n" \
+ << "error message: " << ASSERT_NO_ERROR_ec.message() << "\n"; \
+ } \
+ } while (false)
+
+namespace {
+std::error_code CreateFileWithContent(const SmallString<128> &FilePath,
+ const StringRef &content) {
+ int FD = 0;
+ if (std::error_code ec = fs::openFileForWrite(FilePath, FD, fs::F_None))
+ return ec;
+
+ const bool ShouldClose = true;
+ raw_fd_ostream OS(FD, ShouldClose);
+ OS << content;
+
+ return std::error_code();
+}
+
+class ScopedFD {
+ int FD;
+
+ ScopedFD(const ScopedFD &) = delete;
+ ScopedFD &operator=(const ScopedFD &) = delete;
+
+ public:
+ explicit ScopedFD(int Descriptor) : FD(Descriptor) {}
+ ~ScopedFD() { Process::SafelyCloseFileDescriptor(FD); }
+};
+
+TEST(rename, FileOpenedForReadingCanBeReplaced) {
+ // Create unique temporary directory for this test.
+ SmallString<128> TestDirectory;
+ ASSERT_NO_ERROR(fs::createUniqueDirectory(
+ "FileOpenedForReadingCanBeReplaced-test", TestDirectory));
+
+ // Add a couple of files to the test directory.
+ SmallString<128> SourceFileName(TestDirectory);
+ path::append(SourceFileName, "source");
+
+ SmallString<128> TargetFileName(TestDirectory);
+ path::append(TargetFileName, "target");
+
+ ASSERT_NO_ERROR(CreateFileWithContent(SourceFileName, "!!source!!"));
+ ASSERT_NO_ERROR(CreateFileWithContent(TargetFileName, "!!target!!"));
+
+ {
+ // Open the target file for reading.
+ int ReadFD = 0;
+ ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, ReadFD));
+ ScopedFD EventuallyCloseIt(ReadFD);
+
+ // Confirm we can replace the file while it is open.
+ EXPECT_TRUE(!fs::rename(SourceFileName, TargetFileName));
+
+ // We should still be able to read the old data through the existing
+ // descriptor.
+ auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1);
+ ASSERT_TRUE(static_cast<bool>(Buffer));
+ EXPECT_EQ(Buffer.get()->getBuffer(), "!!target!!");
+
+ // The source file should no longer exist
+ EXPECT_FALSE(fs::exists(SourceFileName));
+ }
+
+ {
+ // If we obtain a new descriptor for the target file, we should find that it
+ // contains the content that was in the source file.
+ int ReadFD = 0;
+ ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, ReadFD));
+ ScopedFD EventuallyCloseIt(ReadFD);
+ auto Buffer = MemoryBuffer::getOpenFile(ReadFD, TargetFileName, -1);
+ ASSERT_TRUE(static_cast<bool>(Buffer));
+
+ EXPECT_EQ(Buffer.get()->getBuffer(), "!!source!!");
+ }
+
+ // Rename the target file back to the source file name to confirm that rename
+ // still works if the destination does not already exist.
+ EXPECT_TRUE(!fs::rename(TargetFileName, SourceFileName));
+ EXPECT_FALSE(fs::exists(TargetFileName));
+ ASSERT_TRUE(fs::exists(SourceFileName));
+
+ // Clean up.
+ ASSERT_NO_ERROR(fs::remove(SourceFileName));
+ ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));
+}
+
+} // anonymous namespace
diff --git a/gnu/llvm/unittests/Support/ScaledNumberTest.cpp b/gnu/llvm/unittests/Support/ScaledNumberTest.cpp
new file mode 100644
index 00000000000..2f38b2a40fb
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ScaledNumberTest.cpp
@@ -0,0 +1,564 @@
+//===- llvm/unittest/Support/ScaledNumberTest.cpp - ScaledPair tests -----==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ScaledNumber.h"
+#include "llvm/Support/DataTypes.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace llvm::ScaledNumbers;
+
+namespace {
+
+template <class UIntT> struct ScaledPair {
+ UIntT D;
+ int S;
+ ScaledPair(const std::pair<UIntT, int16_t> &F) : D(F.first), S(F.second) {}
+ ScaledPair(UIntT D, int S) : D(D), S(S) {}
+
+ bool operator==(const ScaledPair<UIntT> &X) const {
+ return D == X.D && S == X.S;
+ }
+};
+template <class UIntT>
+bool operator==(const std::pair<UIntT, int16_t> &L,
+ const ScaledPair<UIntT> &R) {
+ return ScaledPair<UIntT>(L) == R;
+}
+template <class UIntT>
+void PrintTo(const ScaledPair<UIntT> &F, ::std::ostream *os) {
+ *os << F.D << "*2^" << F.S;
+}
+
+typedef ScaledPair<uint32_t> SP32;
+typedef ScaledPair<uint64_t> SP64;
+
+TEST(ScaledNumberHelpersTest, getRounded) {
+ EXPECT_EQ(getRounded32(0, 0, false), SP32(0, 0));
+ EXPECT_EQ(getRounded32(0, 0, true), SP32(1, 0));
+ EXPECT_EQ(getRounded32(20, 21, true), SP32(21, 21));
+ EXPECT_EQ(getRounded32(UINT32_MAX, 0, false), SP32(UINT32_MAX, 0));
+ EXPECT_EQ(getRounded32(UINT32_MAX, 0, true), SP32(1 << 31, 1));
+
+ EXPECT_EQ(getRounded64(0, 0, false), SP64(0, 0));
+ EXPECT_EQ(getRounded64(0, 0, true), SP64(1, 0));
+ EXPECT_EQ(getRounded64(20, 21, true), SP64(21, 21));
+ EXPECT_EQ(getRounded64(UINT32_MAX, 0, false), SP64(UINT32_MAX, 0));
+ EXPECT_EQ(getRounded64(UINT32_MAX, 0, true), SP64(UINT64_C(1) << 32, 0));
+ EXPECT_EQ(getRounded64(UINT64_MAX, 0, false), SP64(UINT64_MAX, 0));
+ EXPECT_EQ(getRounded64(UINT64_MAX, 0, true), SP64(UINT64_C(1) << 63, 1));
+}
+
+TEST(ScaledNumberHelpersTest, getAdjusted) {
+ const uint64_t Max32In64 = UINT32_MAX;
+ EXPECT_EQ(getAdjusted32(0), SP32(0, 0));
+ EXPECT_EQ(getAdjusted32(0, 5), SP32(0, 5));
+ EXPECT_EQ(getAdjusted32(UINT32_MAX), SP32(UINT32_MAX, 0));
+ EXPECT_EQ(getAdjusted32(Max32In64 << 1), SP32(UINT32_MAX, 1));
+ EXPECT_EQ(getAdjusted32(Max32In64 << 1, 1), SP32(UINT32_MAX, 2));
+ EXPECT_EQ(getAdjusted32(Max32In64 << 31), SP32(UINT32_MAX, 31));
+ EXPECT_EQ(getAdjusted32(Max32In64 << 32), SP32(UINT32_MAX, 32));
+ EXPECT_EQ(getAdjusted32(Max32In64 + 1), SP32(1u << 31, 1));
+ EXPECT_EQ(getAdjusted32(UINT64_MAX), SP32(1u << 31, 33));
+
+ EXPECT_EQ(getAdjusted64(0), SP64(0, 0));
+ EXPECT_EQ(getAdjusted64(0, 5), SP64(0, 5));
+ EXPECT_EQ(getAdjusted64(UINT32_MAX), SP64(UINT32_MAX, 0));
+ EXPECT_EQ(getAdjusted64(Max32In64 << 1), SP64(Max32In64 << 1, 0));
+ EXPECT_EQ(getAdjusted64(Max32In64 << 1, 1), SP64(Max32In64 << 1, 1));
+ EXPECT_EQ(getAdjusted64(Max32In64 << 31), SP64(Max32In64 << 31, 0));
+ EXPECT_EQ(getAdjusted64(Max32In64 << 32), SP64(Max32In64 << 32, 0));
+ EXPECT_EQ(getAdjusted64(Max32In64 + 1), SP64(Max32In64 + 1, 0));
+ EXPECT_EQ(getAdjusted64(UINT64_MAX), SP64(UINT64_MAX, 0));
+}
+
+TEST(ScaledNumberHelpersTest, getProduct) {
+ // Zero.
+ EXPECT_EQ(SP32(0, 0), getProduct32(0, 0));
+ EXPECT_EQ(SP32(0, 0), getProduct32(0, 1));
+ EXPECT_EQ(SP32(0, 0), getProduct32(0, 33));
+
+ // Basic.
+ EXPECT_EQ(SP32(6, 0), getProduct32(2, 3));
+ EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0),
+ getProduct32(UINT16_MAX / 3, UINT16_MAX / 5 * 2));
+
+ // Overflow, no loss of precision.
+ // ==> 0xf00010 * 0x1001
+ // ==> 0xf00f00000 + 0x10010
+ // ==> 0xf00f10010
+ // ==> 0xf00f1001 * 2^4
+ EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0xf00010, 0x1001));
+
+ // Overflow, loss of precision, rounds down.
+ // ==> 0xf000070 * 0x1001
+ // ==> 0xf00f000000 + 0x70070
+ // ==> 0xf00f070070
+ // ==> 0xf00f0700 * 2^8
+ EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0xf000070, 0x1001));
+
+ // Overflow, loss of precision, rounds up.
+ // ==> 0xf000080 * 0x1001
+ // ==> 0xf00f000000 + 0x80080
+ // ==> 0xf00f080080
+ // ==> 0xf00f0801 * 2^8
+ EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0xf000080, 0x1001));
+
+ // Reverse operand order.
+ EXPECT_EQ(SP32(0, 0), getProduct32(1, 0));
+ EXPECT_EQ(SP32(0, 0), getProduct32(33, 0));
+ EXPECT_EQ(SP32(6, 0), getProduct32(3, 2));
+ EXPECT_EQ(SP32(UINT16_MAX / 3 * UINT16_MAX / 5 * 2, 0),
+ getProduct32(UINT16_MAX / 5 * 2, UINT16_MAX / 3));
+ EXPECT_EQ(SP32(0xf00f1001, 4), getProduct32(0x1001, 0xf00010));
+ EXPECT_EQ(SP32(0xf00f0700, 8), getProduct32(0x1001, 0xf000070));
+ EXPECT_EQ(SP32(0xf00f0801, 8), getProduct32(0x1001, 0xf000080));
+
+ // Round to overflow.
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 64),
+ getProduct64(UINT64_C(10376293541461622786),
+ UINT64_C(16397105843297379211)));
+
+ // Big number with rounding.
+ EXPECT_EQ(SP64(UINT64_C(9223372036854775810), 64),
+ getProduct64(UINT64_C(18446744073709551556),
+ UINT64_C(9223372036854775840)));
+}
+
+TEST(ScaledNumberHelpersTest, getQuotient) {
+ // Zero.
+ EXPECT_EQ(SP32(0, 0), getQuotient32(0, 0));
+ EXPECT_EQ(SP32(0, 0), getQuotient32(0, 1));
+ EXPECT_EQ(SP32(0, 0), getQuotient32(0, 73));
+ EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(1, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, MaxScale), getQuotient32(6, 0));
+
+ // Powers of two.
+ EXPECT_EQ(SP32(1u << 31, -31), getQuotient32(1, 1));
+ EXPECT_EQ(SP32(1u << 31, -30), getQuotient32(2, 1));
+ EXPECT_EQ(SP32(1u << 31, -33), getQuotient32(4, 16));
+ EXPECT_EQ(SP32(7u << 29, -29), getQuotient32(7, 1));
+ EXPECT_EQ(SP32(7u << 29, -30), getQuotient32(7, 2));
+ EXPECT_EQ(SP32(7u << 29, -33), getQuotient32(7, 16));
+
+ // Divide evenly.
+ EXPECT_EQ(SP32(3u << 30, -30), getQuotient32(9, 3));
+ EXPECT_EQ(SP32(9u << 28, -28), getQuotient32(63, 7));
+
+ // Divide unevenly.
+ EXPECT_EQ(SP32(0xaaaaaaab, -33), getQuotient32(1, 3));
+ EXPECT_EQ(SP32(0xd5555555, -31), getQuotient32(5, 3));
+
+ // 64-bit division is hard to test, since divide64 doesn't canonicalize its
+ // output. However, this is the algorithm the implementation uses:
+ //
+ // - Shift divisor right.
+ // - If we have 1 (power of 2), return early -- not canonicalized.
+ // - Shift dividend left.
+ // - 64-bit integer divide.
+ // - If there's a remainder, continue with long division.
+ //
+ // TODO: require less knowledge about the implementation in the test.
+
+ // Zero.
+ EXPECT_EQ(SP64(0, 0), getQuotient64(0, 0));
+ EXPECT_EQ(SP64(0, 0), getQuotient64(0, 1));
+ EXPECT_EQ(SP64(0, 0), getQuotient64(0, 73));
+ EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(1, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, MaxScale), getQuotient64(6, 0));
+
+ // Powers of two.
+ EXPECT_EQ(SP64(1, 0), getQuotient64(1, 1));
+ EXPECT_EQ(SP64(2, 0), getQuotient64(2, 1));
+ EXPECT_EQ(SP64(4, -4), getQuotient64(4, 16));
+ EXPECT_EQ(SP64(7, 0), getQuotient64(7, 1));
+ EXPECT_EQ(SP64(7, -1), getQuotient64(7, 2));
+ EXPECT_EQ(SP64(7, -4), getQuotient64(7, 16));
+
+ // Divide evenly.
+ EXPECT_EQ(SP64(UINT64_C(3) << 60, -60), getQuotient64(9, 3));
+ EXPECT_EQ(SP64(UINT64_C(9) << 58, -58), getQuotient64(63, 7));
+
+ // Divide unevenly.
+ EXPECT_EQ(SP64(0xaaaaaaaaaaaaaaab, -65), getQuotient64(1, 3));
+ EXPECT_EQ(SP64(0xd555555555555555, -63), getQuotient64(5, 3));
+}
+
+TEST(ScaledNumberHelpersTest, getLg) {
+ EXPECT_EQ(0, getLg(UINT32_C(1), 0));
+ EXPECT_EQ(1, getLg(UINT32_C(1), 1));
+ EXPECT_EQ(1, getLg(UINT32_C(2), 0));
+ EXPECT_EQ(3, getLg(UINT32_C(1), 3));
+ EXPECT_EQ(3, getLg(UINT32_C(7), 0));
+ EXPECT_EQ(3, getLg(UINT32_C(8), 0));
+ EXPECT_EQ(3, getLg(UINT32_C(9), 0));
+ EXPECT_EQ(3, getLg(UINT32_C(64), -3));
+ EXPECT_EQ(31, getLg((UINT32_MAX >> 1) + 2, 0));
+ EXPECT_EQ(32, getLg(UINT32_MAX, 0));
+ EXPECT_EQ(-1, getLg(UINT32_C(1), -1));
+ EXPECT_EQ(-1, getLg(UINT32_C(2), -2));
+ EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLg(UINT32_C(0), 1));
+
+ EXPECT_EQ(0, getLg(UINT64_C(1), 0));
+ EXPECT_EQ(1, getLg(UINT64_C(1), 1));
+ EXPECT_EQ(1, getLg(UINT64_C(2), 0));
+ EXPECT_EQ(3, getLg(UINT64_C(1), 3));
+ EXPECT_EQ(3, getLg(UINT64_C(7), 0));
+ EXPECT_EQ(3, getLg(UINT64_C(8), 0));
+ EXPECT_EQ(3, getLg(UINT64_C(9), 0));
+ EXPECT_EQ(3, getLg(UINT64_C(64), -3));
+ EXPECT_EQ(63, getLg((UINT64_MAX >> 1) + 2, 0));
+ EXPECT_EQ(64, getLg(UINT64_MAX, 0));
+ EXPECT_EQ(-1, getLg(UINT64_C(1), -1));
+ EXPECT_EQ(-1, getLg(UINT64_C(2), -2));
+ EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLg(UINT64_C(0), 1));
+}
+
+TEST(ScaledNumberHelpersTest, getLgFloor) {
+ EXPECT_EQ(0, getLgFloor(UINT32_C(1), 0));
+ EXPECT_EQ(1, getLgFloor(UINT32_C(1), 1));
+ EXPECT_EQ(1, getLgFloor(UINT32_C(2), 0));
+ EXPECT_EQ(2, getLgFloor(UINT32_C(7), 0));
+ EXPECT_EQ(3, getLgFloor(UINT32_C(1), 3));
+ EXPECT_EQ(3, getLgFloor(UINT32_C(8), 0));
+ EXPECT_EQ(3, getLgFloor(UINT32_C(9), 0));
+ EXPECT_EQ(3, getLgFloor(UINT32_C(64), -3));
+ EXPECT_EQ(31, getLgFloor((UINT32_MAX >> 1) + 2, 0));
+ EXPECT_EQ(31, getLgFloor(UINT32_MAX, 0));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT32_C(0), 1));
+
+ EXPECT_EQ(0, getLgFloor(UINT64_C(1), 0));
+ EXPECT_EQ(1, getLgFloor(UINT64_C(1), 1));
+ EXPECT_EQ(1, getLgFloor(UINT64_C(2), 0));
+ EXPECT_EQ(2, getLgFloor(UINT64_C(7), 0));
+ EXPECT_EQ(3, getLgFloor(UINT64_C(1), 3));
+ EXPECT_EQ(3, getLgFloor(UINT64_C(8), 0));
+ EXPECT_EQ(3, getLgFloor(UINT64_C(9), 0));
+ EXPECT_EQ(3, getLgFloor(UINT64_C(64), -3));
+ EXPECT_EQ(63, getLgFloor((UINT64_MAX >> 1) + 2, 0));
+ EXPECT_EQ(63, getLgFloor(UINT64_MAX, 0));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLgFloor(UINT64_C(0), 1));
+}
+
+TEST(ScaledNumberHelpersTest, getLgCeiling) {
+ EXPECT_EQ(0, getLgCeiling(UINT32_C(1), 0));
+ EXPECT_EQ(1, getLgCeiling(UINT32_C(1), 1));
+ EXPECT_EQ(1, getLgCeiling(UINT32_C(2), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT32_C(1), 3));
+ EXPECT_EQ(3, getLgCeiling(UINT32_C(7), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT32_C(8), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT32_C(64), -3));
+ EXPECT_EQ(4, getLgCeiling(UINT32_C(9), 0));
+ EXPECT_EQ(32, getLgCeiling(UINT32_MAX, 0));
+ EXPECT_EQ(32, getLgCeiling((UINT32_MAX >> 1) + 2, 0));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT32_C(0), 1));
+
+ EXPECT_EQ(0, getLgCeiling(UINT64_C(1), 0));
+ EXPECT_EQ(1, getLgCeiling(UINT64_C(1), 1));
+ EXPECT_EQ(1, getLgCeiling(UINT64_C(2), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT64_C(1), 3));
+ EXPECT_EQ(3, getLgCeiling(UINT64_C(7), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT64_C(8), 0));
+ EXPECT_EQ(3, getLgCeiling(UINT64_C(64), -3));
+ EXPECT_EQ(4, getLgCeiling(UINT64_C(9), 0));
+ EXPECT_EQ(64, getLgCeiling((UINT64_MAX >> 1) + 2, 0));
+ EXPECT_EQ(64, getLgCeiling(UINT64_MAX, 0));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), -1));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 0));
+ EXPECT_EQ(INT32_MIN, getLgCeiling(UINT64_C(0), 1));
+}
+
+TEST(ScaledNumberHelpersTest, compare) {
+ EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 1));
+ EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), -10));
+ EXPECT_EQ(0, compare(UINT32_C(0), 0, UINT32_C(0), 20));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(64), -3));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(32), -2));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(16), -1));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(8), 0));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(4), 1));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(2), 2));
+ EXPECT_EQ(0, compare(UINT32_C(8), 0, UINT32_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT32_C(0), 0, UINT32_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT32_C(7), 0, UINT32_C(64), -3));
+ EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(1), 3));
+ EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(64), -3));
+ EXPECT_EQ(1, compare(UINT32_C(9), 0, UINT32_C(0), 0));
+
+ EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 1));
+ EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), -10));
+ EXPECT_EQ(0, compare(UINT64_C(0), 0, UINT64_C(0), 20));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(64), -3));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(32), -2));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(16), -1));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(8), 0));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(4), 1));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(2), 2));
+ EXPECT_EQ(0, compare(UINT64_C(8), 0, UINT64_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT64_C(0), 0, UINT64_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(1), 3));
+ EXPECT_EQ(-1, compare(UINT64_C(7), 0, UINT64_C(64), -3));
+ EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(1), 3));
+ EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(64), -3));
+ EXPECT_EQ(1, compare(UINT64_C(9), 0, UINT64_C(0), 0));
+ EXPECT_EQ(-1, compare(UINT64_MAX, 0, UINT64_C(1), 64));
+}
+
+TEST(ScaledNumberHelpersTest, matchScales) {
+#define MATCH_SCALES(T, LDIn, LSIn, RDIn, RSIn, LDOut, RDOut, SOut) \
+ do { \
+ T LDx = LDIn; \
+ T RDx = RDIn; \
+ T LDy = LDOut; \
+ T RDy = RDOut; \
+ int16_t LSx = LSIn; \
+ int16_t RSx = RSIn; \
+ int16_t Sy = SOut; \
+ \
+ EXPECT_EQ(SOut, matchScales(LDx, LSx, RDx, RSx)); \
+ EXPECT_EQ(LDy, LDx); \
+ EXPECT_EQ(RDy, RDx); \
+ if (LDy) \
+ EXPECT_EQ(Sy, LSx); \
+ if (RDy) \
+ EXPECT_EQ(Sy, RSx); \
+ } while (false)
+
+ MATCH_SCALES(uint32_t, 0, 0, 0, 0, 0, 0, 0);
+ MATCH_SCALES(uint32_t, 0, 50, 7, 1, 0, 7, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 1, 9, 0, UINT32_C(1) << 31, 4, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 2, 9, 0, UINT32_C(1) << 31, 2, 2);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 3, 9, 0, UINT32_C(1) << 31, 1, 3);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 31, 4, 9, 0, UINT32_C(1) << 31, 0, 4);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 30, 4, 9, 0, UINT32_C(1) << 31, 1, 3);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 29, 4, 9, 0, UINT32_C(1) << 31, 2, 2);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 28, 4, 9, 0, UINT32_C(1) << 31, 4, 1);
+ MATCH_SCALES(uint32_t, UINT32_C(1) << 27, 4, 9, 0, UINT32_C(1) << 31, 9, 0);
+ MATCH_SCALES(uint32_t, 7, 1, 0, 50, 7, 0, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 1, 4, UINT32_C(1) << 31, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 2, 2, UINT32_C(1) << 31, 2);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 3, 1, UINT32_C(1) << 31, 3);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 31, 4, 0, UINT32_C(1) << 31, 4);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 30, 4, 1, UINT32_C(1) << 31, 3);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 29, 4, 2, UINT32_C(1) << 31, 2);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 28, 4, 4, UINT32_C(1) << 31, 1);
+ MATCH_SCALES(uint32_t, 9, 0, UINT32_C(1) << 27, 4, 9, UINT32_C(1) << 31, 0);
+
+ MATCH_SCALES(uint64_t, 0, 0, 0, 0, 0, 0, 0);
+ MATCH_SCALES(uint64_t, 0, 100, 7, 1, 0, 7, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 1, 9, 0, UINT64_C(1) << 63, 4, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 2, 9, 0, UINT64_C(1) << 63, 2, 2);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 3, 9, 0, UINT64_C(1) << 63, 1, 3);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 63, 4, 9, 0, UINT64_C(1) << 63, 0, 4);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 62, 4, 9, 0, UINT64_C(1) << 63, 1, 3);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 61, 4, 9, 0, UINT64_C(1) << 63, 2, 2);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 60, 4, 9, 0, UINT64_C(1) << 63, 4, 1);
+ MATCH_SCALES(uint64_t, UINT64_C(1) << 59, 4, 9, 0, UINT64_C(1) << 63, 9, 0);
+ MATCH_SCALES(uint64_t, 7, 1, 0, 100, 7, 0, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 1, 4, UINT64_C(1) << 63, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 2, 2, UINT64_C(1) << 63, 2);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 3, 1, UINT64_C(1) << 63, 3);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 63, 4, 0, UINT64_C(1) << 63, 4);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 62, 4, 1, UINT64_C(1) << 63, 3);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 61, 4, 2, UINT64_C(1) << 63, 2);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 60, 4, 4, UINT64_C(1) << 63, 1);
+ MATCH_SCALES(uint64_t, 9, 0, UINT64_C(1) << 59, 4, 9, UINT64_C(1) << 63, 0);
+}
+
+TEST(ScaledNumberHelpersTest, getSum) {
+ // Zero.
+ EXPECT_EQ(SP32(1, 0), getSum32(0, 0, 1, 0));
+ EXPECT_EQ(SP32(8, -3), getSum32(0, 0, 8, -3));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(0, 0, UINT32_MAX, 0));
+
+ // Basic.
+ EXPECT_EQ(SP32(2, 0), getSum32(1, 0, 1, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 2, 0));
+ EXPECT_EQ(SP32(67, 0), getSum32(7, 0, 60, 0));
+
+ // Different scales.
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 0, 1, 1));
+ EXPECT_EQ(SP32(4, 0), getSum32(2, 0, 1, 1));
+
+ // Loss of precision.
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 32, 1, 0));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, -32, 1, 0));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 32, 1, 1));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -32, 1, -1));
+
+ // Overflow.
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, UINT32_MAX, 0));
+
+ // Reverse operand order.
+ EXPECT_EQ(SP32(1, 0), getSum32(1, 0, 0, 0));
+ EXPECT_EQ(SP32(8, -3), getSum32(8, -3, 0, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getSum32(UINT32_MAX, 0, 0, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(2, 0, 1, 0));
+ EXPECT_EQ(SP32(67, 0), getSum32(60, 0, 7, 0));
+ EXPECT_EQ(SP32(3, 0), getSum32(1, 1, 1, 0));
+ EXPECT_EQ(SP32(4, 0), getSum32(1, 1, 2, 0));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(1, 0, 1, 32));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, -31), getSum32(1, 0, 1, -32));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1), getSum32(1, 1, 1, 32));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -32), getSum32(1, -1, 1, -32));
+ EXPECT_EQ(SP32(UINT32_C(1) << 31, 1), getSum32(UINT32_MAX, 0, 1, 0));
+
+ // Zero.
+ EXPECT_EQ(SP64(1, 0), getSum64(0, 0, 1, 0));
+ EXPECT_EQ(SP64(8, -3), getSum64(0, 0, 8, -3));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(0, 0, UINT64_MAX, 0));
+
+ // Basic.
+ EXPECT_EQ(SP64(2, 0), getSum64(1, 0, 1, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 2, 0));
+ EXPECT_EQ(SP64(67, 0), getSum64(7, 0, 60, 0));
+
+ // Different scales.
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 0, 1, 1));
+ EXPECT_EQ(SP64(4, 0), getSum64(2, 0, 1, 1));
+
+ // Loss of precision.
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 64, 1, 0));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, -64, 1, 0));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 64, 1, 1));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -64, 1, -1));
+
+ // Overflow.
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, UINT64_MAX, 0));
+
+ // Reverse operand order.
+ EXPECT_EQ(SP64(1, 0), getSum64(1, 0, 0, 0));
+ EXPECT_EQ(SP64(8, -3), getSum64(8, -3, 0, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getSum64(UINT64_MAX, 0, 0, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(2, 0, 1, 0));
+ EXPECT_EQ(SP64(67, 0), getSum64(60, 0, 7, 0));
+ EXPECT_EQ(SP64(3, 0), getSum64(1, 1, 1, 0));
+ EXPECT_EQ(SP64(4, 0), getSum64(1, 1, 2, 0));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(1, 0, 1, 64));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, -63), getSum64(1, 0, 1, -64));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1), getSum64(1, 1, 1, 64));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -64), getSum64(1, -1, 1, -64));
+ EXPECT_EQ(SP64(UINT64_C(1) << 63, 1), getSum64(UINT64_MAX, 0, 1, 0));
+}
+
+TEST(ScaledNumberHelpersTest, getDifference) {
+ // Basic.
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 0));
+ EXPECT_EQ(SP32(1, 0), getDifference32(2, 0, 1, 0));
+ EXPECT_EQ(SP32(53, 0), getDifference32(60, 0, 7, 0));
+
+ // Equals "0", different scales.
+ EXPECT_EQ(SP32(0, 0), getDifference32(2, 0, 1, 1));
+
+ // Subtract "0".
+ EXPECT_EQ(SP32(1, 0), getDifference32(1, 0, 0, 0));
+ EXPECT_EQ(SP32(8, -3), getDifference32(8, -3, 0, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(UINT32_MAX, 0, 0, 0));
+
+ // Loss of precision.
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, 1),
+ getDifference32((UINT32_C(1) << 31) + 1, 1, 1, 0));
+ EXPECT_EQ(SP32((UINT32_C(1) << 31) + 1, -31),
+ getDifference32((UINT32_C(1) << 31) + 1, -31, 1, -32));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP32(UINT32_MAX, 0), getDifference32(1, 32, 1, 0));
+ EXPECT_EQ(SP32(UINT32_MAX, -32), getDifference32(1, 0, 1, -32));
+
+ // Saturate to "0".
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 1, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, 8, -3));
+ EXPECT_EQ(SP32(0, 0), getDifference32(0, 0, UINT32_MAX, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(7, 0, 60, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, 0, 1, 1));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, 0));
+ EXPECT_EQ(SP32(0, 0), getDifference32(1, -32, 1, -1));
+
+ // Regression tests for cases that failed during bringup.
+ EXPECT_EQ(SP32(UINT32_C(1) << 26, -31),
+ getDifference32(1, 0, UINT32_C(31) << 27, -32));
+
+ // Basic.
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 0));
+ EXPECT_EQ(SP64(1, 0), getDifference64(2, 0, 1, 0));
+ EXPECT_EQ(SP64(53, 0), getDifference64(60, 0, 7, 0));
+
+ // Equals "0", different scales.
+ EXPECT_EQ(SP64(0, 0), getDifference64(2, 0, 1, 1));
+
+ // Subtract "0".
+ EXPECT_EQ(SP64(1, 0), getDifference64(1, 0, 0, 0));
+ EXPECT_EQ(SP64(8, -3), getDifference64(8, -3, 0, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(UINT64_MAX, 0, 0, 0));
+
+ // Loss of precision.
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, 1),
+ getDifference64((UINT64_C(1) << 63) + 1, 1, 1, 0));
+ EXPECT_EQ(SP64((UINT64_C(1) << 63) + 1, -63),
+ getDifference64((UINT64_C(1) << 63) + 1, -63, 1, -64));
+
+ // Not quite loss of precision.
+ EXPECT_EQ(SP64(UINT64_MAX, 0), getDifference64(1, 64, 1, 0));
+ EXPECT_EQ(SP64(UINT64_MAX, -64), getDifference64(1, 0, 1, -64));
+
+ // Saturate to "0".
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 1, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, 8, -3));
+ EXPECT_EQ(SP64(0, 0), getDifference64(0, 0, UINT64_MAX, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(7, 0, 60, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, 0, 1, 1));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, 0));
+ EXPECT_EQ(SP64(0, 0), getDifference64(1, -64, 1, -1));
+}
+
+TEST(ScaledNumberHelpersTest, arithmeticOperators) {
+ EXPECT_EQ(ScaledNumber<uint32_t>(10, 0),
+ ScaledNumber<uint32_t>(1, 3) + ScaledNumber<uint32_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint32_t>(6, 0),
+ ScaledNumber<uint32_t>(1, 3) - ScaledNumber<uint32_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint32_t>(2, 3),
+ ScaledNumber<uint32_t>(1, 3) * ScaledNumber<uint32_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint32_t>(1, 2),
+ ScaledNumber<uint32_t>(1, 3) / ScaledNumber<uint32_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint32_t>(1, 2), ScaledNumber<uint32_t>(1, 3) >> 1);
+ EXPECT_EQ(ScaledNumber<uint32_t>(1, 4), ScaledNumber<uint32_t>(1, 3) << 1);
+
+ EXPECT_EQ(ScaledNumber<uint64_t>(10, 0),
+ ScaledNumber<uint64_t>(1, 3) + ScaledNumber<uint64_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint64_t>(6, 0),
+ ScaledNumber<uint64_t>(1, 3) - ScaledNumber<uint64_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint64_t>(2, 3),
+ ScaledNumber<uint64_t>(1, 3) * ScaledNumber<uint64_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint64_t>(1, 2),
+ ScaledNumber<uint64_t>(1, 3) / ScaledNumber<uint64_t>(1, 1));
+ EXPECT_EQ(ScaledNumber<uint64_t>(1, 2), ScaledNumber<uint64_t>(1, 3) >> 1);
+ EXPECT_EQ(ScaledNumber<uint64_t>(1, 4), ScaledNumber<uint64_t>(1, 3) << 1);
+}
+
+TEST(ScaledNumberHelpersTest, toIntBug) {
+ ScaledNumber<uint32_t> n(1, 0);
+ EXPECT_EQ(1u, (n * n).toInt<uint32_t>());
+}
+
+} // end namespace
diff --git a/gnu/llvm/unittests/Support/SourceMgrTest.cpp b/gnu/llvm/unittests/Support/SourceMgrTest.cpp
new file mode 100644
index 00000000000..79c2d7278f1
--- /dev/null
+++ b/gnu/llvm/unittests/Support/SourceMgrTest.cpp
@@ -0,0 +1,175 @@
+//===- unittests/Support/SourceMgrTest.cpp - SourceMgr tests --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class SourceMgrTest : public testing::Test {
+public:
+ SourceMgr SM;
+ unsigned MainBufferID;
+ std::string Output;
+
+ void setMainBuffer(StringRef Text, StringRef BufferName) {
+ std::unique_ptr<MemoryBuffer> MainBuffer =
+ MemoryBuffer::getMemBuffer(Text, BufferName);
+ MainBufferID = SM.AddNewSourceBuffer(std::move(MainBuffer), llvm::SMLoc());
+ }
+
+ SMLoc getLoc(unsigned Offset) {
+ return SMLoc::getFromPointer(
+ SM.getMemoryBuffer(MainBufferID)->getBufferStart() + Offset);
+ }
+
+ SMRange getRange(unsigned Offset, unsigned Length) {
+ return SMRange(getLoc(Offset), getLoc(Offset + Length));
+ }
+
+ void printMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
+ const Twine &Msg, ArrayRef<SMRange> Ranges,
+ ArrayRef<SMFixIt> FixIts) {
+ raw_string_ostream OS(Output);
+ SM.PrintMessage(OS, Loc, Kind, Msg, Ranges, FixIts);
+ }
+};
+
+} // unnamed namespace
+
+TEST_F(SourceMgrTest, BasicError) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicWarning) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Warning, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: warning: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicNote) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Note, "message", None, None);
+
+ EXPECT_EQ("file.in:1:5: note: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtEndOfLine) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(6), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:7: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, LocationAtNewline) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(7), SourceMgr::DK_Error, "message", None, None);
+
+ EXPECT_EQ("file.in:1:8: error: message\n"
+ "aaa bbb\n"
+ " ^\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, RangeWithTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(3, 3), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ~~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultiLineRange) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", getRange(4, 7), None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, MultipleRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(4, 3) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~ ^~~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, OverlappingRanges) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ SMRange Ranges[] = { getRange(0, 3), getRange(2, 4) };
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", Ranges, None);
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ "~~~~^~\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, BasicFixit) {
+ setMainBuffer("aaa bbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(4), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(4, 3), "zzz")));
+
+ EXPECT_EQ("file.in:1:5: error: message\n"
+ "aaa bbb\n"
+ " ^~~\n"
+ " zzz\n",
+ Output);
+}
+
+TEST_F(SourceMgrTest, FixitForTab) {
+ setMainBuffer("aaa\tbbb\nccc ddd\n", "file.in");
+ printMessage(getLoc(3), SourceMgr::DK_Error, "message", None,
+ makeArrayRef(SMFixIt(getRange(3, 1), "zzz")));
+
+ EXPECT_EQ("file.in:1:4: error: message\n"
+ "aaa bbb\n"
+ " ^^^^^\n"
+ " zzz\n",
+ Output);
+}
+
diff --git a/gnu/llvm/unittests/Support/SpecialCaseListTest.cpp b/gnu/llvm/unittests/Support/SpecialCaseListTest.cpp
new file mode 100644
index 00000000000..0657f8003e8
--- /dev/null
+++ b/gnu/llvm/unittests/Support/SpecialCaseListTest.cpp
@@ -0,0 +1,135 @@
+//===- SpecialCaseListTest.cpp - Unit tests for SpecialCaseList -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SpecialCaseList.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class SpecialCaseListTest : public ::testing::Test {
+protected:
+ std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List,
+ std::string &Error) {
+ std::unique_ptr<MemoryBuffer> MB = MemoryBuffer::getMemBuffer(List);
+ return SpecialCaseList::create(MB.get(), Error);
+ }
+
+ std::unique_ptr<SpecialCaseList> makeSpecialCaseList(StringRef List) {
+ std::string Error;
+ auto SCL = makeSpecialCaseList(List, Error);
+ assert(SCL);
+ assert(Error == "");
+ return SCL;
+ }
+
+ std::string makeSpecialCaseListFile(StringRef Contents) {
+ int FD;
+ SmallString<64> Path;
+ sys::fs::createTemporaryFile("SpecialCaseListTest", "temp", FD, Path);
+ raw_fd_ostream OF(FD, true, true);
+ OF << Contents;
+ OF.close();
+ return Path.str();
+ }
+};
+
+TEST_F(SpecialCaseListTest, Basic) {
+ std::unique_ptr<SpecialCaseList> SCL =
+ makeSpecialCaseList("# This is a comment.\n"
+ "\n"
+ "src:hello\n"
+ "src:bye\n"
+ "src:hi=category\n"
+ "src:z*=category\n");
+ EXPECT_TRUE(SCL->inSection("src", "hello"));
+ EXPECT_TRUE(SCL->inSection("src", "bye"));
+ EXPECT_TRUE(SCL->inSection("src", "hi", "category"));
+ EXPECT_TRUE(SCL->inSection("src", "zzzz", "category"));
+ EXPECT_FALSE(SCL->inSection("src", "hi"));
+ EXPECT_FALSE(SCL->inSection("fun", "hello"));
+ EXPECT_FALSE(SCL->inSection("src", "hello", "category"));
+}
+
+TEST_F(SpecialCaseListTest, GlobalInit) {
+ std::unique_ptr<SpecialCaseList> SCL =
+ makeSpecialCaseList("global:foo=init\n");
+ EXPECT_FALSE(SCL->inSection("global", "foo"));
+ EXPECT_FALSE(SCL->inSection("global", "bar"));
+ EXPECT_TRUE(SCL->inSection("global", "foo", "init"));
+ EXPECT_FALSE(SCL->inSection("global", "bar", "init"));
+
+ SCL = makeSpecialCaseList("type:t2=init\n");
+ EXPECT_FALSE(SCL->inSection("type", "t1"));
+ EXPECT_FALSE(SCL->inSection("type", "t2"));
+ EXPECT_FALSE(SCL->inSection("type", "t1", "init"));
+ EXPECT_TRUE(SCL->inSection("type", "t2", "init"));
+
+ SCL = makeSpecialCaseList("src:hello=init\n");
+ EXPECT_FALSE(SCL->inSection("src", "hello"));
+ EXPECT_FALSE(SCL->inSection("src", "bye"));
+ EXPECT_TRUE(SCL->inSection("src", "hello", "init"));
+ EXPECT_FALSE(SCL->inSection("src", "bye", "init"));
+}
+
+TEST_F(SpecialCaseListTest, Substring) {
+ std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:hello\n"
+ "fun:foo\n"
+ "global:bar\n");
+ EXPECT_FALSE(SCL->inSection("src", "othello"));
+ EXPECT_FALSE(SCL->inSection("fun", "tomfoolery"));
+ EXPECT_FALSE(SCL->inSection("global", "bartender"));
+
+ SCL = makeSpecialCaseList("fun:*foo*\n");
+ EXPECT_TRUE(SCL->inSection("fun", "tomfoolery"));
+ EXPECT_TRUE(SCL->inSection("fun", "foobar"));
+}
+
+TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {
+ std::string Error;
+ EXPECT_EQ(nullptr, makeSpecialCaseList("badline", Error));
+ EXPECT_EQ("malformed line 1: 'badline'", Error);
+ EXPECT_EQ(nullptr, makeSpecialCaseList("src:bad[a-", Error));
+ EXPECT_EQ("malformed regex in line 1: 'bad[a-': invalid character range",
+ Error);
+ EXPECT_EQ(nullptr, makeSpecialCaseList("src:a.c\n"
+ "fun:fun(a\n",
+ Error));
+ EXPECT_EQ("malformed regex in line 2: 'fun(a': parentheses not balanced",
+ Error);
+ std::vector<std::string> Files(1, "unexisting");
+ EXPECT_EQ(nullptr, SpecialCaseList::create(Files, Error));
+ EXPECT_EQ(0U, Error.find("can't open file 'unexisting':"));
+}
+
+TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {
+ std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("");
+ EXPECT_FALSE(SCL->inSection("foo", "bar"));
+}
+
+TEST_F(SpecialCaseListTest, MultipleBlacklists) {
+ std::vector<std::string> Files;
+ Files.push_back(makeSpecialCaseListFile("src:bar\n"
+ "src:*foo*\n"
+ "src:ban=init\n"));
+ Files.push_back(makeSpecialCaseListFile("src:baz\n"
+ "src:*fog*\n"));
+ auto SCL = SpecialCaseList::createOrDie(Files);
+ EXPECT_TRUE(SCL->inSection("src", "bar"));
+ EXPECT_TRUE(SCL->inSection("src", "baz"));
+ EXPECT_FALSE(SCL->inSection("src", "ban"));
+ EXPECT_TRUE(SCL->inSection("src", "ban", "init"));
+ EXPECT_TRUE(SCL->inSection("src", "tomfoolery"));
+ EXPECT_TRUE(SCL->inSection("src", "tomfoglery"));
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/StreamingMemoryObject.cpp b/gnu/llvm/unittests/Support/StreamingMemoryObject.cpp
new file mode 100644
index 00000000000..e86aa9cae51
--- /dev/null
+++ b/gnu/llvm/unittests/Support/StreamingMemoryObject.cpp
@@ -0,0 +1,39 @@
+//===- llvm/unittest/Support/StreamingMemoryObject.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/STLExtras.h"
+#include "llvm/Support/StreamingMemoryObject.h"
+#include "gtest/gtest.h"
+#include <string.h>
+
+using namespace llvm;
+
+namespace {
+class NullDataStreamer : public DataStreamer {
+ size_t GetBytes(unsigned char *buf, size_t len) override {
+ memset(buf, 0, len);
+ return len;
+ }
+};
+}
+
+TEST(StreamingMemoryObject, Test) {
+ auto DS = make_unique<NullDataStreamer>();
+ StreamingMemoryObject O(std::move(DS));
+ EXPECT_TRUE(O.isValidAddress(32 * 1024));
+}
+
+TEST(StreamingMemoryObject, TestSetKnownObjectSize) {
+ auto DS = make_unique<NullDataStreamer>();
+ StreamingMemoryObject O(std::move(DS));
+ uint8_t Buf[32];
+ EXPECT_EQ((uint64_t) 16, O.readBytes(Buf, 16, 0));
+ O.setKnownObjectSize(24);
+ EXPECT_EQ((uint64_t) 8, O.readBytes(Buf, 16, 16));
+}
diff --git a/gnu/llvm/unittests/Support/StringPool.cpp b/gnu/llvm/unittests/Support/StringPool.cpp
new file mode 100644
index 00000000000..ac39fec059e
--- /dev/null
+++ b/gnu/llvm/unittests/Support/StringPool.cpp
@@ -0,0 +1,31 @@
+//===- llvm/unittest/Support/StringPoiil.cpp - StringPool tests -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/StringPool.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(PooledStringPtrTest, OperatorEquals) {
+ StringPool pool;
+ const PooledStringPtr a = pool.intern("a");
+ const PooledStringPtr b = pool.intern("b");
+ EXPECT_FALSE(a == b);
+}
+
+TEST(PooledStringPtrTest, OperatorNotEquals) {
+ StringPool pool;
+ const PooledStringPtr a = pool.intern("a");
+ const PooledStringPtr b = pool.intern("b");
+ EXPECT_TRUE(a != b);
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/SwapByteOrderTest.cpp b/gnu/llvm/unittests/Support/SwapByteOrderTest.cpp
new file mode 100644
index 00000000000..4f2537c4d5d
--- /dev/null
+++ b/gnu/llvm/unittests/Support/SwapByteOrderTest.cpp
@@ -0,0 +1,201 @@
+//===- unittests/Support/SwapByteOrderTest.cpp - swap byte order test -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <cstdlib>
+#include <ctime>
+using namespace llvm;
+
+#undef max
+
+namespace {
+
+// In these first two tests all of the original_uintx values are truncated
+// except for 64. We could avoid this, but there's really no point.
+
+TEST(getSwappedBytes, UnsignedRoundTrip) {
+ // The point of the bit twiddling of magic is to test with and without bits
+ // in every byte.
+ uint64_t value = 1;
+ for (std::size_t i = 0; i <= sizeof(value); ++i) {
+ uint8_t original_uint8 = static_cast<uint8_t>(value);
+ EXPECT_EQ(original_uint8,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_uint8)));
+
+ uint16_t original_uint16 = static_cast<uint16_t>(value);
+ EXPECT_EQ(original_uint16,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_uint16)));
+
+ uint32_t original_uint32 = static_cast<uint32_t>(value);
+ EXPECT_EQ(original_uint32,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_uint32)));
+
+ uint64_t original_uint64 = static_cast<uint64_t>(value);
+ EXPECT_EQ(original_uint64,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_uint64)));
+
+ value = (value << 8) | 0x55; // binary 0101 0101.
+ }
+}
+
+TEST(getSwappedBytes, SignedRoundTrip) {
+ // The point of the bit twiddling of magic is to test with and without bits
+ // in every byte.
+ uint64_t value = 1;
+ for (std::size_t i = 0; i <= sizeof(value); ++i) {
+ int8_t original_int8 = static_cast<int8_t>(value);
+ EXPECT_EQ(original_int8,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
+
+ int16_t original_int16 = static_cast<int16_t>(value);
+ EXPECT_EQ(original_int16,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
+
+ int32_t original_int32 = static_cast<int32_t>(value);
+ EXPECT_EQ(original_int32,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
+
+ int64_t original_int64 = static_cast<int64_t>(value);
+ EXPECT_EQ(original_int64,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
+
+ // Test other sign.
+ value *= -1;
+
+ original_int8 = static_cast<int8_t>(value);
+ EXPECT_EQ(original_int8,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
+
+ original_int16 = static_cast<int16_t>(value);
+ EXPECT_EQ(original_int16,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
+
+ original_int32 = static_cast<int32_t>(value);
+ EXPECT_EQ(original_int32,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
+
+ original_int64 = static_cast<int64_t>(value);
+ EXPECT_EQ(original_int64,
+ sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
+
+ // Return to normal sign and twiddle.
+ value *= -1;
+ value = (value << 8) | 0x55; // binary 0101 0101.
+ }
+}
+
+TEST(getSwappedBytes, uint8_t) {
+ EXPECT_EQ(uint8_t(0x11), sys::getSwappedBytes(uint8_t(0x11)));
+}
+
+TEST(getSwappedBytes, uint16_t) {
+ EXPECT_EQ(uint16_t(0x1122), sys::getSwappedBytes(uint16_t(0x2211)));
+}
+
+TEST(getSwappedBytes, uint32_t) {
+ EXPECT_EQ(uint32_t(0x11223344), sys::getSwappedBytes(uint32_t(0x44332211)));
+}
+
+TEST(getSwappedBytes, uint64_t) {
+ EXPECT_EQ(uint64_t(0x1122334455667788ULL),
+ sys::getSwappedBytes(uint64_t(0x8877665544332211ULL)));
+}
+
+TEST(getSwappedBytes, int8_t) {
+ EXPECT_EQ(int8_t(0x11), sys::getSwappedBytes(int8_t(0x11)));
+}
+
+TEST(getSwappedBytes, int16_t) {
+ EXPECT_EQ(int16_t(0x1122), sys::getSwappedBytes(int16_t(0x2211)));
+}
+
+TEST(getSwappedBytes, int32_t) {
+ EXPECT_EQ(int32_t(0x11223344), sys::getSwappedBytes(int32_t(0x44332211)));
+}
+
+TEST(getSwappedBytes, int64_t) {
+ EXPECT_EQ(int64_t(0x1122334455667788LL),
+ sys::getSwappedBytes(int64_t(0x8877665544332211LL)));
+}
+
+TEST(getSwappedBytes, float) {
+ EXPECT_EQ(1.79366203433576585078237386661e-43f, sys::getSwappedBytes(-0.0f));
+ // 0x11223344
+ EXPECT_EQ(7.1653228759765625e2f, sys::getSwappedBytes(1.2795344e-28f));
+}
+
+TEST(getSwappedBytes, double) {
+ EXPECT_EQ(6.32404026676795576546008054871e-322, sys::getSwappedBytes(-0.0));
+ // 0x1122334455667788
+ EXPECT_EQ(-7.08687663657301358331704585496e-268,
+ sys::getSwappedBytes(3.84141202447173065923064450234e-226));
+}
+
+TEST(swapByteOrder, uint8_t) {
+ uint8_t value = 0x11;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(uint8_t(0x11), value);
+}
+
+TEST(swapByteOrder, uint16_t) {
+ uint16_t value = 0x2211;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(uint16_t(0x1122), value);
+}
+
+TEST(swapByteOrder, uint32_t) {
+ uint32_t value = 0x44332211;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(uint32_t(0x11223344), value);
+}
+
+TEST(swapByteOrder, uint64_t) {
+ uint64_t value = 0x8877665544332211ULL;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(uint64_t(0x1122334455667788ULL), value);
+}
+
+TEST(swapByteOrder, int8_t) {
+ int8_t value = 0x11;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(int8_t(0x11), value);
+}
+
+TEST(swapByteOrder, int16_t) {
+ int16_t value = 0x2211;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(int16_t(0x1122), value);
+}
+
+TEST(swapByteOrder, int32_t) {
+ int32_t value = 0x44332211;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(int32_t(0x11223344), value);
+}
+
+TEST(swapByteOrder, int64_t) {
+ int64_t value = 0x8877665544332211LL;
+ sys::swapByteOrder(value);
+ EXPECT_EQ(int64_t(0x1122334455667788LL), value);
+}
+
+TEST(swapByteOrder, float) {
+ float value = 7.1653228759765625e2f; // 0x44332211
+ sys::swapByteOrder(value);
+ EXPECT_EQ(1.2795344e-28f, value);
+}
+
+TEST(swapByteOrder, double) {
+ double value = -7.08687663657301358331704585496e-268; // 0x8877665544332211
+ sys::swapByteOrder(value);
+ EXPECT_EQ(3.84141202447173065923064450234e-226, value);
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/TargetRegistry.cpp b/gnu/llvm/unittests/Support/TargetRegistry.cpp
new file mode 100644
index 00000000000..ae89c8b6493
--- /dev/null
+++ b/gnu/llvm/unittests/Support/TargetRegistry.cpp
@@ -0,0 +1,42 @@
+//===- unittests/Support/TargetRegistry.cpp - -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(TargetRegistry, TargetHasArchType) {
+ // Presence of at least one target will be asserted when done with the loop,
+ // else this would pass by accident if InitializeAllTargetInfos were omitted.
+ int Count = 0;
+
+ llvm::InitializeAllTargetInfos();
+
+ for (const Target &T : TargetRegistry::targets()) {
+ StringRef Name = T.getName();
+ // There is really no way (at present) to ask a Target whether it targets
+ // a specific architecture, because the logic for that is buried in a
+ // predicate.
+ // We can't ask the predicate "Are you a function that always returns
+ // false?"
+ // So given that the cpp backend truly has no target arch, it is skipped.
+ if (Name != "cpp") {
+ Triple::ArchType Arch = Triple::getArchTypeForLLVMName(Name);
+ EXPECT_NE(Arch, Triple::UnknownArch);
+ ++Count;
+ }
+ }
+ ASSERT_NE(Count, 0);
+}
+
+} // end namespace
diff --git a/gnu/llvm/unittests/Support/ThreadLocalTest.cpp b/gnu/llvm/unittests/Support/ThreadLocalTest.cpp
new file mode 100644
index 00000000000..e71c7dba22f
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ThreadLocalTest.cpp
@@ -0,0 +1,57 @@
+//===- llvm/unittest/Support/ThreadLocalTest.cpp - ThreadLocal tests ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadLocal.h"
+#include "gtest/gtest.h"
+#include <type_traits>
+
+using namespace llvm;
+using namespace sys;
+
+namespace {
+
+class ThreadLocalTest : public ::testing::Test {
+};
+
+struct S {
+ int i;
+};
+
+TEST_F(ThreadLocalTest, Basics) {
+ ThreadLocal<const S> x;
+
+ static_assert(
+ std::is_const<std::remove_pointer<decltype(x.get())>::type>::value,
+ "ThreadLocal::get didn't return a pointer to const object");
+
+ EXPECT_EQ(nullptr, x.get());
+
+ S s;
+ x.set(&s);
+ EXPECT_EQ(&s, x.get());
+
+ x.erase();
+ EXPECT_EQ(nullptr, x.get());
+
+ ThreadLocal<S> y;
+
+ static_assert(
+ !std::is_const<std::remove_pointer<decltype(y.get())>::type>::value,
+ "ThreadLocal::get returned a pointer to const object");
+
+ EXPECT_EQ(nullptr, y.get());
+
+ y.set(&s);
+ EXPECT_EQ(&s, y.get());
+
+ y.erase();
+ EXPECT_EQ(nullptr, y.get());
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/ThreadPool.cpp b/gnu/llvm/unittests/Support/ThreadPool.cpp
new file mode 100644
index 00000000000..0f36c383d49
--- /dev/null
+++ b/gnu/llvm/unittests/Support/ThreadPool.cpp
@@ -0,0 +1,168 @@
+//========- unittests/Support/ThreadPools.cpp - ThreadPools.h tests --========//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/ThreadPool.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/TargetSelect.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+// Fixture for the unittests, allowing to *temporarily* disable the unittests
+// on a particular platform
+class ThreadPoolTest : public testing::Test {
+ Triple Host;
+ SmallVector<Triple::ArchType, 4> UnsupportedArchs;
+ SmallVector<Triple::OSType, 4> UnsupportedOSs;
+ SmallVector<Triple::EnvironmentType, 1> UnsupportedEnvironments;
+protected:
+ // This is intended for platform as a temporary "XFAIL"
+ bool isUnsupportedOSOrEnvironment() {
+ Triple Host(Triple::normalize(sys::getProcessTriple()));
+
+ if (std::find(UnsupportedEnvironments.begin(), UnsupportedEnvironments.end(),
+ Host.getEnvironment()) != UnsupportedEnvironments.end())
+ return true;
+
+ if (std::find(UnsupportedOSs.begin(), UnsupportedOSs.end(), Host.getOS())
+ != UnsupportedOSs.end())
+ return true;
+
+ if (std::find(UnsupportedArchs.begin(), UnsupportedArchs.end(), Host.getArch())
+ != UnsupportedArchs.end())
+ return true;
+
+ return false;
+ }
+
+ ThreadPoolTest() {
+ // Add unsupported configuration here, example:
+ // UnsupportedArchs.push_back(Triple::x86_64);
+
+ // See https://llvm.org/bugs/show_bug.cgi?id=25829
+ UnsupportedArchs.push_back(Triple::ppc64le);
+ UnsupportedArchs.push_back(Triple::ppc64);
+ }
+
+ /// Make sure this thread not progress faster than the main thread.
+ void waitForMainThread() {
+ std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
+ WaitMainThread.wait(LockGuard, [&] { return MainThreadReady; });
+ }
+
+ /// Set the readiness of the main thread.
+ void setMainThreadReady() {
+ {
+ std::unique_lock<std::mutex> LockGuard(WaitMainThreadMutex);
+ MainThreadReady = true;
+ }
+ WaitMainThread.notify_all();
+ }
+
+ void SetUp() override { MainThreadReady = false; }
+
+ std::condition_variable WaitMainThread;
+ std::mutex WaitMainThreadMutex;
+ bool MainThreadReady;
+
+};
+
+#define CHECK_UNSUPPORTED() \
+ do { \
+ if (isUnsupportedOSOrEnvironment()) \
+ return; \
+ } while (0); \
+
+TEST_F(ThreadPoolTest, AsyncBarrier) {
+ CHECK_UNSUPPORTED();
+ // test that async & barrier work together properly.
+
+ std::atomic_int checked_in{0};
+
+ ThreadPool Pool;
+ for (size_t i = 0; i < 5; ++i) {
+ Pool.async([this, &checked_in, i] {
+ waitForMainThread();
+ ++checked_in;
+ });
+ }
+ ASSERT_EQ(0, checked_in);
+ setMainThreadReady();
+ Pool.wait();
+ ASSERT_EQ(5, checked_in);
+}
+
+static void TestFunc(std::atomic_int &checked_in, int i) { checked_in += i; }
+
+TEST_F(ThreadPoolTest, AsyncBarrierArgs) {
+ CHECK_UNSUPPORTED();
+ // Test that async works with a function requiring multiple parameters.
+ std::atomic_int checked_in{0};
+
+ ThreadPool Pool;
+ for (size_t i = 0; i < 5; ++i) {
+ Pool.async(TestFunc, std::ref(checked_in), i);
+ }
+ Pool.wait();
+ ASSERT_EQ(10, checked_in);
+}
+
+TEST_F(ThreadPoolTest, Async) {
+ CHECK_UNSUPPORTED();
+ ThreadPool Pool;
+ std::atomic_int i{0};
+ Pool.async([this, &i] {
+ waitForMainThread();
+ ++i;
+ });
+ Pool.async([&i] { ++i; });
+ ASSERT_NE(2, i.load());
+ setMainThreadReady();
+ Pool.wait();
+ ASSERT_EQ(2, i.load());
+}
+
+TEST_F(ThreadPoolTest, GetFuture) {
+ CHECK_UNSUPPORTED();
+ ThreadPool Pool;
+ std::atomic_int i{0};
+ Pool.async([this, &i] {
+ waitForMainThread();
+ ++i;
+ });
+ // Force the future using get()
+ Pool.async([&i] { ++i; }).get();
+ ASSERT_NE(2, i.load());
+ setMainThreadReady();
+ Pool.wait();
+ ASSERT_EQ(2, i.load());
+}
+
+TEST_F(ThreadPoolTest, PoolDestruction) {
+ CHECK_UNSUPPORTED();
+ // Test that we are waiting on destruction
+ std::atomic_int checked_in{0};
+ {
+ ThreadPool Pool;
+ for (size_t i = 0; i < 5; ++i) {
+ Pool.async([this, &checked_in, i] {
+ waitForMainThread();
+ ++checked_in;
+ });
+ }
+ ASSERT_EQ(0, checked_in);
+ setMainThreadReady();
+ }
+ ASSERT_EQ(5, checked_in);
+}
diff --git a/gnu/llvm/unittests/Support/TimeValueTest.cpp b/gnu/llvm/unittests/Support/TimeValueTest.cpp
new file mode 100644
index 00000000000..3d2b9780c06
--- /dev/null
+++ b/gnu/llvm/unittests/Support/TimeValueTest.cpp
@@ -0,0 +1,40 @@
+//===- llvm/unittest/Support/TimeValueTest.cpp - Time Value tests ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/Support/TimeValue.h"
+#include <time.h>
+
+using namespace llvm;
+namespace {
+
+TEST(TimeValue, time_t) {
+ sys::TimeValue now = sys::TimeValue::now();
+ time_t now_t = time(nullptr);
+ EXPECT_TRUE(std::abs(static_cast<long>(now_t - now.toEpochTime())) < 2);
+}
+
+TEST(TimeValue, Win32FILETIME) {
+ uint64_t epoch_as_filetime = 0x19DB1DED53E8000ULL;
+ uint32_t ns = 765432100;
+ sys::TimeValue epoch;
+
+ // FILETIME has 100ns of intervals.
+ uint64_t ft1970 = epoch_as_filetime + ns / 100;
+ epoch.fromWin32Time(ft1970);
+
+ // The "seconds" part in Posix time may be expected as zero.
+ EXPECT_EQ(0u, epoch.toEpochTime());
+ EXPECT_EQ(ns, static_cast<uint32_t>(epoch.nanoseconds()));
+
+ // Confirm it reversible.
+ EXPECT_EQ(ft1970, epoch.toWin32Time());
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/TimerTest.cpp b/gnu/llvm/unittests/Support/TimerTest.cpp
new file mode 100644
index 00000000000..f556a3f72c6
--- /dev/null
+++ b/gnu/llvm/unittests/Support/TimerTest.cpp
@@ -0,0 +1,65 @@
+//===- unittests/TimerTest.cpp - Timer tests ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Timer.h"
+#include "gtest/gtest.h"
+
+#if LLVM_ON_WIN32
+#include <windows.h>
+#else
+#include <time.h>
+#endif
+
+using namespace llvm;
+
+namespace {
+
+// FIXME: Put this somewhere in Support, it's also used in LockFileManager.
+void SleepMS() {
+#if LLVM_ON_WIN32
+ Sleep(1);
+#else
+ struct timespec Interval;
+ Interval.tv_sec = 0;
+ Interval.tv_nsec = 1000000;
+ nanosleep(&Interval, nullptr);
+#endif
+}
+
+TEST(Timer, Additivity) {
+ Timer T1("T1");
+
+ EXPECT_TRUE(T1.isInitialized());
+
+ T1.startTimer();
+ T1.stopTimer();
+ auto TR1 = T1.getTotalTime();
+
+ T1.startTimer();
+ SleepMS();
+ T1.stopTimer();
+ auto TR2 = T1.getTotalTime();
+
+ EXPECT_TRUE(TR1 < TR2);
+}
+
+TEST(Timer, CheckIfTriggered) {
+ Timer T1("T1");
+
+ EXPECT_FALSE(T1.hasTriggered());
+ T1.startTimer();
+ EXPECT_TRUE(T1.hasTriggered());
+ T1.stopTimer();
+ EXPECT_TRUE(T1.hasTriggered());
+
+ T1.clear();
+ EXPECT_FALSE(T1.hasTriggered());
+}
+
+} // end anon namespace
diff --git a/gnu/llvm/unittests/Support/TrailingObjectsTest.cpp b/gnu/llvm/unittests/Support/TrailingObjectsTest.cpp
new file mode 100644
index 00000000000..866ff1e6e88
--- /dev/null
+++ b/gnu/llvm/unittests/Support/TrailingObjectsTest.cpp
@@ -0,0 +1,195 @@
+//=== - llvm/unittest/Support/TrailingObjectsTest.cpp ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/TrailingObjects.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+// This class, beyond being used by the test case, a nice
+// demonstration of the intended usage of TrailingObjects, with a
+// single trailing array.
+class Class1 final : protected TrailingObjects<Class1, short> {
+ friend TrailingObjects;
+
+ unsigned NumShorts;
+
+protected:
+ size_t numTrailingObjects(OverloadToken<short>) const { return NumShorts; }
+
+ Class1(int *ShortArray, unsigned NumShorts) : NumShorts(NumShorts) {
+ std::uninitialized_copy(ShortArray, ShortArray + NumShorts,
+ getTrailingObjects<short>());
+ }
+
+public:
+ static Class1 *create(int *ShortArray, unsigned NumShorts) {
+ void *Mem = ::operator new(totalSizeToAlloc<short>(NumShorts));
+ return new (Mem) Class1(ShortArray, NumShorts);
+ }
+
+ short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; }
+
+ unsigned numShorts() const { return NumShorts; }
+
+ // Pull some protected members in as public, for testability.
+ using TrailingObjects::totalSizeToAlloc;
+ using TrailingObjects::additionalSizeToAlloc;
+ using TrailingObjects::getTrailingObjects;
+};
+
+// Here, there are two singular optional object types appended. Note
+// that the alignment of Class2 is automatically increased to account
+// for the alignment requirements of the trailing objects.
+class Class2 final : protected TrailingObjects<Class2, double, short> {
+ friend TrailingObjects;
+
+ bool HasShort, HasDouble;
+
+protected:
+ size_t numTrailingObjects(OverloadToken<short>) const {
+ return HasShort ? 1 : 0;
+ }
+ size_t numTrailingObjects(OverloadToken<double>) const {
+ return HasDouble ? 1 : 0;
+ }
+
+ Class2(bool HasShort, bool HasDouble)
+ : HasShort(HasShort), HasDouble(HasDouble) {}
+
+public:
+ static Class2 *create(short S = 0, double D = 0.0) {
+ bool HasShort = S != 0;
+ bool HasDouble = D != 0.0;
+
+ void *Mem =
+ ::operator new(totalSizeToAlloc<double, short>(HasDouble, HasShort));
+ Class2 *C = new (Mem) Class2(HasShort, HasDouble);
+ if (HasShort)
+ *C->getTrailingObjects<short>() = S;
+ if (HasDouble)
+ *C->getTrailingObjects<double>() = D;
+ return C;
+ }
+
+ short getShort() const {
+ if (!HasShort)
+ return 0;
+ return *getTrailingObjects<short>();
+ }
+
+ double getDouble() const {
+ if (!HasDouble)
+ return 0.0;
+ return *getTrailingObjects<double>();
+ }
+
+ // Pull some protected members in as public, for testability.
+ using TrailingObjects::totalSizeToAlloc;
+ using TrailingObjects::additionalSizeToAlloc;
+ using TrailingObjects::getTrailingObjects;
+};
+
+TEST(TrailingObjects, OneArg) {
+ int arr[] = {1, 2, 3};
+ Class1 *C = Class1::create(arr, 3);
+ EXPECT_EQ(sizeof(Class1), sizeof(unsigned));
+ EXPECT_EQ(Class1::additionalSizeToAlloc<short>(1), sizeof(short));
+ EXPECT_EQ(Class1::additionalSizeToAlloc<short>(3), sizeof(short) * 3);
+
+ EXPECT_EQ(Class1::totalSizeToAlloc<short>(1), sizeof(Class1) + sizeof(short));
+ EXPECT_EQ(Class1::totalSizeToAlloc<short>(3),
+ sizeof(Class1) + sizeof(short) * 3);
+
+ EXPECT_EQ(C->getTrailingObjects<short>(), reinterpret_cast<short *>(C + 1));
+ EXPECT_EQ(C->get(0), 1);
+ EXPECT_EQ(C->get(2), 3);
+ delete C;
+}
+
+TEST(TrailingObjects, TwoArg) {
+ Class2 *C1 = Class2::create(4);
+ Class2 *C2 = Class2::create(0, 4.2);
+
+ EXPECT_EQ(sizeof(Class2), llvm::RoundUpToAlignment(sizeof(bool) * 2,
+ llvm::alignOf<double>()));
+ EXPECT_EQ(llvm::alignOf<Class2>(), llvm::alignOf<double>());
+
+ EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(1, 0)),
+ sizeof(double));
+ EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(0, 1)),
+ sizeof(short));
+ EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(3, 1)),
+ sizeof(double) * 3 + sizeof(short));
+
+ EXPECT_EQ((Class2::totalSizeToAlloc<double, short>(1, 1)),
+ sizeof(Class2) + sizeof(double) + sizeof(short));
+
+ EXPECT_EQ(C1->getDouble(), 0);
+ EXPECT_EQ(C1->getShort(), 4);
+ EXPECT_EQ(C1->getTrailingObjects<double>(),
+ reinterpret_cast<double *>(C1 + 1));
+ EXPECT_EQ(C1->getTrailingObjects<short>(), reinterpret_cast<short *>(C1 + 1));
+
+ EXPECT_EQ(C2->getDouble(), 4.2);
+ EXPECT_EQ(C2->getShort(), 0);
+ EXPECT_EQ(C2->getTrailingObjects<double>(),
+ reinterpret_cast<double *>(C2 + 1));
+ EXPECT_EQ(C2->getTrailingObjects<short>(),
+ reinterpret_cast<short *>(reinterpret_cast<double *>(C2 + 1) + 1));
+ delete C1;
+ delete C2;
+}
+
+// This test class is not trying to be a usage demo, just asserting
+// that three args does actually work too (it's the same code as
+// handles the second arg, so it's basically covered by the above, but
+// just in case..)
+class Class3 final : public TrailingObjects<Class3, double, short, bool> {
+ friend TrailingObjects;
+
+ size_t numTrailingObjects(OverloadToken<double>) const { return 1; }
+ size_t numTrailingObjects(OverloadToken<short>) const { return 1; }
+};
+
+TEST(TrailingObjects, ThreeArg) {
+ EXPECT_EQ((Class3::additionalSizeToAlloc<double, short, bool>(1, 1, 3)),
+ sizeof(double) + sizeof(short) + 3 * sizeof(bool));
+ EXPECT_EQ(sizeof(Class3),
+ llvm::RoundUpToAlignment(1, llvm::alignOf<double>()));
+ std::unique_ptr<char[]> P(new char[1000]);
+ Class3 *C = reinterpret_cast<Class3 *>(P.get());
+ EXPECT_EQ(C->getTrailingObjects<double>(), reinterpret_cast<double *>(C + 1));
+ EXPECT_EQ(C->getTrailingObjects<short>(),
+ reinterpret_cast<short *>(reinterpret_cast<double *>(C + 1) + 1));
+ EXPECT_EQ(
+ C->getTrailingObjects<bool>(),
+ reinterpret_cast<bool *>(
+ reinterpret_cast<short *>(reinterpret_cast<double *>(C + 1) + 1) +
+ 1));
+}
+
+class Class4 final : public TrailingObjects<Class4, char, long> {
+ friend TrailingObjects;
+ size_t numTrailingObjects(OverloadToken<char>) const { return 1; }
+};
+
+TEST(TrailingObjects, Realignment) {
+ EXPECT_EQ((Class4::additionalSizeToAlloc<char, long>(1, 1)),
+ llvm::RoundUpToAlignment(sizeof(long) + 1, llvm::alignOf<long>()));
+ EXPECT_EQ(sizeof(Class4), llvm::RoundUpToAlignment(1, llvm::alignOf<long>()));
+ std::unique_ptr<char[]> P(new char[1000]);
+ Class4 *C = reinterpret_cast<Class4 *>(P.get());
+ EXPECT_EQ(C->getTrailingObjects<char>(), reinterpret_cast<char *>(C + 1));
+ EXPECT_EQ(C->getTrailingObjects<long>(),
+ reinterpret_cast<long *>(llvm::alignAddr(
+ reinterpret_cast<char *>(C + 1) + 1, llvm::alignOf<long>())));
+}
+}
diff --git a/gnu/llvm/unittests/Support/UnicodeTest.cpp b/gnu/llvm/unittests/Support/UnicodeTest.cpp
new file mode 100644
index 00000000000..0733397d45c
--- /dev/null
+++ b/gnu/llvm/unittests/Support/UnicodeTest.cpp
@@ -0,0 +1,93 @@
+//===- unittests/Support/UnicodeTest.cpp - Unicode.h tests ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/Unicode.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+namespace sys {
+namespace unicode {
+namespace {
+
+TEST(Unicode, columnWidthUTF8) {
+ EXPECT_EQ(0, columnWidthUTF8(""));
+ EXPECT_EQ(1, columnWidthUTF8(" "));
+ EXPECT_EQ(1, columnWidthUTF8("a"));
+ EXPECT_EQ(1, columnWidthUTF8("~"));
+
+ EXPECT_EQ(6, columnWidthUTF8("abcdef"));
+
+ EXPECT_EQ(-1, columnWidthUTF8("\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("aaaaaaaaaa\x01"));
+ EXPECT_EQ(-1, columnWidthUTF8("\342\200\213")); // 200B ZERO WIDTH SPACE
+
+ // 00AD SOFT HYPHEN is displayed on most terminals as a space or a dash. Some
+ // text editors display it only when a line is broken at it, some use it as a
+ // line-break hint, but don't display. We choose terminal-oriented
+ // interpretation.
+ EXPECT_EQ(1, columnWidthUTF8("\302\255"));
+
+ EXPECT_EQ(0, columnWidthUTF8("\314\200")); // 0300 COMBINING GRAVE ACCENT
+ EXPECT_EQ(1, columnWidthUTF8("\340\270\201")); // 0E01 THAI CHARACTER KO KAI
+ EXPECT_EQ(2, columnWidthUTF8("\344\270\200")); // CJK UNIFIED IDEOGRAPH-4E00
+
+ EXPECT_EQ(4, columnWidthUTF8("\344\270\200\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("q\344\270\200"));
+ EXPECT_EQ(3, columnWidthUTF8("\314\200\340\270\201\344\270\200"));
+
+ // Invalid UTF-8 strings, columnWidthUTF8 should error out.
+ EXPECT_EQ(-2, columnWidthUTF8("\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("\377\366\355"));
+
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\033"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\344\270\300"));
+ EXPECT_EQ(-2, columnWidthUTF8("qwer\377\366\355"));
+
+ // UTF-8 sequences longer than 4 bytes correspond to unallocated Unicode
+ // characters.
+ EXPECT_EQ(-2, columnWidthUTF8("\370\200\200\200\200")); // U+200000
+ EXPECT_EQ(-2, columnWidthUTF8("\374\200\200\200\200\200")); // U+4000000
+}
+
+TEST(Unicode, isPrintable) {
+ EXPECT_FALSE(isPrintable(0)); // <control-0000>-<control-001F>
+ EXPECT_FALSE(isPrintable(0x01));
+ EXPECT_FALSE(isPrintable(0x1F));
+ EXPECT_TRUE(isPrintable(' '));
+ EXPECT_TRUE(isPrintable('A'));
+ EXPECT_TRUE(isPrintable('~'));
+ EXPECT_FALSE(isPrintable(0x7F)); // <control-007F>..<control-009F>
+ EXPECT_FALSE(isPrintable(0x90));
+ EXPECT_FALSE(isPrintable(0x9F));
+
+ EXPECT_TRUE(isPrintable(0xAC));
+ EXPECT_TRUE(isPrintable(0xAD)); // SOFT HYPHEN is displayed on most terminals
+ // as either a space or a dash.
+ EXPECT_TRUE(isPrintable(0xAE));
+
+ EXPECT_TRUE(isPrintable(0x0377)); // GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+ EXPECT_FALSE(isPrintable(0x0378)); // <reserved-0378>..<reserved-0379>
+
+ EXPECT_FALSE(isPrintable(0x0600)); // ARABIC NUMBER SIGN
+
+ EXPECT_FALSE(isPrintable(0x1FFFF)); // <reserved-1F774>..<noncharacter-1FFFF>
+ EXPECT_TRUE(isPrintable(0x20000)); // CJK UNIFIED IDEOGRAPH-20000
+
+ EXPECT_FALSE(isPrintable(0x10FFFF)); // noncharacter
+}
+
+} // namespace
+} // namespace unicode
+} // namespace sys
+} // namespace llvm
diff --git a/gnu/llvm/unittests/Support/YAMLIOTest.cpp b/gnu/llvm/unittests/Support/YAMLIOTest.cpp
new file mode 100644
index 00000000000..e7affa1698d
--- /dev/null
+++ b/gnu/llvm/unittests/Support/YAMLIOTest.cpp
@@ -0,0 +1,2196 @@
+//===- unittest/Support/YAMLIOTest.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/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "gtest/gtest.h"
+
+
+using llvm::yaml::Input;
+using llvm::yaml::Output;
+using llvm::yaml::IO;
+using llvm::yaml::MappingTraits;
+using llvm::yaml::MappingNormalization;
+using llvm::yaml::ScalarTraits;
+using llvm::yaml::Hex8;
+using llvm::yaml::Hex16;
+using llvm::yaml::Hex32;
+using llvm::yaml::Hex64;
+
+
+
+
+static void suppressErrorMessages(const llvm::SMDiagnostic &, void *) {
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Test MappingTraits
+//===----------------------------------------------------------------------===//
+
+struct FooBar {
+ int foo;
+ int bar;
+};
+typedef std::vector<FooBar> FooBarSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(FooBar)
+
+struct FooBarContainer {
+ FooBarSequence fbs;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<FooBar> {
+ static void mapping(IO &io, FooBar& fb) {
+ io.mapRequired("foo", fb.foo);
+ io.mapRequired("bar", fb.bar);
+ }
+ };
+
+ template <> struct MappingTraits<FooBarContainer> {
+ static void mapping(IO &io, FooBarContainer &fb) {
+ io.mapRequired("fbs", fb.fbs);
+ }
+ };
+}
+}
+
+
+//
+// Test the reading of a yaml mapping
+//
+TEST(YAMLIO, TestMapRead) {
+ FooBar doc;
+ {
+ Input yin("---\nfoo: 3\nbar: 5\n...\n");
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+
+ {
+ Input yin("{foo: 3, bar: 5}");
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar, 5);
+ }
+}
+
+TEST(YAMLIO, TestMalformedMapRead) {
+ FooBar doc;
+ Input yin("{foo: 3; bar: 5}", nullptr, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test the reading of a yaml sequence of mappings
+//
+TEST(YAMLIO, TestSequenceMapRead) {
+ FooBarSequence seq;
+ Input yin("---\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n");
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq.size(), 2UL);
+ FooBar& map1 = seq[0];
+ FooBar& map2 = seq[1];
+ EXPECT_EQ(map1.foo, 3);
+ EXPECT_EQ(map1.bar, 5);
+ EXPECT_EQ(map2.foo, 7);
+ EXPECT_EQ(map2.bar, 9);
+}
+
+//
+// Test the reading of a map containing a yaml sequence of mappings
+//
+TEST(YAMLIO, TestContainerSequenceMapRead) {
+ {
+ FooBarContainer cont;
+ Input yin2("---\nfbs:\n - foo: 3\n bar: 5\n - foo: 7\n bar: 9\n...\n");
+ yin2 >> cont;
+
+ EXPECT_FALSE(yin2.error());
+ EXPECT_EQ(cont.fbs.size(), 2UL);
+ EXPECT_EQ(cont.fbs[0].foo, 3);
+ EXPECT_EQ(cont.fbs[0].bar, 5);
+ EXPECT_EQ(cont.fbs[1].foo, 7);
+ EXPECT_EQ(cont.fbs[1].bar, 9);
+ }
+
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs:\n...\n");
+ yin >> cont;
+ // Okay: Empty node represents an empty array.
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs: !!null null\n...\n");
+ yin >> cont;
+ // Okay: null represents an empty array.
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs: ~\n...\n");
+ yin >> cont;
+ // Okay: null represents an empty array.
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs: null\n...\n");
+ yin >> cont;
+ // Okay: null represents an empty array.
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+}
+
+//
+// Test the reading of a map containing a malformed yaml sequence
+//
+TEST(YAMLIO, TestMalformedContainerSequenceMapRead) {
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs:\n foo: 3\n bar: 5\n...\n", nullptr,
+ suppressErrorMessages);
+ yin >> cont;
+ // Error: fbs is not a sequence.
+ EXPECT_TRUE(!!yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+
+ {
+ FooBarContainer cont;
+ Input yin("---\nfbs: 'scalar'\n...\n", nullptr, suppressErrorMessages);
+ yin >> cont;
+ // This should be an error.
+ EXPECT_TRUE(!!yin.error());
+ EXPECT_EQ(cont.fbs.size(), 0UL);
+ }
+}
+
+//
+// Test writing then reading back a sequence of mappings
+//
+TEST(YAMLIO, TestSequenceMapWriteAndRead) {
+ std::string intermediate;
+ {
+ FooBar entry1;
+ entry1.foo = 10;
+ entry1.bar = -3;
+ FooBar entry2;
+ entry2.foo = 257;
+ entry2.bar = 0;
+ FooBarSequence seq;
+ seq.push_back(entry1);
+ seq.push_back(entry2);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << seq;
+ }
+
+ {
+ Input yin(intermediate);
+ FooBarSequence seq2;
+ yin >> seq2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq2.size(), 2UL);
+ FooBar& map1 = seq2[0];
+ FooBar& map2 = seq2[1];
+ EXPECT_EQ(map1.foo, 10);
+ EXPECT_EQ(map1.bar, -3);
+ EXPECT_EQ(map2.foo, 257);
+ EXPECT_EQ(map2.bar, 0);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test built-in types
+//===----------------------------------------------------------------------===//
+
+struct BuiltInTypes {
+ llvm::StringRef str;
+ std::string stdstr;
+ uint64_t u64;
+ uint32_t u32;
+ uint16_t u16;
+ uint8_t u8;
+ bool b;
+ int64_t s64;
+ int32_t s32;
+ int16_t s16;
+ int8_t s8;
+ float f;
+ double d;
+ Hex8 h8;
+ Hex16 h16;
+ Hex32 h32;
+ Hex64 h64;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<BuiltInTypes> {
+ static void mapping(IO &io, BuiltInTypes& bt) {
+ io.mapRequired("str", bt.str);
+ io.mapRequired("stdstr", bt.stdstr);
+ io.mapRequired("u64", bt.u64);
+ io.mapRequired("u32", bt.u32);
+ io.mapRequired("u16", bt.u16);
+ io.mapRequired("u8", bt.u8);
+ io.mapRequired("b", bt.b);
+ io.mapRequired("s64", bt.s64);
+ io.mapRequired("s32", bt.s32);
+ io.mapRequired("s16", bt.s16);
+ io.mapRequired("s8", bt.s8);
+ io.mapRequired("f", bt.f);
+ io.mapRequired("d", bt.d);
+ io.mapRequired("h8", bt.h8);
+ io.mapRequired("h16", bt.h16);
+ io.mapRequired("h32", bt.h32);
+ io.mapRequired("h64", bt.h64);
+ }
+ };
+}
+}
+
+
+//
+// Test the reading of all built-in scalar conversions
+//
+TEST(YAMLIO, TestReadBuiltInTypes) {
+ BuiltInTypes map;
+ Input yin("---\n"
+ "str: hello there\n"
+ "stdstr: hello where?\n"
+ "u64: 5000000000\n"
+ "u32: 4000000000\n"
+ "u16: 65000\n"
+ "u8: 255\n"
+ "b: false\n"
+ "s64: -5000000000\n"
+ "s32: -2000000000\n"
+ "s16: -32000\n"
+ "s8: -127\n"
+ "f: 137.125\n"
+ "d: -2.8625\n"
+ "h8: 0xFF\n"
+ "h16: 0x8765\n"
+ "h32: 0xFEDCBA98\n"
+ "h64: 0xFEDCBA9876543210\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map.str.equals("hello there"));
+ EXPECT_TRUE(map.stdstr == "hello where?");
+ EXPECT_EQ(map.u64, 5000000000ULL);
+ EXPECT_EQ(map.u32, 4000000000U);
+ EXPECT_EQ(map.u16, 65000);
+ EXPECT_EQ(map.u8, 255);
+ EXPECT_EQ(map.b, false);
+ EXPECT_EQ(map.s64, -5000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.s8, -127);
+ EXPECT_EQ(map.f, 137.125);
+ EXPECT_EQ(map.d, -2.8625);
+ EXPECT_EQ(map.h8, Hex8(255));
+ EXPECT_EQ(map.h16, Hex16(0x8765));
+ EXPECT_EQ(map.h32, Hex32(0xFEDCBA98));
+ EXPECT_EQ(map.h64, Hex64(0xFEDCBA9876543210LL));
+}
+
+
+//
+// Test writing then reading back all built-in scalar types
+//
+TEST(YAMLIO, TestReadWriteBuiltInTypes) {
+ std::string intermediate;
+ {
+ BuiltInTypes map;
+ map.str = "one two";
+ map.stdstr = "three four";
+ map.u64 = 6000000000ULL;
+ map.u32 = 3000000000U;
+ map.u16 = 50000;
+ map.u8 = 254;
+ map.b = true;
+ map.s64 = -6000000000LL;
+ map.s32 = -2000000000;
+ map.s16 = -32000;
+ map.s8 = -128;
+ map.f = 3.25;
+ map.d = -2.8625;
+ map.h8 = 254;
+ map.h16 = 50000;
+ map.h32 = 3000000000U;
+ map.h64 = 6000000000LL;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ BuiltInTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map.str.equals("one two"));
+ EXPECT_TRUE(map.stdstr == "three four");
+ EXPECT_EQ(map.u64, 6000000000ULL);
+ EXPECT_EQ(map.u32, 3000000000U);
+ EXPECT_EQ(map.u16, 50000);
+ EXPECT_EQ(map.u8, 254);
+ EXPECT_EQ(map.b, true);
+ EXPECT_EQ(map.s64, -6000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.s8, -128);
+ EXPECT_EQ(map.f, 3.25);
+ EXPECT_EQ(map.d, -2.8625);
+ EXPECT_EQ(map.h8, Hex8(254));
+ EXPECT_EQ(map.h16, Hex16(50000));
+ EXPECT_EQ(map.h32, Hex32(3000000000U));
+ EXPECT_EQ(map.h64, Hex64(6000000000LL));
+ }
+}
+
+struct StringTypes {
+ llvm::StringRef str1;
+ llvm::StringRef str2;
+ llvm::StringRef str3;
+ llvm::StringRef str4;
+ llvm::StringRef str5;
+ llvm::StringRef str6;
+ llvm::StringRef str7;
+ llvm::StringRef str8;
+ llvm::StringRef str9;
+ llvm::StringRef str10;
+ llvm::StringRef str11;
+ std::string stdstr1;
+ std::string stdstr2;
+ std::string stdstr3;
+ std::string stdstr4;
+ std::string stdstr5;
+ std::string stdstr6;
+ std::string stdstr7;
+ std::string stdstr8;
+ std::string stdstr9;
+ std::string stdstr10;
+ std::string stdstr11;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<StringTypes> {
+ static void mapping(IO &io, StringTypes& st) {
+ io.mapRequired("str1", st.str1);
+ io.mapRequired("str2", st.str2);
+ io.mapRequired("str3", st.str3);
+ io.mapRequired("str4", st.str4);
+ io.mapRequired("str5", st.str5);
+ io.mapRequired("str6", st.str6);
+ io.mapRequired("str7", st.str7);
+ io.mapRequired("str8", st.str8);
+ io.mapRequired("str9", st.str9);
+ io.mapRequired("str10", st.str10);
+ io.mapRequired("str11", st.str11);
+ io.mapRequired("stdstr1", st.stdstr1);
+ io.mapRequired("stdstr2", st.stdstr2);
+ io.mapRequired("stdstr3", st.stdstr3);
+ io.mapRequired("stdstr4", st.stdstr4);
+ io.mapRequired("stdstr5", st.stdstr5);
+ io.mapRequired("stdstr6", st.stdstr6);
+ io.mapRequired("stdstr7", st.stdstr7);
+ io.mapRequired("stdstr8", st.stdstr8);
+ io.mapRequired("stdstr9", st.stdstr9);
+ io.mapRequired("stdstr10", st.stdstr10);
+ io.mapRequired("stdstr11", st.stdstr11);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, TestReadWriteStringTypes) {
+ std::string intermediate;
+ {
+ StringTypes map;
+ map.str1 = "'aaa";
+ map.str2 = "\"bbb";
+ map.str3 = "`ccc";
+ map.str4 = "@ddd";
+ map.str5 = "";
+ map.str6 = "0000000004000000";
+ map.str7 = "true";
+ map.str8 = "FALSE";
+ map.str9 = "~";
+ map.str10 = "0.2e20";
+ map.str11 = "0x30";
+ map.stdstr1 = "'eee";
+ map.stdstr2 = "\"fff";
+ map.stdstr3 = "`ggg";
+ map.stdstr4 = "@hhh";
+ map.stdstr5 = "";
+ map.stdstr6 = "0000000004000000";
+ map.stdstr7 = "true";
+ map.stdstr8 = "FALSE";
+ map.stdstr9 = "~";
+ map.stdstr10 = "0.2e20";
+ map.stdstr11 = "0x30";
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'''aaa"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'\"bbb'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'`ccc'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'@ddd'"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("''\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0000000004000000'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'true'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'FALSE'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'~'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0.2e20'\n"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("'0x30'\n"));
+ EXPECT_NE(std::string::npos, flowOut.find("'''eee"));
+ EXPECT_NE(std::string::npos, flowOut.find("'\"fff'"));
+ EXPECT_NE(std::string::npos, flowOut.find("'`ggg'"));
+ EXPECT_NE(std::string::npos, flowOut.find("'@hhh'"));
+ EXPECT_NE(std::string::npos, flowOut.find("''\n"));
+ EXPECT_NE(std::string::npos, flowOut.find("'0000000004000000'\n"));
+
+ {
+ Input yin(intermediate);
+ StringTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map.str1.equals("'aaa"));
+ EXPECT_TRUE(map.str2.equals("\"bbb"));
+ EXPECT_TRUE(map.str3.equals("`ccc"));
+ EXPECT_TRUE(map.str4.equals("@ddd"));
+ EXPECT_TRUE(map.str5.equals(""));
+ EXPECT_TRUE(map.str6.equals("0000000004000000"));
+ EXPECT_TRUE(map.stdstr1 == "'eee");
+ EXPECT_TRUE(map.stdstr2 == "\"fff");
+ EXPECT_TRUE(map.stdstr3 == "`ggg");
+ EXPECT_TRUE(map.stdstr4 == "@hhh");
+ EXPECT_TRUE(map.stdstr5 == "");
+ EXPECT_TRUE(map.stdstr6 == "0000000004000000");
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Test ScalarEnumerationTraits
+//===----------------------------------------------------------------------===//
+
+enum Colors {
+ cRed,
+ cBlue,
+ cGreen,
+ cYellow
+};
+
+struct ColorMap {
+ Colors c1;
+ Colors c2;
+ Colors c3;
+ Colors c4;
+ Colors c5;
+ Colors c6;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct ScalarEnumerationTraits<Colors> {
+ static void enumeration(IO &io, Colors &value) {
+ io.enumCase(value, "red", cRed);
+ io.enumCase(value, "blue", cBlue);
+ io.enumCase(value, "green", cGreen);
+ io.enumCase(value, "yellow",cYellow);
+ }
+ };
+ template <>
+ struct MappingTraits<ColorMap> {
+ static void mapping(IO &io, ColorMap& c) {
+ io.mapRequired("c1", c.c1);
+ io.mapRequired("c2", c.c2);
+ io.mapRequired("c3", c.c3);
+ io.mapOptional("c4", c.c4, cBlue); // supplies default
+ io.mapOptional("c5", c.c5, cYellow); // supplies default
+ io.mapOptional("c6", c.c6, cRed); // supplies default
+ }
+ };
+}
+}
+
+
+//
+// Test reading enumerated scalars
+//
+TEST(YAMLIO, TestEnumRead) {
+ ColorMap map;
+ Input yin("---\n"
+ "c1: blue\n"
+ "c2: red\n"
+ "c3: green\n"
+ "c5: yellow\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(cBlue, map.c1);
+ EXPECT_EQ(cRed, map.c2);
+ EXPECT_EQ(cGreen, map.c3);
+ EXPECT_EQ(cBlue, map.c4); // tests default
+ EXPECT_EQ(cYellow,map.c5); // tests overridden
+ EXPECT_EQ(cRed, map.c6); // tests default
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Test ScalarBitSetTraits
+//===----------------------------------------------------------------------===//
+
+enum MyFlags {
+ flagNone = 0,
+ flagBig = 1 << 0,
+ flagFlat = 1 << 1,
+ flagRound = 1 << 2,
+ flagPointy = 1 << 3
+};
+inline MyFlags operator|(MyFlags a, MyFlags b) {
+ return static_cast<MyFlags>(
+ static_cast<uint32_t>(a) | static_cast<uint32_t>(b));
+}
+
+struct FlagsMap {
+ MyFlags f1;
+ MyFlags f2;
+ MyFlags f3;
+ MyFlags f4;
+};
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct ScalarBitSetTraits<MyFlags> {
+ static void bitset(IO &io, MyFlags &value) {
+ io.bitSetCase(value, "big", flagBig);
+ io.bitSetCase(value, "flat", flagFlat);
+ io.bitSetCase(value, "round", flagRound);
+ io.bitSetCase(value, "pointy",flagPointy);
+ }
+ };
+ template <>
+ struct MappingTraits<FlagsMap> {
+ static void mapping(IO &io, FlagsMap& c) {
+ io.mapRequired("f1", c.f1);
+ io.mapRequired("f2", c.f2);
+ io.mapRequired("f3", c.f3);
+ io.mapOptional("f4", c.f4, MyFlags(flagRound));
+ }
+ };
+}
+}
+
+
+//
+// Test reading flow sequence representing bit-mask values
+//
+TEST(YAMLIO, TestFlagsRead) {
+ FlagsMap map;
+ Input yin("---\n"
+ "f1: [ big ]\n"
+ "f2: [ round, flat ]\n"
+ "f3: []\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(flagBig, map.f1);
+ EXPECT_EQ(flagRound|flagFlat, map.f2);
+ EXPECT_EQ(flagNone, map.f3); // check empty set
+ EXPECT_EQ(flagRound, map.f4); // check optional key
+}
+
+
+//
+// Test writing then reading back bit-mask values
+//
+TEST(YAMLIO, TestReadWriteFlags) {
+ std::string intermediate;
+ {
+ FlagsMap map;
+ map.f1 = flagBig;
+ map.f2 = flagRound | flagFlat;
+ map.f3 = flagNone;
+ map.f4 = flagNone;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ FlagsMap map2;
+ yin >> map2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(flagBig, map2.f1);
+ EXPECT_EQ(flagRound|flagFlat, map2.f2);
+ EXPECT_EQ(flagNone, map2.f3);
+ //EXPECT_EQ(flagRound, map2.f4); // check optional key
+ }
+}
+
+
+
+//===----------------------------------------------------------------------===//
+// Test ScalarTraits
+//===----------------------------------------------------------------------===//
+
+struct MyCustomType {
+ int length;
+ int width;
+};
+
+struct MyCustomTypeMap {
+ MyCustomType f1;
+ MyCustomType f2;
+ int f3;
+};
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MyCustomTypeMap> {
+ static void mapping(IO &io, MyCustomTypeMap& s) {
+ io.mapRequired("f1", s.f1);
+ io.mapRequired("f2", s.f2);
+ io.mapRequired("f3", s.f3);
+ }
+ };
+ // MyCustomType is formatted as a yaml scalar. A value of
+ // {length=3, width=4} would be represented in yaml as "3 by 4".
+ template<>
+ struct ScalarTraits<MyCustomType> {
+ static void output(const MyCustomType &value, void* ctxt, llvm::raw_ostream &out) {
+ out << llvm::format("%d by %d", value.length, value.width);
+ }
+ static StringRef input(StringRef scalar, void* ctxt, MyCustomType &value) {
+ size_t byStart = scalar.find("by");
+ if ( byStart != StringRef::npos ) {
+ StringRef lenStr = scalar.slice(0, byStart);
+ lenStr = lenStr.rtrim();
+ if ( lenStr.getAsInteger(0, value.length) ) {
+ return "malformed length";
+ }
+ StringRef widthStr = scalar.drop_front(byStart+2);
+ widthStr = widthStr.ltrim();
+ if ( widthStr.getAsInteger(0, value.width) ) {
+ return "malformed width";
+ }
+ return StringRef();
+ }
+ else {
+ return "malformed by";
+ }
+ }
+ static bool mustQuote(StringRef) { return true; }
+ };
+}
+}
+
+
+//
+// Test writing then reading back custom values
+//
+TEST(YAMLIO, TestReadWriteMyCustomType) {
+ std::string intermediate;
+ {
+ MyCustomTypeMap map;
+ map.f1.length = 1;
+ map.f1.width = 4;
+ map.f2.length = 100;
+ map.f2.width = 400;
+ map.f3 = 10;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ MyCustomTypeMap map2;
+ yin >> map2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(1, map2.f1.length);
+ EXPECT_EQ(4, map2.f1.width);
+ EXPECT_EQ(100, map2.f2.length);
+ EXPECT_EQ(400, map2.f2.width);
+ EXPECT_EQ(10, map2.f3);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test BlockScalarTraits
+//===----------------------------------------------------------------------===//
+
+struct MultilineStringType {
+ std::string str;
+};
+
+struct MultilineStringTypeMap {
+ MultilineStringType name;
+ MultilineStringType description;
+ MultilineStringType ingredients;
+ MultilineStringType recipes;
+ MultilineStringType warningLabels;
+ MultilineStringType documentation;
+ int price;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MultilineStringTypeMap> {
+ static void mapping(IO &io, MultilineStringTypeMap& s) {
+ io.mapRequired("name", s.name);
+ io.mapRequired("description", s.description);
+ io.mapRequired("ingredients", s.ingredients);
+ io.mapRequired("recipes", s.recipes);
+ io.mapRequired("warningLabels", s.warningLabels);
+ io.mapRequired("documentation", s.documentation);
+ io.mapRequired("price", s.price);
+ }
+ };
+
+ // MultilineStringType is formatted as a yaml block literal scalar. A value of
+ // "Hello\nWorld" would be represented in yaml as
+ // |
+ // Hello
+ // World
+ template <>
+ struct BlockScalarTraits<MultilineStringType> {
+ static void output(const MultilineStringType &value, void *ctxt,
+ llvm::raw_ostream &out) {
+ out << value.str;
+ }
+ static StringRef input(StringRef scalar, void *ctxt,
+ MultilineStringType &value) {
+ value.str = scalar.str();
+ return StringRef();
+ }
+ };
+}
+}
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MultilineStringType)
+
+//
+// Test writing then reading back custom values
+//
+TEST(YAMLIO, TestReadWriteMultilineStringType) {
+ std::string intermediate;
+ {
+ MultilineStringTypeMap map;
+ map.name.str = "An Item";
+ map.description.str = "Hello\nWorld";
+ map.ingredients.str = "SubItem 1\nSub Item 2\n\nSub Item 3\n";
+ map.recipes.str = "\n\nTest 1\n\n\n";
+ map.warningLabels.str = "";
+ map.documentation.str = "\n\n";
+ map.price = 350;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+ {
+ Input yin(intermediate);
+ MultilineStringTypeMap map2;
+ yin >> map2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(map2.name.str, "An Item\n");
+ EXPECT_EQ(map2.description.str, "Hello\nWorld\n");
+ EXPECT_EQ(map2.ingredients.str, "SubItem 1\nSub Item 2\n\nSub Item 3\n");
+ EXPECT_EQ(map2.recipes.str, "\n\nTest 1\n");
+ EXPECT_TRUE(map2.warningLabels.str.empty());
+ EXPECT_TRUE(map2.documentation.str.empty());
+ EXPECT_EQ(map2.price, 350);
+ }
+}
+
+//
+// Test writing then reading back custom values
+//
+TEST(YAMLIO, TestReadWriteBlockScalarDocuments) {
+ std::string intermediate;
+ {
+ std::vector<MultilineStringType> documents;
+ MultilineStringType doc;
+ doc.str = "Hello\nWorld";
+ documents.push_back(doc);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << documents;
+
+ // Verify that the block scalar header was written out on the same line
+ // as the document marker.
+ EXPECT_NE(llvm::StringRef::npos, llvm::StringRef(ostr.str()).find("--- |"));
+ }
+ {
+ Input yin(intermediate);
+ std::vector<MultilineStringType> documents2;
+ yin >> documents2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(documents2.size(), size_t(1));
+ EXPECT_EQ(documents2[0].str, "Hello\nWorld\n");
+ }
+}
+
+TEST(YAMLIO, TestReadWriteBlockScalarValue) {
+ std::string intermediate;
+ {
+ MultilineStringType doc;
+ doc.str = "Just a block\nscalar doc";
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << doc;
+ }
+ {
+ Input yin(intermediate);
+ MultilineStringType doc;
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.str, "Just a block\nscalar doc\n");
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Test flow sequences
+//===----------------------------------------------------------------------===//
+
+LLVM_YAML_STRONG_TYPEDEF(int, MyNumber)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(MyNumber)
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::StringRef)
+
+namespace llvm {
+namespace yaml {
+ template<>
+ struct ScalarTraits<MyNumber> {
+ static void output(const MyNumber &value, void *, llvm::raw_ostream &out) {
+ out << value;
+ }
+
+ static StringRef input(StringRef scalar, void *, MyNumber &value) {
+ long long n;
+ if ( getAsSignedInteger(scalar, 0, n) )
+ return "invalid number";
+ value = n;
+ return StringRef();
+ }
+
+ static bool mustQuote(StringRef) { return false; }
+ };
+}
+}
+
+struct NameAndNumbers {
+ llvm::StringRef name;
+ std::vector<llvm::StringRef> strings;
+ std::vector<MyNumber> single;
+ std::vector<MyNumber> numbers;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<NameAndNumbers> {
+ static void mapping(IO &io, NameAndNumbers& nn) {
+ io.mapRequired("name", nn.name);
+ io.mapRequired("strings", nn.strings);
+ io.mapRequired("single", nn.single);
+ io.mapRequired("numbers", nn.numbers);
+ }
+ };
+}
+}
+
+typedef std::vector<MyNumber> MyNumberFlowSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(MyNumberFlowSequence)
+
+struct NameAndNumbersFlow {
+ llvm::StringRef name;
+ std::vector<MyNumberFlowSequence> sequenceOfNumbers;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<NameAndNumbersFlow> {
+ static void mapping(IO &io, NameAndNumbersFlow& nn) {
+ io.mapRequired("name", nn.name);
+ io.mapRequired("sequenceOfNumbers", nn.sequenceOfNumbers);
+ }
+ };
+}
+}
+
+//
+// Test writing then reading back custom values
+//
+TEST(YAMLIO, TestReadWriteMyFlowSequence) {
+ std::string intermediate;
+ {
+ NameAndNumbers map;
+ map.name = "hello";
+ map.strings.push_back(llvm::StringRef("one"));
+ map.strings.push_back(llvm::StringRef("two"));
+ map.single.push_back(1);
+ map.numbers.push_back(10);
+ map.numbers.push_back(-30);
+ map.numbers.push_back(1024);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+
+ // Verify sequences were written in flow style
+ ostr.flush();
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("one, two"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("10, -30, 1024"));
+ }
+
+ {
+ Input yin(intermediate);
+ NameAndNumbers map2;
+ yin >> map2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map2.name.equals("hello"));
+ EXPECT_EQ(map2.strings.size(), 2UL);
+ EXPECT_TRUE(map2.strings[0].equals("one"));
+ EXPECT_TRUE(map2.strings[1].equals("two"));
+ EXPECT_EQ(map2.single.size(), 1UL);
+ EXPECT_EQ(1, map2.single[0]);
+ EXPECT_EQ(map2.numbers.size(), 3UL);
+ EXPECT_EQ(10, map2.numbers[0]);
+ EXPECT_EQ(-30, map2.numbers[1]);
+ EXPECT_EQ(1024, map2.numbers[2]);
+ }
+}
+
+
+//
+// Test writing then reading back a sequence of flow sequences.
+//
+TEST(YAMLIO, TestReadWriteSequenceOfMyFlowSequence) {
+ std::string intermediate;
+ {
+ NameAndNumbersFlow map;
+ map.name = "hello";
+ MyNumberFlowSequence single = { 0 };
+ MyNumberFlowSequence numbers = { 12, 1, -512 };
+ map.sequenceOfNumbers.push_back(single);
+ map.sequenceOfNumbers.push_back(numbers);
+ map.sequenceOfNumbers.push_back(MyNumberFlowSequence());
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+
+ // Verify sequences were written in flow style
+ // and that the parent sequence used '-'.
+ ostr.flush();
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 0 ]"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ 12, 1, -512 ]"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- [ ]"));
+ }
+
+ {
+ Input yin(intermediate);
+ NameAndNumbersFlow map2;
+ yin >> map2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(map2.name.equals("hello"));
+ EXPECT_EQ(map2.sequenceOfNumbers.size(), 3UL);
+ EXPECT_EQ(map2.sequenceOfNumbers[0].size(), 1UL);
+ EXPECT_EQ(0, map2.sequenceOfNumbers[0][0]);
+ EXPECT_EQ(map2.sequenceOfNumbers[1].size(), 3UL);
+ EXPECT_EQ(12, map2.sequenceOfNumbers[1][0]);
+ EXPECT_EQ(1, map2.sequenceOfNumbers[1][1]);
+ EXPECT_EQ(-512, map2.sequenceOfNumbers[1][2]);
+ EXPECT_TRUE(map2.sequenceOfNumbers[2].empty());
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Test normalizing/denormalizing
+//===----------------------------------------------------------------------===//
+
+LLVM_YAML_STRONG_TYPEDEF(uint32_t, TotalSeconds)
+
+typedef std::vector<TotalSeconds> SecondsSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(TotalSeconds)
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<TotalSeconds> {
+
+ class NormalizedSeconds {
+ public:
+ NormalizedSeconds(IO &io)
+ : hours(0), minutes(0), seconds(0) {
+ }
+ NormalizedSeconds(IO &, TotalSeconds &secs)
+ : hours(secs/3600),
+ minutes((secs - (hours*3600))/60),
+ seconds(secs % 60) {
+ }
+ TotalSeconds denormalize(IO &) {
+ return TotalSeconds(hours*3600 + minutes*60 + seconds);
+ }
+
+ uint32_t hours;
+ uint8_t minutes;
+ uint8_t seconds;
+ };
+
+ static void mapping(IO &io, TotalSeconds &secs) {
+ MappingNormalization<NormalizedSeconds, TotalSeconds> keys(io, secs);
+
+ io.mapOptional("hours", keys->hours, (uint32_t)0);
+ io.mapOptional("minutes", keys->minutes, (uint8_t)0);
+ io.mapRequired("seconds", keys->seconds);
+ }
+ };
+}
+}
+
+
+//
+// Test the reading of a yaml sequence of mappings
+//
+TEST(YAMLIO, TestReadMySecondsSequence) {
+ SecondsSequence seq;
+ Input yin("---\n - hours: 1\n seconds: 5\n - seconds: 59\n...\n");
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq.size(), 2UL);
+ EXPECT_EQ(seq[0], 3605U);
+ EXPECT_EQ(seq[1], 59U);
+}
+
+
+//
+// Test writing then reading back custom values
+//
+TEST(YAMLIO, TestReadWriteMySecondsSequence) {
+ std::string intermediate;
+ {
+ SecondsSequence seq;
+ seq.push_back(4000);
+ seq.push_back(500);
+ seq.push_back(59);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << seq;
+ }
+ {
+ Input yin(intermediate);
+ SecondsSequence seq2;
+ yin >> seq2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq2.size(), 3UL);
+ EXPECT_EQ(seq2[0], 4000U);
+ EXPECT_EQ(seq2[1], 500U);
+ EXPECT_EQ(seq2[2], 59U);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test dynamic typing
+//===----------------------------------------------------------------------===//
+
+enum AFlags {
+ a1,
+ a2,
+ a3
+};
+
+enum BFlags {
+ b1,
+ b2,
+ b3
+};
+
+enum Kind {
+ kindA,
+ kindB
+};
+
+struct KindAndFlags {
+ KindAndFlags() : kind(kindA), flags(0) { }
+ KindAndFlags(Kind k, uint32_t f) : kind(k), flags(f) { }
+ Kind kind;
+ uint32_t flags;
+};
+
+typedef std::vector<KindAndFlags> KindAndFlagsSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(KindAndFlags)
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct ScalarEnumerationTraits<AFlags> {
+ static void enumeration(IO &io, AFlags &value) {
+ io.enumCase(value, "a1", a1);
+ io.enumCase(value, "a2", a2);
+ io.enumCase(value, "a3", a3);
+ }
+ };
+ template <>
+ struct ScalarEnumerationTraits<BFlags> {
+ static void enumeration(IO &io, BFlags &value) {
+ io.enumCase(value, "b1", b1);
+ io.enumCase(value, "b2", b2);
+ io.enumCase(value, "b3", b3);
+ }
+ };
+ template <>
+ struct ScalarEnumerationTraits<Kind> {
+ static void enumeration(IO &io, Kind &value) {
+ io.enumCase(value, "A", kindA);
+ io.enumCase(value, "B", kindB);
+ }
+ };
+ template <>
+ struct MappingTraits<KindAndFlags> {
+ static void mapping(IO &io, KindAndFlags& kf) {
+ io.mapRequired("kind", kf.kind);
+ // Type of "flags" field varies depending on "kind" field.
+ // Use memcpy here to avoid breaking strict aliasing rules.
+ if (kf.kind == kindA) {
+ AFlags aflags = static_cast<AFlags>(kf.flags);
+ io.mapRequired("flags", aflags);
+ kf.flags = aflags;
+ } else {
+ BFlags bflags = static_cast<BFlags>(kf.flags);
+ io.mapRequired("flags", bflags);
+ kf.flags = bflags;
+ }
+ }
+ };
+}
+}
+
+
+//
+// Test the reading of a yaml sequence dynamic types
+//
+TEST(YAMLIO, TestReadKindAndFlagsSequence) {
+ KindAndFlagsSequence seq;
+ Input yin("---\n - kind: A\n flags: a2\n - kind: B\n flags: b1\n...\n");
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq.size(), 2UL);
+ EXPECT_EQ(seq[0].kind, kindA);
+ EXPECT_EQ(seq[0].flags, (uint32_t)a2);
+ EXPECT_EQ(seq[1].kind, kindB);
+ EXPECT_EQ(seq[1].flags, (uint32_t)b1);
+}
+
+//
+// Test writing then reading back dynamic types
+//
+TEST(YAMLIO, TestReadWriteKindAndFlagsSequence) {
+ std::string intermediate;
+ {
+ KindAndFlagsSequence seq;
+ seq.push_back(KindAndFlags(kindA,a1));
+ seq.push_back(KindAndFlags(kindB,b1));
+ seq.push_back(KindAndFlags(kindA,a2));
+ seq.push_back(KindAndFlags(kindB,b2));
+ seq.push_back(KindAndFlags(kindA,a3));
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << seq;
+ }
+ {
+ Input yin(intermediate);
+ KindAndFlagsSequence seq2;
+ yin >> seq2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(seq2.size(), 5UL);
+ EXPECT_EQ(seq2[0].kind, kindA);
+ EXPECT_EQ(seq2[0].flags, (uint32_t)a1);
+ EXPECT_EQ(seq2[1].kind, kindB);
+ EXPECT_EQ(seq2[1].flags, (uint32_t)b1);
+ EXPECT_EQ(seq2[2].kind, kindA);
+ EXPECT_EQ(seq2[2].flags, (uint32_t)a2);
+ EXPECT_EQ(seq2[3].kind, kindB);
+ EXPECT_EQ(seq2[3].flags, (uint32_t)b2);
+ EXPECT_EQ(seq2[4].kind, kindA);
+ EXPECT_EQ(seq2[4].flags, (uint32_t)a3);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test document list
+//===----------------------------------------------------------------------===//
+
+struct FooBarMap {
+ int foo;
+ int bar;
+};
+typedef std::vector<FooBarMap> FooBarMapDocumentList;
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(FooBarMap)
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<FooBarMap> {
+ static void mapping(IO &io, FooBarMap& fb) {
+ io.mapRequired("foo", fb.foo);
+ io.mapRequired("bar", fb.bar);
+ }
+ };
+}
+}
+
+
+//
+// Test the reading of a yaml mapping
+//
+TEST(YAMLIO, TestDocRead) {
+ FooBarMap doc;
+ Input yin("---\nfoo: 3\nbar: 5\n...\n");
+ yin >> doc;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc.foo, 3);
+ EXPECT_EQ(doc.bar,5);
+}
+
+
+
+//
+// Test writing then reading back a sequence of mappings
+//
+TEST(YAMLIO, TestSequenceDocListWriteAndRead) {
+ std::string intermediate;
+ {
+ FooBarMap doc1;
+ doc1.foo = 10;
+ doc1.bar = -3;
+ FooBarMap doc2;
+ doc2.foo = 257;
+ doc2.bar = 0;
+ std::vector<FooBarMap> docList;
+ docList.push_back(doc1);
+ docList.push_back(doc2);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << docList;
+ }
+
+
+ {
+ Input yin(intermediate);
+ std::vector<FooBarMap> docList2;
+ yin >> docList2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList2.size(), 2UL);
+ FooBarMap& map1 = docList2[0];
+ FooBarMap& map2 = docList2[1];
+ EXPECT_EQ(map1.foo, 10);
+ EXPECT_EQ(map1.bar, -3);
+ EXPECT_EQ(map2.foo, 257);
+ EXPECT_EQ(map2.bar, 0);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Test document tags
+//===----------------------------------------------------------------------===//
+
+struct MyDouble {
+ MyDouble() : value(0.0) { }
+ MyDouble(double x) : value(x) { }
+ double value;
+};
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyDouble)
+
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MyDouble> {
+ static void mapping(IO &io, MyDouble &d) {
+ if (io.mapTag("!decimal", true)) {
+ mappingDecimal(io, d);
+ } else if (io.mapTag("!fraction")) {
+ mappingFraction(io, d);
+ }
+ }
+ static void mappingDecimal(IO &io, MyDouble &d) {
+ io.mapRequired("value", d.value);
+ }
+ static void mappingFraction(IO &io, MyDouble &d) {
+ double num, denom;
+ io.mapRequired("numerator", num);
+ io.mapRequired("denominator", denom);
+ // convert fraction to double
+ d.value = num/denom;
+ }
+ };
+ }
+}
+
+
+//
+// Test the reading of two different tagged yaml documents.
+//
+TEST(YAMLIO, TestTaggedDocuments) {
+ std::vector<MyDouble> docList;
+ Input yin("--- !decimal\nvalue: 3.0\n"
+ "--- !fraction\nnumerator: 9.0\ndenominator: 2\n...\n");
+ yin >> docList;
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList.size(), 2UL);
+ EXPECT_EQ(docList[0].value, 3.0);
+ EXPECT_EQ(docList[1].value, 4.5);
+}
+
+
+
+//
+// Test writing then reading back tagged documents
+//
+TEST(YAMLIO, TestTaggedDocumentsWriteAndRead) {
+ std::string intermediate;
+ {
+ MyDouble a(10.25);
+ MyDouble b(-3.75);
+ std::vector<MyDouble> docList;
+ docList.push_back(a);
+ docList.push_back(b);
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << docList;
+ }
+
+ {
+ Input yin(intermediate);
+ std::vector<MyDouble> docList2;
+ yin >> docList2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(docList2.size(), 2UL);
+ EXPECT_EQ(docList2[0].value, 10.25);
+ EXPECT_EQ(docList2[1].value, -3.75);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Test mapping validation
+//===----------------------------------------------------------------------===//
+
+struct MyValidation {
+ double value;
+};
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(MyValidation)
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<MyValidation> {
+ static void mapping(IO &io, MyValidation &d) {
+ io.mapRequired("value", d.value);
+ }
+ static StringRef validate(IO &io, MyValidation &d) {
+ if (d.value < 0)
+ return "negative value";
+ return StringRef();
+ }
+ };
+ }
+}
+
+
+//
+// Test that validate() is called and complains about the negative value.
+//
+TEST(YAMLIO, TestValidatingInput) {
+ std::vector<MyValidation> docList;
+ Input yin("--- \nvalue: 3.0\n"
+ "--- \nvalue: -1.0\n...\n",
+ nullptr, suppressErrorMessages);
+ yin >> docList;
+ EXPECT_TRUE(!!yin.error());
+}
+
+//===----------------------------------------------------------------------===//
+// Test flow mapping
+//===----------------------------------------------------------------------===//
+
+struct FlowFooBar {
+ int foo;
+ int bar;
+
+ FlowFooBar() : foo(0), bar(0) {}
+ FlowFooBar(int foo, int bar) : foo(foo), bar(bar) {}
+};
+
+typedef std::vector<FlowFooBar> FlowFooBarSequence;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(FlowFooBar)
+
+struct FlowFooBarDoc {
+ FlowFooBar attribute;
+ FlowFooBarSequence seq;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<FlowFooBar> {
+ static void mapping(IO &io, FlowFooBar &fb) {
+ io.mapRequired("foo", fb.foo);
+ io.mapRequired("bar", fb.bar);
+ }
+
+ static const bool flow = true;
+ };
+
+ template <>
+ struct MappingTraits<FlowFooBarDoc> {
+ static void mapping(IO &io, FlowFooBarDoc &fb) {
+ io.mapRequired("attribute", fb.attribute);
+ io.mapRequired("seq", fb.seq);
+ }
+ };
+}
+}
+
+//
+// Test writing then reading back custom mappings
+//
+TEST(YAMLIO, TestReadWriteMyFlowMapping) {
+ std::string intermediate;
+ {
+ FlowFooBarDoc doc;
+ doc.attribute = FlowFooBar(42, 907);
+ doc.seq.push_back(FlowFooBar(1, 2));
+ doc.seq.push_back(FlowFooBar(0, 0));
+ doc.seq.push_back(FlowFooBar(-1, 1024));
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << doc;
+
+ // Verify that mappings were written in flow style
+ ostr.flush();
+ llvm::StringRef flowOut(intermediate);
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("{ foo: 42, bar: 907 }"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 1, bar: 2 }"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: 0, bar: 0 }"));
+ EXPECT_NE(llvm::StringRef::npos, flowOut.find("- { foo: -1, bar: 1024 }"));
+ }
+
+ {
+ Input yin(intermediate);
+ FlowFooBarDoc doc2;
+ yin >> doc2;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(doc2.attribute.foo, 42);
+ EXPECT_EQ(doc2.attribute.bar, 907);
+ EXPECT_EQ(doc2.seq.size(), 3UL);
+ EXPECT_EQ(doc2.seq[0].foo, 1);
+ EXPECT_EQ(doc2.seq[0].bar, 2);
+ EXPECT_EQ(doc2.seq[1].foo, 0);
+ EXPECT_EQ(doc2.seq[1].bar, 0);
+ EXPECT_EQ(doc2.seq[2].foo, -1);
+ EXPECT_EQ(doc2.seq[2].bar, 1024);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Test error handling
+//===----------------------------------------------------------------------===//
+
+//
+// Test error handling of unknown enumerated scalar
+//
+TEST(YAMLIO, TestColorsReadError) {
+ ColorMap map;
+ Input yin("---\n"
+ "c1: blue\n"
+ "c2: purple\n"
+ "c3: green\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> map;
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling of flow sequence with unknown value
+//
+TEST(YAMLIO, TestFlagsReadError) {
+ FlagsMap map;
+ Input yin("---\n"
+ "f1: [ big ]\n"
+ "f2: [ round, hollow ]\n"
+ "f3: []\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> map;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in uint8_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint8_t)
+TEST(YAMLIO, TestReadBuiltInTypesUint8Error) {
+ std::vector<uint8_t> seq;
+ Input yin("---\n"
+ "- 255\n"
+ "- 0\n"
+ "- 257\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in uint16_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint16_t)
+TEST(YAMLIO, TestReadBuiltInTypesUint16Error) {
+ std::vector<uint16_t> seq;
+ Input yin("---\n"
+ "- 65535\n"
+ "- 0\n"
+ "- 66000\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in uint32_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint32_t)
+TEST(YAMLIO, TestReadBuiltInTypesUint32Error) {
+ std::vector<uint32_t> seq;
+ Input yin("---\n"
+ "- 4000000000\n"
+ "- 0\n"
+ "- 5000000000\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in uint64_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(uint64_t)
+TEST(YAMLIO, TestReadBuiltInTypesUint64Error) {
+ std::vector<uint64_t> seq;
+ Input yin("---\n"
+ "- 18446744073709551615\n"
+ "- 0\n"
+ "- 19446744073709551615\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in int8_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(int8_t)
+TEST(YAMLIO, TestReadBuiltInTypesint8OverError) {
+ std::vector<int8_t> seq;
+ Input yin("---\n"
+ "- -128\n"
+ "- 0\n"
+ "- 127\n"
+ "- 128\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in int8_t type
+//
+TEST(YAMLIO, TestReadBuiltInTypesint8UnderError) {
+ std::vector<int8_t> seq;
+ Input yin("---\n"
+ "- -128\n"
+ "- 0\n"
+ "- 127\n"
+ "- -129\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in int16_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(int16_t)
+TEST(YAMLIO, TestReadBuiltInTypesint16UnderError) {
+ std::vector<int16_t> seq;
+ Input yin("---\n"
+ "- 32767\n"
+ "- 0\n"
+ "- -32768\n"
+ "- -32769\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in int16_t type
+//
+TEST(YAMLIO, TestReadBuiltInTypesint16OverError) {
+ std::vector<int16_t> seq;
+ Input yin("---\n"
+ "- 32767\n"
+ "- 0\n"
+ "- -32768\n"
+ "- 32768\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in int32_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(int32_t)
+TEST(YAMLIO, TestReadBuiltInTypesint32UnderError) {
+ std::vector<int32_t> seq;
+ Input yin("---\n"
+ "- 2147483647\n"
+ "- 0\n"
+ "- -2147483648\n"
+ "- -2147483649\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in int32_t type
+//
+TEST(YAMLIO, TestReadBuiltInTypesint32OverError) {
+ std::vector<int32_t> seq;
+ Input yin("---\n"
+ "- 2147483647\n"
+ "- 0\n"
+ "- -2147483648\n"
+ "- 2147483649\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in int64_t type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(int64_t)
+TEST(YAMLIO, TestReadBuiltInTypesint64UnderError) {
+ std::vector<int64_t> seq;
+ Input yin("---\n"
+ "- -9223372036854775808\n"
+ "- 0\n"
+ "- 9223372036854775807\n"
+ "- -9223372036854775809\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in int64_t type
+//
+TEST(YAMLIO, TestReadBuiltInTypesint64OverError) {
+ std::vector<int64_t> seq;
+ Input yin("---\n"
+ "- -9223372036854775808\n"
+ "- 0\n"
+ "- 9223372036854775807\n"
+ "- 9223372036854775809\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in float type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(float)
+TEST(YAMLIO, TestReadBuiltInTypesFloatError) {
+ std::vector<float> seq;
+ Input yin("---\n"
+ "- 0.0\n"
+ "- 1000.1\n"
+ "- -123.456\n"
+ "- 1.2.3\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in float type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(double)
+TEST(YAMLIO, TestReadBuiltInTypesDoubleError) {
+ std::vector<double> seq;
+ Input yin("---\n"
+ "- 0.0\n"
+ "- 1000.1\n"
+ "- -123.456\n"
+ "- 1.2.3\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in Hex8 type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(Hex8)
+TEST(YAMLIO, TestReadBuiltInTypesHex8Error) {
+ std::vector<Hex8> seq;
+ Input yin("---\n"
+ "- 0x12\n"
+ "- 0xFE\n"
+ "- 0x123\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+
+//
+// Test error handling reading built-in Hex16 type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(Hex16)
+TEST(YAMLIO, TestReadBuiltInTypesHex16Error) {
+ std::vector<Hex16> seq;
+ Input yin("---\n"
+ "- 0x0012\n"
+ "- 0xFEFF\n"
+ "- 0x12345\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in Hex32 type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(Hex32)
+TEST(YAMLIO, TestReadBuiltInTypesHex32Error) {
+ std::vector<Hex32> seq;
+ Input yin("---\n"
+ "- 0x0012\n"
+ "- 0xFEFF0000\n"
+ "- 0x1234556789\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+//
+// Test error handling reading built-in Hex64 type
+//
+LLVM_YAML_IS_SEQUENCE_VECTOR(Hex64)
+TEST(YAMLIO, TestReadBuiltInTypesHex64Error) {
+ std::vector<Hex64> seq;
+ Input yin("---\n"
+ "- 0x0012\n"
+ "- 0xFFEEDDCCBBAA9988\n"
+ "- 0x12345567890ABCDEF0\n"
+ "...\n",
+ /*Ctxt=*/nullptr,
+ suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_TRUE(!!yin.error());
+}
+
+TEST(YAMLIO, TestMalformedMapFailsGracefully) {
+ FooBar doc;
+ {
+ // We pass the suppressErrorMessages handler to handle the error
+ // message generated in the constructor of Input.
+ Input yin("{foo:3, bar: 5}", /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(!!yin.error());
+ }
+
+ {
+ Input yin("---\nfoo:3\nbar: 5\n...\n", /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin >> doc;
+ EXPECT_TRUE(!!yin.error());
+ }
+}
+
+struct OptionalTest {
+ std::vector<int> Numbers;
+};
+
+struct OptionalTestSeq {
+ std::vector<OptionalTest> Tests;
+};
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(OptionalTest)
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<OptionalTest> {
+ static void mapping(IO& IO, OptionalTest &OT) {
+ IO.mapOptional("Numbers", OT.Numbers);
+ }
+ };
+
+ template <>
+ struct MappingTraits<OptionalTestSeq> {
+ static void mapping(IO &IO, OptionalTestSeq &OTS) {
+ IO.mapOptional("Tests", OTS.Tests);
+ }
+ };
+}
+}
+
+TEST(YAMLIO, SequenceElideTest) {
+ // Test that writing out a purely optional structure with its fields set to
+ // default followed by other data is properly read back in.
+ OptionalTestSeq Seq;
+ OptionalTest One, Two, Three, Four;
+ int N[] = {1, 2, 3};
+ Three.Numbers.assign(N, N + 3);
+ Seq.Tests.push_back(One);
+ Seq.Tests.push_back(Two);
+ Seq.Tests.push_back(Three);
+ Seq.Tests.push_back(Four);
+
+ std::string intermediate;
+ {
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << Seq;
+ }
+
+ Input yin(intermediate);
+ OptionalTestSeq Seq2;
+ yin >> Seq2;
+
+ EXPECT_FALSE(yin.error());
+
+ EXPECT_EQ(4UL, Seq2.Tests.size());
+
+ EXPECT_TRUE(Seq2.Tests[0].Numbers.empty());
+ EXPECT_TRUE(Seq2.Tests[1].Numbers.empty());
+
+ EXPECT_EQ(1, Seq2.Tests[2].Numbers[0]);
+ EXPECT_EQ(2, Seq2.Tests[2].Numbers[1]);
+ EXPECT_EQ(3, Seq2.Tests[2].Numbers[2]);
+
+ EXPECT_TRUE(Seq2.Tests[3].Numbers.empty());
+}
+
+TEST(YAMLIO, TestEmptyStringFailsForMapWithRequiredFields) {
+ FooBar doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_TRUE(!!yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForMapWithOptionalFields) {
+ OptionalTest doc;
+ Input yin("");
+ yin >> doc;
+ EXPECT_FALSE(yin.error());
+}
+
+TEST(YAMLIO, TestEmptyStringSucceedsForSequence) {
+ std::vector<uint8_t> seq;
+ Input yin("", /*Ctxt=*/nullptr, suppressErrorMessages);
+ yin >> seq;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_TRUE(seq.empty());
+}
+
+struct FlowMap {
+ llvm::StringRef str1, str2, str3;
+ FlowMap(llvm::StringRef str1, llvm::StringRef str2, llvm::StringRef str3)
+ : str1(str1), str2(str2), str3(str3) {}
+};
+
+struct FlowSeq {
+ llvm::StringRef str;
+ FlowSeq(llvm::StringRef S) : str(S) {}
+ FlowSeq() = default;
+};
+
+namespace llvm {
+namespace yaml {
+ template <>
+ struct MappingTraits<FlowMap> {
+ static void mapping(IO &io, FlowMap &fm) {
+ io.mapRequired("str1", fm.str1);
+ io.mapRequired("str2", fm.str2);
+ io.mapRequired("str3", fm.str3);
+ }
+
+ static const bool flow = true;
+ };
+
+template <>
+struct ScalarTraits<FlowSeq> {
+ static void output(const FlowSeq &value, void*, llvm::raw_ostream &out) {
+ out << value.str;
+ }
+ static StringRef input(StringRef scalar, void*, FlowSeq &value) {
+ value.str = scalar;
+ return "";
+ }
+
+ static bool mustQuote(StringRef S) { return false; }
+};
+}
+}
+
+LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FlowSeq)
+
+TEST(YAMLIO, TestWrapFlow) {
+ std::string out;
+ llvm::raw_string_ostream ostr(out);
+ FlowMap Map("This is str1", "This is str2", "This is str3");
+ std::vector<FlowSeq> Seq;
+ Seq.emplace_back("This is str1");
+ Seq.emplace_back("This is str2");
+ Seq.emplace_back("This is str3");
+
+ {
+ // 20 is just bellow the total length of the first mapping field.
+ // We should wreap at every element.
+ Output yout(ostr, nullptr, 15);
+
+ yout << Map;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "{ str1: This is str1, \n"
+ " str2: This is str2, \n"
+ " str3: This is str3 }\n"
+ "...\n");
+ out.clear();
+
+ yout << Seq;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "[ This is str1, \n"
+ " This is str2, \n"
+ " This is str3 ]\n"
+ "...\n");
+ out.clear();
+ }
+ {
+ // 25 will allow the second field to be output on the first line.
+ Output yout(ostr, nullptr, 25);
+
+ yout << Map;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "{ str1: This is str1, str2: This is str2, \n"
+ " str3: This is str3 }\n"
+ "...\n");
+ out.clear();
+
+ yout << Seq;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "[ This is str1, This is str2, \n"
+ " This is str3 ]\n"
+ "...\n");
+ out.clear();
+ }
+ {
+ // 0 means no wrapping.
+ Output yout(ostr, nullptr, 0);
+
+ yout << Map;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "{ str1: This is str1, str2: This is str2, str3: This is str3 }\n"
+ "...\n");
+ out.clear();
+
+ yout << Seq;
+ ostr.flush();
+ EXPECT_EQ(out,
+ "---\n"
+ "[ This is str1, This is str2, This is str3 ]\n"
+ "...\n");
+ out.clear();
+ }
+}
diff --git a/gnu/llvm/unittests/Support/YAMLParserTest.cpp b/gnu/llvm/unittests/Support/YAMLParserTest.cpp
new file mode 100644
index 00000000000..41ad649699c
--- /dev/null
+++ b/gnu/llvm/unittests/Support/YAMLParserTest.cpp
@@ -0,0 +1,335 @@
+//===- unittest/Support/YAMLParserTest ------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/YAMLParser.h"
+#include "gtest/gtest.h"
+
+namespace llvm {
+
+static void SuppressDiagnosticsOutput(const SMDiagnostic &, void *) {
+ // Prevent SourceMgr from writing errors to stderr
+ // to reduce noise in unit test runs.
+}
+
+// Assumes Ctx is an SMDiagnostic where Diag can be stored.
+static void CollectDiagnosticsOutput(const SMDiagnostic &Diag, void *Ctx) {
+ SMDiagnostic* DiagOut = static_cast<SMDiagnostic*>(Ctx);
+ *DiagOut = Diag;
+}
+
+// Checks that the given input gives a parse error. Makes sure that an error
+// text is available and the parse fails.
+static void ExpectParseError(StringRef Message, StringRef Input) {
+ SourceMgr SM;
+ yaml::Stream Stream(Input, SM);
+ SM.setDiagHandler(SuppressDiagnosticsOutput);
+ EXPECT_FALSE(Stream.validate()) << Message << ": " << Input;
+ EXPECT_TRUE(Stream.failed()) << Message << ": " << Input;
+}
+
+// Checks that the given input can be parsed without error.
+static void ExpectParseSuccess(StringRef Message, StringRef Input) {
+ SourceMgr SM;
+ yaml::Stream Stream(Input, SM);
+ EXPECT_TRUE(Stream.validate()) << Message << ": " << Input;
+}
+
+TEST(YAMLParser, ParsesEmptyArray) {
+ ExpectParseSuccess("Empty array", "[]");
+}
+
+TEST(YAMLParser, FailsIfNotClosingArray) {
+ ExpectParseError("Not closing array", "[");
+ ExpectParseError("Not closing array", " [ ");
+ ExpectParseError("Not closing array", " [x");
+}
+
+TEST(YAMLParser, ParsesEmptyArrayWithWhitespace) {
+ ExpectParseSuccess("Array with spaces", " [ ] ");
+ ExpectParseSuccess("All whitespaces", "\t\r\n[\t\n \t\r ]\t\r \n\n");
+}
+
+TEST(YAMLParser, ParsesEmptyObject) {
+ ExpectParseSuccess("Empty object", "[{}]");
+}
+
+TEST(YAMLParser, ParsesObject) {
+ ExpectParseSuccess("Object with an entry", "[{\"a\":\"/b\"}]");
+}
+
+TEST(YAMLParser, ParsesMultipleKeyValuePairsInObject) {
+ ExpectParseSuccess("Multiple key, value pairs",
+ "[{\"a\":\"/b\",\"c\":\"d\",\"e\":\"f\"}]");
+}
+
+TEST(YAMLParser, FailsIfNotClosingObject) {
+ ExpectParseError("Missing close on empty", "[{]");
+ ExpectParseError("Missing close after pair", "[{\"a\":\"b\"]");
+}
+
+TEST(YAMLParser, FailsIfMissingColon) {
+ ExpectParseError("Missing colon between key and value", "[{\"a\"\"/b\"}]");
+ ExpectParseError("Missing colon between key and value", "[{\"a\" \"b\"}]");
+}
+
+TEST(YAMLParser, FailsOnMissingQuote) {
+ ExpectParseError("Missing open quote", "[{a\":\"b\"}]");
+ ExpectParseError("Missing closing quote", "[{\"a\":\"b}]");
+}
+
+TEST(YAMLParser, ParsesEscapedQuotes) {
+ ExpectParseSuccess("Parses escaped string in key and value",
+ "[{\"a\":\"\\\"b\\\" \\\" \\\"\"}]");
+}
+
+TEST(YAMLParser, ParsesEmptyString) {
+ ExpectParseSuccess("Parses empty string in value", "[{\"a\":\"\"}]");
+}
+
+TEST(YAMLParser, ParsesMultipleObjects) {
+ ExpectParseSuccess(
+ "Multiple objects in array",
+ "["
+ " { \"a\" : \"b\" },"
+ " { \"a\" : \"b\" },"
+ " { \"a\" : \"b\" }"
+ "]");
+}
+
+TEST(YAMLParser, FailsOnMissingComma) {
+ ExpectParseError(
+ "Missing comma",
+ "["
+ " { \"a\" : \"b\" }"
+ " { \"a\" : \"b\" }"
+ "]");
+}
+
+TEST(YAMLParser, ParsesSpacesInBetweenTokens) {
+ ExpectParseSuccess(
+ "Various whitespace between tokens",
+ " \t \n\n \r [ \t \n\n \r"
+ " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
+ " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r,\t \n\n \r"
+ " \t \n\n \r { \t \n\n \r\"a\"\t \n\n \r :"
+ " \t \n\n \r \"b\"\t \n\n \r } \t \n\n \r]\t \n\n \r");
+}
+
+TEST(YAMLParser, ParsesArrayOfArrays) {
+ ExpectParseSuccess("Array of arrays", "[[]]");
+}
+
+TEST(YAMLParser, ParsesBlockLiteralScalars) {
+ ExpectParseSuccess("Block literal scalar", "test: |\n Hello\n World\n");
+ ExpectParseSuccess("Block literal scalar EOF", "test: |\n Hello\n World");
+ ExpectParseSuccess("Empty block literal scalar header EOF", "test: | ");
+ ExpectParseSuccess("Empty block literal scalar", "test: |\ntest2: 20");
+ ExpectParseSuccess("Empty block literal scalar 2", "- | \n \n\n \n- 42");
+ ExpectParseSuccess("Block literal scalar in sequence",
+ "- |\n Testing\n Out\n\n- 22");
+ ExpectParseSuccess("Block literal scalar in document",
+ "--- |\n Document\n...");
+ ExpectParseSuccess("Empty non indented lines still count",
+ "- |\n First line\n \n\n Another line\n\n- 2");
+ ExpectParseSuccess("Comment in block literal scalar header",
+ "test: | # Comment \n No Comment\ntest 2: | # Void");
+ ExpectParseSuccess("Chomping indicators in block literal scalar header",
+ "test: |- \n Hello\n\ntest 2: |+ \n\n World\n\n\n");
+ ExpectParseSuccess("Indent indicators in block literal scalar header",
+ "test: |1 \n \n Hello \n World\n");
+ ExpectParseSuccess("Chomping and indent indicators in block literals",
+ "test: |-1\n Hello\ntest 2: |9+\n World");
+ ExpectParseSuccess("Trailing comments in block literals",
+ "test: |\n Content\n # Trailing\n #Comment\ntest 2: 3");
+ ExpectParseError("Invalid block scalar header", "test: | failure");
+ ExpectParseError("Invalid line indentation", "test: |\n First line\n Error");
+ ExpectParseError("Long leading space line", "test: |\n \n Test\n");
+}
+
+TEST(YAMLParser, NullTerminatedBlockScalars) {
+ SourceMgr SM;
+ yaml::Stream Stream("test: |\n Hello\n World\n", SM);
+ yaml::Document &Doc = *Stream.begin();
+ yaml::MappingNode *Map = cast<yaml::MappingNode>(Doc.getRoot());
+ StringRef Value =
+ cast<yaml::BlockScalarNode>(Map->begin()->getValue())->getValue();
+
+ EXPECT_EQ(Value, "Hello\nWorld\n");
+ EXPECT_EQ(Value.data()[Value.size()], '\0');
+}
+
+TEST(YAMLParser, HandlesEndOfFileGracefully) {
+ ExpectParseError("In string starting with EOF", "[\"");
+ ExpectParseError("In string hitting EOF", "[\" ");
+ ExpectParseError("In string escaping EOF", "[\" \\");
+ ExpectParseError("In array starting with EOF", "[");
+ ExpectParseError("In array element starting with EOF", "[[], ");
+ ExpectParseError("In array hitting EOF", "[[] ");
+ ExpectParseError("In array hitting EOF", "[[]");
+ ExpectParseError("In object hitting EOF", "{\"\"");
+}
+
+TEST(YAMLParser, HandlesNullValuesInKeyValueNodesGracefully) {
+ ExpectParseError("KeyValueNode with null value", "test: '");
+}
+
+// Checks that the given string can be parsed into an identical string inside
+// of an array.
+static void ExpectCanParseString(StringRef String) {
+ std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
+ SourceMgr SM;
+ yaml::Stream Stream(StringInArray, SM);
+ yaml::SequenceNode *ParsedSequence
+ = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
+ StringRef ParsedString
+ = dyn_cast<yaml::ScalarNode>(
+ static_cast<yaml::Node*>(ParsedSequence->begin()))->getRawValue();
+ ParsedString = ParsedString.substr(1, ParsedString.size() - 2);
+ EXPECT_EQ(String, ParsedString.str());
+}
+
+// Checks that parsing the given string inside an array fails.
+static void ExpectCannotParseString(StringRef String) {
+ std::string StringInArray = (llvm::Twine("[\"") + String + "\"]").str();
+ ExpectParseError((Twine("When parsing string \"") + String + "\"").str(),
+ StringInArray);
+}
+
+TEST(YAMLParser, ParsesStrings) {
+ ExpectCanParseString("");
+ ExpectCannotParseString("\\");
+ ExpectCannotParseString("\"");
+ ExpectCanParseString(" ");
+ ExpectCanParseString("\\ ");
+ ExpectCanParseString("\\\"");
+ ExpectCannotParseString("\"\\");
+ ExpectCannotParseString(" \\");
+ ExpectCanParseString("\\\\");
+ ExpectCannotParseString("\\\\\\");
+ ExpectCanParseString("\\\\\\\\");
+ ExpectCanParseString("\\\" ");
+ ExpectCannotParseString("\\\\\" ");
+ ExpectCanParseString("\\\\\\\" ");
+ ExpectCanParseString(" \\\\ \\\" \\\\\\\" ");
+}
+
+TEST(YAMLParser, WorksWithIteratorAlgorithms) {
+ SourceMgr SM;
+ yaml::Stream Stream("[\"1\", \"2\", \"3\", \"4\", \"5\", \"6\"]", SM);
+ yaml::SequenceNode *Array
+ = dyn_cast<yaml::SequenceNode>(Stream.begin()->getRoot());
+ EXPECT_EQ(6, std::distance(Array->begin(), Array->end()));
+}
+
+TEST(YAMLParser, DefaultDiagnosticFilename) {
+ SourceMgr SM;
+
+ SMDiagnostic GeneratedDiag;
+ SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
+
+ // When we construct a YAML stream over an unnamed string,
+ // the filename is hard-coded as "YAML".
+ yaml::Stream UnnamedStream("[]", SM);
+ UnnamedStream.printError(UnnamedStream.begin()->getRoot(), "Hello, World!");
+ EXPECT_EQ("YAML", GeneratedDiag.getFilename());
+}
+
+TEST(YAMLParser, DiagnosticFilenameFromBufferID) {
+ SourceMgr SM;
+
+ SMDiagnostic GeneratedDiag;
+ SM.setDiagHandler(CollectDiagnosticsOutput, &GeneratedDiag);
+
+ // When we construct a YAML stream over a named buffer,
+ // we get its ID as filename in diagnostics.
+ std::unique_ptr<MemoryBuffer> Buffer =
+ MemoryBuffer::getMemBuffer("[]", "buffername.yaml");
+ yaml::Stream Stream(Buffer->getMemBufferRef(), SM);
+ Stream.printError(Stream.begin()->getRoot(), "Hello, World!");
+ EXPECT_EQ("buffername.yaml", GeneratedDiag.getFilename());
+}
+
+TEST(YAMLParser, SameNodeIteratorOperatorNotEquals) {
+ SourceMgr SM;
+ yaml::Stream Stream("[\"1\", \"2\"]", SM);
+
+ yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
+ Stream.begin()->getRoot());
+
+ auto Begin = Node->begin();
+ auto End = Node->end();
+
+ EXPECT_TRUE(Begin != End);
+ EXPECT_FALSE(Begin != Begin);
+ EXPECT_FALSE(End != End);
+}
+
+TEST(YAMLParser, SameNodeIteratorOperatorEquals) {
+ SourceMgr SM;
+ yaml::Stream Stream("[\"1\", \"2\"]", SM);
+
+ yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
+ Stream.begin()->getRoot());
+
+ auto Begin = Node->begin();
+ auto End = Node->end();
+
+ EXPECT_FALSE(Begin == End);
+ EXPECT_TRUE(Begin == Begin);
+ EXPECT_TRUE(End == End);
+}
+
+TEST(YAMLParser, DifferentNodesIteratorOperatorNotEquals) {
+ SourceMgr SM;
+ yaml::Stream Stream("[\"1\", \"2\"]", SM);
+ yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
+
+ yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
+ Stream.begin()->getRoot());
+ yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
+ AnotherStream.begin()->getRoot());
+
+ auto Begin = Node->begin();
+ auto End = Node->end();
+
+ auto AnotherBegin = AnotherNode->begin();
+ auto AnotherEnd = AnotherNode->end();
+
+ EXPECT_TRUE(Begin != AnotherBegin);
+ EXPECT_TRUE(Begin != AnotherEnd);
+ EXPECT_FALSE(End != AnotherEnd);
+}
+
+TEST(YAMLParser, DifferentNodesIteratorOperatorEquals) {
+ SourceMgr SM;
+ yaml::Stream Stream("[\"1\", \"2\"]", SM);
+ yaml::Stream AnotherStream("[\"1\", \"2\"]", SM);
+
+ yaml::SequenceNode *Node = dyn_cast<yaml::SequenceNode>(
+ Stream.begin()->getRoot());
+ yaml::SequenceNode *AnotherNode = dyn_cast<yaml::SequenceNode>(
+ AnotherStream.begin()->getRoot());
+
+ auto Begin = Node->begin();
+ auto End = Node->end();
+
+ auto AnotherBegin = AnotherNode->begin();
+ auto AnotherEnd = AnotherNode->end();
+
+ EXPECT_FALSE(Begin == AnotherBegin);
+ EXPECT_FALSE(Begin == AnotherEnd);
+ EXPECT_TRUE(End == AnotherEnd);
+}
+
+} // end namespace llvm
diff --git a/gnu/llvm/unittests/Support/formatted_raw_ostream_test.cpp b/gnu/llvm/unittests/Support/formatted_raw_ostream_test.cpp
new file mode 100644
index 00000000000..9bb80469133
--- /dev/null
+++ b/gnu/llvm/unittests/Support/formatted_raw_ostream_test.cpp
@@ -0,0 +1,33 @@
+//===- llvm/unittest/Support/formatted_raw_ostream_test.cpp ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(formatted_raw_ostreamTest, Test_Tell) {
+ // Check offset when underlying stream has buffer contents.
+ SmallString<128> A;
+ raw_svector_ostream B(A);
+ formatted_raw_ostream C(B);
+ char tmp[100] = "";
+
+ for (unsigned i = 0; i != 3; ++i) {
+ C.write(tmp, 100);
+
+ EXPECT_EQ(100*(i+1), (unsigned) C.tell());
+ }
+}
+
+}
diff --git a/gnu/llvm/unittests/Support/raw_ostream_test.cpp b/gnu/llvm/unittests/Support/raw_ostream_test.cpp
new file mode 100644
index 00000000000..ff986025b2c
--- /dev/null
+++ b/gnu/llvm/unittests/Support/raw_ostream_test.cpp
@@ -0,0 +1,185 @@
+//===- llvm/unittest/Support/raw_ostream_test.cpp - raw_ostream tests -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+template<typename T> std::string printToString(const T &Value) {
+ std::string res;
+ llvm::raw_string_ostream(res) << Value;
+ return res;
+}
+
+/// printToString - Print the given value to a stream which only has \arg
+/// BytesLeftInBuffer bytes left in the buffer. This is useful for testing edge
+/// cases in the buffer handling logic.
+template<typename T> std::string printToString(const T &Value,
+ unsigned BytesLeftInBuffer) {
+ // FIXME: This is relying on internal knowledge of how raw_ostream works to
+ // get the buffer position right.
+ SmallString<256> SVec;
+ assert(BytesLeftInBuffer < 256 && "Invalid buffer count!");
+ llvm::raw_svector_ostream OS(SVec);
+ unsigned StartIndex = 256 - BytesLeftInBuffer;
+ for (unsigned i = 0; i != StartIndex; ++i)
+ OS << '?';
+ OS << Value;
+ return OS.str().substr(StartIndex);
+}
+
+template<typename T> std::string printToStringUnbuffered(const T &Value) {
+ std::string res;
+ llvm::raw_string_ostream OS(res);
+ OS.SetUnbuffered();
+ OS << Value;
+ return res;
+}
+
+TEST(raw_ostreamTest, Types_Buffered) {
+ // Char
+ EXPECT_EQ("c", printToString('c'));
+
+ // String
+ EXPECT_EQ("hello", printToString("hello"));
+ EXPECT_EQ("hello", printToString(std::string("hello")));
+
+ // Int
+ EXPECT_EQ("0", printToString(0));
+ EXPECT_EQ("2425", printToString(2425));
+ EXPECT_EQ("-2425", printToString(-2425));
+
+ // Long long
+ EXPECT_EQ("0", printToString(0LL));
+ EXPECT_EQ("257257257235709", printToString(257257257235709LL));
+ EXPECT_EQ("-257257257235709", printToString(-257257257235709LL));
+
+ // Double
+ EXPECT_EQ("1.100000e+00", printToString(1.1));
+
+ // void*
+ EXPECT_EQ("0x0", printToString((void*) nullptr));
+ EXPECT_EQ("0xbeef", printToString((void*) 0xbeef));
+ EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef));
+
+ // Min and max.
+ EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX));
+ EXPECT_EQ("-9223372036854775808", printToString(INT64_MIN));
+}
+
+TEST(raw_ostreamTest, Types_Unbuffered) {
+ // Char
+ EXPECT_EQ("c", printToStringUnbuffered('c'));
+
+ // String
+ EXPECT_EQ("hello", printToStringUnbuffered("hello"));
+ EXPECT_EQ("hello", printToStringUnbuffered(std::string("hello")));
+
+ // Int
+ EXPECT_EQ("0", printToStringUnbuffered(0));
+ EXPECT_EQ("2425", printToStringUnbuffered(2425));
+ EXPECT_EQ("-2425", printToStringUnbuffered(-2425));
+
+ // Long long
+ EXPECT_EQ("0", printToStringUnbuffered(0LL));
+ EXPECT_EQ("257257257235709", printToStringUnbuffered(257257257235709LL));
+ EXPECT_EQ("-257257257235709", printToStringUnbuffered(-257257257235709LL));
+
+ // Double
+ EXPECT_EQ("1.100000e+00", printToStringUnbuffered(1.1));
+
+ // void*
+ EXPECT_EQ("0x0", printToStringUnbuffered((void*) nullptr));
+ EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef));
+ EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef));
+
+ // Min and max.
+ EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX));
+ EXPECT_EQ("-9223372036854775808", printToStringUnbuffered(INT64_MIN));
+}
+
+TEST(raw_ostreamTest, BufferEdge) {
+ EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 1));
+ EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 2));
+ EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 3));
+ EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 4));
+ EXPECT_EQ("1.20", printToString(format("%.2f", 1.2), 10));
+}
+
+TEST(raw_ostreamTest, TinyBuffer) {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS.SetBufferSize(1);
+ OS << "hello";
+ OS << 1;
+ OS << 'w' << 'o' << 'r' << 'l' << 'd';
+ EXPECT_EQ("hello1world", OS.str());
+}
+
+TEST(raw_ostreamTest, WriteEscaped) {
+ std::string Str;
+
+ Str = "";
+ raw_string_ostream(Str).write_escaped("hi");
+ EXPECT_EQ("hi", Str);
+
+ Str = "";
+ raw_string_ostream(Str).write_escaped("\\\t\n\"");
+ EXPECT_EQ("\\\\\\t\\n\\\"", Str);
+
+ Str = "";
+ raw_string_ostream(Str).write_escaped("\1\10\200");
+ EXPECT_EQ("\\001\\010\\200", Str);
+}
+
+TEST(raw_ostreamTest, Justify) {
+ EXPECT_EQ("xyz ", printToString(left_justify("xyz", 6), 6));
+ EXPECT_EQ("abc", printToString(left_justify("abc", 3), 3));
+ EXPECT_EQ("big", printToString(left_justify("big", 1), 3));
+ EXPECT_EQ(" xyz", printToString(right_justify("xyz", 6), 6));
+ EXPECT_EQ("abc", printToString(right_justify("abc", 3), 3));
+ EXPECT_EQ("big", printToString(right_justify("big", 1), 3));
+}
+
+TEST(raw_ostreamTest, FormatHex) {
+ EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 6), 6));
+ EXPECT_EQ("0x001234", printToString(format_hex(0x1234, 8), 8));
+ EXPECT_EQ("0x00001234", printToString(format_hex(0x1234, 10), 10));
+ EXPECT_EQ("0x1234", printToString(format_hex(0x1234, 4), 6));
+ EXPECT_EQ("0xff", printToString(format_hex(255, 4), 4));
+ EXPECT_EQ("0xFF", printToString(format_hex(255, 4, true), 4));
+ EXPECT_EQ("0x1", printToString(format_hex(1, 3), 3));
+ EXPECT_EQ("0x12", printToString(format_hex(0x12, 3), 4));
+ EXPECT_EQ("0x123", printToString(format_hex(0x123, 3), 5));
+ EXPECT_EQ("FF", printToString(format_hex_no_prefix(0xFF, 2, true), 4));
+ EXPECT_EQ("ABCD", printToString(format_hex_no_prefix(0xABCD, 2, true), 4));
+ EXPECT_EQ("0xffffffffffffffff",
+ printToString(format_hex(UINT64_MAX, 18), 18));
+ EXPECT_EQ("0x8000000000000000",
+ printToString(format_hex((INT64_MIN), 18), 18));
+}
+
+TEST(raw_ostreamTest, FormatDecimal) {
+ EXPECT_EQ(" 0", printToString(format_decimal(0, 4), 4));
+ EXPECT_EQ(" -1", printToString(format_decimal(-1, 4), 4));
+ EXPECT_EQ(" -1", printToString(format_decimal(-1, 6), 6));
+ EXPECT_EQ("1234567890", printToString(format_decimal(1234567890, 10), 10));
+ EXPECT_EQ(" 9223372036854775807",
+ printToString(format_decimal(INT64_MAX, 21), 21));
+ EXPECT_EQ(" -9223372036854775808",
+ printToString(format_decimal(INT64_MIN, 21), 21));
+}
+
+
+}
diff --git a/gnu/llvm/unittests/Support/raw_pwrite_stream_test.cpp b/gnu/llvm/unittests/Support/raw_pwrite_stream_test.cpp
new file mode 100644
index 00000000000..a62f6bacb07
--- /dev/null
+++ b/gnu/llvm/unittests/Support/raw_pwrite_stream_test.cpp
@@ -0,0 +1,64 @@
+//===- raw_pwrite_stream_test.cpp - raw_pwrite_stream tests ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(raw_pwrite_ostreamTest, TestSVector) {
+ SmallVector<char, 0> Buffer;
+ raw_svector_ostream OS(Buffer);
+ OS << "abcd";
+ StringRef Test = "test";
+ OS.pwrite(Test.data(), Test.size(), 0);
+ EXPECT_EQ(Test, OS.str());
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+ EXPECT_DEATH(OS.pwrite("12345", 5, 0),
+ "We don't support extending the stream");
+#endif
+#endif
+}
+
+TEST(raw_pwrite_ostreamTest, TestFD) {
+ SmallString<64> Path;
+ int FD;
+ sys::fs::createTemporaryFile("foo", "bar", FD, Path);
+ raw_fd_ostream OS(FD, true);
+ OS << "abcd";
+ StringRef Test = "test";
+ OS.pwrite(Test.data(), Test.size(), 0);
+ OS.pwrite(Test.data(), Test.size(), 0);
+
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+ EXPECT_DEATH(OS.pwrite("12345", 5, 0),
+ "We don't support extending the stream");
+#endif
+#endif
+}
+
+#ifdef LLVM_ON_UNIX
+TEST(raw_pwrite_ostreamTest, TestDevNull) {
+ int FD;
+ sys::fs::openFileForWrite("/dev/null", FD, sys::fs::F_None);
+ raw_fd_ostream OS(FD, true);
+ OS << "abcd";
+ StringRef Test = "test";
+ OS.pwrite(Test.data(), Test.size(), 0);
+ OS.pwrite(Test.data(), Test.size(), 0);
+}
+#endif
+}
diff --git a/gnu/llvm/unittests/Transforms/CMakeLists.txt b/gnu/llvm/unittests/Transforms/CMakeLists.txt
new file mode 100644
index 00000000000..5d3b29c94d7
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/CMakeLists.txt
@@ -0,0 +1,2 @@
+add_subdirectory(IPO)
+add_subdirectory(Utils)
diff --git a/gnu/llvm/unittests/Transforms/IPO/CMakeLists.txt b/gnu/llvm/unittests/Transforms/IPO/CMakeLists.txt
new file mode 100644
index 00000000000..58b71b2bce0
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/IPO/CMakeLists.txt
@@ -0,0 +1,9 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ IPO
+ )
+
+add_llvm_unittest(IPOTests
+ LowerBitSets.cpp
+ )
diff --git a/gnu/llvm/unittests/Transforms/IPO/LowerBitSets.cpp b/gnu/llvm/unittests/Transforms/IPO/LowerBitSets.cpp
new file mode 100644
index 00000000000..49a42cd20d7
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/IPO/LowerBitSets.cpp
@@ -0,0 +1,155 @@
+//===- LowerBitSets.cpp - Unit tests for bitset lowering ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/IPO/LowerBitSets.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(LowerBitSets, BitSetBuilder) {
+ struct {
+ std::vector<uint64_t> Offsets;
+ std::set<uint64_t> Bits;
+ uint64_t ByteOffset;
+ uint64_t BitSize;
+ unsigned AlignLog2;
+ bool IsSingleOffset;
+ bool IsAllOnes;
+ } BSBTests[] = {
+ {{}, std::set<uint64_t>{}, 0, 1, 0, false, false},
+ {{0}, {0}, 0, 1, 0, true, true},
+ {{4}, {0}, 4, 1, 0, true, true},
+ {{37}, {0}, 37, 1, 0, true, true},
+ {{0, 1}, {0, 1}, 0, 2, 0, false, true},
+ {{0, 4}, {0, 1}, 0, 2, 2, false, true},
+ {{0, uint64_t(1) << 33}, {0, 1}, 0, 2, 33, false, true},
+ {{3, 7}, {0, 1}, 3, 2, 2, false, true},
+ {{0, 1, 7}, {0, 1, 7}, 0, 8, 0, false, false},
+ {{0, 2, 14}, {0, 1, 7}, 0, 8, 1, false, false},
+ {{0, 1, 8}, {0, 1, 8}, 0, 9, 0, false, false},
+ {{0, 2, 16}, {0, 1, 8}, 0, 9, 1, false, false},
+ {{0, 1, 2, 3, 4, 5, 6, 7},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ 0,
+ 8,
+ 0,
+ false,
+ true},
+ {{0, 1, 2, 3, 4, 5, 6, 7, 8},
+ {0, 1, 2, 3, 4, 5, 6, 7, 8},
+ 0,
+ 9,
+ 0,
+ false,
+ true},
+ };
+
+ for (auto &&T : BSBTests) {
+ BitSetBuilder BSB;
+ for (auto Offset : T.Offsets)
+ BSB.addOffset(Offset);
+
+ BitSetInfo BSI = BSB.build();
+
+ EXPECT_EQ(T.Bits, BSI.Bits);
+ EXPECT_EQ(T.ByteOffset, BSI.ByteOffset);
+ EXPECT_EQ(T.BitSize, BSI.BitSize);
+ EXPECT_EQ(T.AlignLog2, BSI.AlignLog2);
+ EXPECT_EQ(T.IsSingleOffset, BSI.isSingleOffset());
+ EXPECT_EQ(T.IsAllOnes, BSI.isAllOnes());
+
+ for (auto Offset : T.Offsets)
+ EXPECT_TRUE(BSI.containsGlobalOffset(Offset));
+
+ auto I = T.Offsets.begin();
+ for (uint64_t NonOffset = 0; NonOffset != 256; ++NonOffset) {
+ if (I != T.Offsets.end() && *I == NonOffset) {
+ ++I;
+ continue;
+ }
+
+ EXPECT_FALSE(BSI.containsGlobalOffset(NonOffset));
+ }
+ }
+}
+
+TEST(LowerBitSets, GlobalLayoutBuilder) {
+ struct {
+ uint64_t NumObjects;
+ std::vector<std::set<uint64_t>> Fragments;
+ std::vector<uint64_t> WantLayout;
+ } GLBTests[] = {
+ {0, {}, {}},
+ {4, {{0, 1}, {2, 3}}, {0, 1, 2, 3}},
+ {3, {{0, 1}, {1, 2}}, {0, 1, 2}},
+ {4, {{0, 1}, {1, 2}, {2, 3}}, {0, 1, 2, 3}},
+ {4, {{0, 1}, {2, 3}, {1, 2}}, {0, 1, 2, 3}},
+ {6, {{2, 5}, {0, 1, 2, 3, 4, 5}}, {0, 1, 2, 5, 3, 4}},
+ };
+
+ for (auto &&T : GLBTests) {
+ GlobalLayoutBuilder GLB(T.NumObjects);
+ for (auto &&F : T.Fragments)
+ GLB.addFragment(F);
+
+ std::vector<uint64_t> ComputedLayout;
+ for (auto &&F : GLB.Fragments)
+ ComputedLayout.insert(ComputedLayout.end(), F.begin(), F.end());
+
+ EXPECT_EQ(T.WantLayout, ComputedLayout);
+ }
+}
+
+TEST(LowerBitSets, ByteArrayBuilder) {
+ struct BABAlloc {
+ std::set<uint64_t> Bits;
+ uint64_t BitSize;
+ uint64_t WantByteOffset;
+ uint8_t WantMask;
+ };
+
+ struct {
+ std::vector<BABAlloc> Allocs;
+ std::vector<uint8_t> WantBytes;
+ } BABTests[] = {
+ {{{{0}, 1, 0, 1}, {{0}, 1, 0, 2}}, {3}},
+ {{{{0}, 16, 0, 1},
+ {{1}, 15, 0, 2},
+ {{2}, 14, 0, 4},
+ {{3}, 13, 0, 8},
+ {{4}, 12, 0, 0x10},
+ {{5}, 11, 0, 0x20},
+ {{6}, 10, 0, 0x40},
+ {{7}, 9, 0, 0x80},
+ {{0}, 7, 9, 0x80},
+ {{0}, 6, 10, 0x40},
+ {{0}, 5, 11, 0x20},
+ {{0}, 4, 12, 0x10},
+ {{0}, 3, 13, 8},
+ {{0}, 2, 14, 4},
+ {{0}, 1, 15, 2}},
+ {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0, 0x80, 0x40, 0x20, 0x10, 8, 4,
+ 2}},
+ };
+
+ for (auto &&T : BABTests) {
+ ByteArrayBuilder BABuilder;
+
+ for (auto &&A : T.Allocs) {
+ uint64_t GotByteOffset;
+ uint8_t GotMask;
+
+ BABuilder.allocate(A.Bits, A.BitSize, GotByteOffset, GotMask);
+ EXPECT_EQ(A.WantByteOffset, GotByteOffset);
+ EXPECT_EQ(A.WantMask, GotMask);
+ }
+
+ EXPECT_EQ(T.WantBytes, BABuilder.Bytes);
+ }
+}
diff --git a/gnu/llvm/unittests/Transforms/IPO/Makefile b/gnu/llvm/unittests/Transforms/IPO/Makefile
new file mode 100644
index 00000000000..f807879c2b5
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/IPO/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Transforms/IPO/Makefile -------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = IPO
+LINK_COMPONENTS := IPO
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Transforms/Makefile b/gnu/llvm/unittests/Transforms/Makefile
new file mode 100644
index 00000000000..3a2cdfc2c74
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Makefile
@@ -0,0 +1,17 @@
+##===- unittests/Transforms/Makefile -----------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../..
+
+PARALLEL_DIRS = IPO Utils
+
+include $(LEVEL)/Makefile.common
+
+clean::
+ $(Verb) $(RM) -f *Tests
diff --git a/gnu/llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/gnu/llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
new file mode 100644
index 00000000000..0d3a239da34
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
@@ -0,0 +1,102 @@
+//===- ASanStackFrameLayoutTest.cpp - Tests for ComputeASanStackFrameLayout===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#include "llvm/Transforms/Utils/ASanStackFrameLayout.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "gtest/gtest.h"
+#include <sstream>
+
+using namespace llvm;
+
+static std::string
+ShadowBytesToString(ArrayRef<uint8_t> ShadowBytes) {
+ std::ostringstream os;
+ for (size_t i = 0, n = ShadowBytes.size(); i < n; i++) {
+ switch (ShadowBytes[i]) {
+ case kAsanStackLeftRedzoneMagic: os << "L"; break;
+ case kAsanStackRightRedzoneMagic: os << "R"; break;
+ case kAsanStackMidRedzoneMagic: os << "M"; break;
+ default: os << (unsigned)ShadowBytes[i];
+ }
+ }
+ return os.str();
+}
+
+static void TestLayout(SmallVector<ASanStackVariableDescription, 10> Vars,
+ size_t Granularity, size_t MinHeaderSize,
+ const std::string &ExpectedDescr,
+ const std::string &ExpectedShadow) {
+ ASanStackFrameLayout L;
+ ComputeASanStackFrameLayout(Vars, Granularity, MinHeaderSize, &L);
+ EXPECT_EQ(ExpectedDescr, L.DescriptionString);
+ EXPECT_EQ(ExpectedShadow, ShadowBytesToString(L.ShadowBytes));
+}
+
+TEST(ASanStackFrameLayout, Test) {
+#define VEC1(a) SmallVector<ASanStackVariableDescription, 10>(1, a)
+#define VEC(a) \
+ SmallVector<ASanStackVariableDescription, 10>(a, a + sizeof(a) / sizeof(a[0]))
+
+#define VAR(name, size, alignment) \
+ ASanStackVariableDescription name##size##_##alignment = { \
+ #name #size "_" #alignment, \
+ size, \
+ alignment, \
+ 0, \
+ 0 \
+ }
+
+ VAR(a, 1, 1);
+ VAR(p, 1, 32);
+ VAR(p, 1, 256);
+ VAR(a, 2, 1);
+ VAR(a, 3, 1);
+ VAR(a, 4, 1);
+ VAR(a, 7, 1);
+ VAR(a, 8, 1);
+ VAR(a, 9, 1);
+ VAR(a, 16, 1);
+ VAR(a, 41, 1);
+ VAR(a, 105, 1);
+
+ TestLayout(VEC1(a1_1), 8, 16, "1 16 1 4 a1_1", "LL1R");
+ TestLayout(VEC1(a1_1), 64, 64, "1 64 1 4 a1_1", "L1");
+ TestLayout(VEC1(p1_32), 8, 32, "1 32 1 5 p1_32", "LLLL1RRR");
+ TestLayout(VEC1(p1_32), 8, 64, "1 64 1 5 p1_32", "LLLLLLLL1RRRRRRR");
+
+ TestLayout(VEC1(a1_1), 8, 32, "1 32 1 4 a1_1", "LLLL1RRR");
+ TestLayout(VEC1(a2_1), 8, 32, "1 32 2 4 a2_1", "LLLL2RRR");
+ TestLayout(VEC1(a3_1), 8, 32, "1 32 3 4 a3_1", "LLLL3RRR");
+ TestLayout(VEC1(a4_1), 8, 32, "1 32 4 4 a4_1", "LLLL4RRR");
+ TestLayout(VEC1(a7_1), 8, 32, "1 32 7 4 a7_1", "LLLL7RRR");
+ TestLayout(VEC1(a8_1), 8, 32, "1 32 8 4 a8_1", "LLLL0RRR");
+ TestLayout(VEC1(a9_1), 8, 32, "1 32 9 4 a9_1", "LLLL01RR");
+ TestLayout(VEC1(a16_1), 8, 32, "1 32 16 5 a16_1", "LLLL00RR");
+ TestLayout(VEC1(p1_256), 8, 32, "1 256 1 6 p1_256",
+ "LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL1RRR");
+ TestLayout(VEC1(a41_1), 8, 32, "1 32 41 5 a41_1", "LLLL000001RRRRRR");
+ TestLayout(VEC1(a105_1), 8, 32, "1 32 105 6 a105_1",
+ "LLLL00000000000001RRRRRR");
+
+ {
+ ASanStackVariableDescription t[] = {a1_1, p1_256};
+ TestLayout(VEC(t), 8, 32,
+ "2 256 1 6 p1_256 272 1 4 a1_1",
+ "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "LLLLLLLL" "1M1R");
+ }
+
+ {
+ ASanStackVariableDescription t[] = {a1_1, a16_1, a41_1};
+ TestLayout(VEC(t), 8, 32,
+ "3 32 1 4 a1_1 48 16 5 a16_1 80 41 5 a41_1",
+ "LLLL" "1M00" "MM00" "0001" "RRRR");
+ }
+#undef VEC1
+#undef VEC
+#undef VAR
+}
diff --git a/gnu/llvm/unittests/Transforms/Utils/CMakeLists.txt b/gnu/llvm/unittests/Transforms/Utils/CMakeLists.txt
new file mode 100644
index 00000000000..517ff99ea46
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS
+ Core
+ Support
+ TransformUtils
+ )
+
+add_llvm_unittest(UtilsTests
+ ASanStackFrameLayoutTest.cpp
+ Cloning.cpp
+ IntegerDivision.cpp
+ Local.cpp
+ ValueMapperTest.cpp
+ )
diff --git a/gnu/llvm/unittests/Transforms/Utils/Cloning.cpp b/gnu/llvm/unittests/Transforms/Utils/Cloning.cpp
new file mode 100644
index 00000000000..25e322ee5a8
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/Cloning.cpp
@@ -0,0 +1,450 @@
+//===- Cloning.cpp - Unit tests for the Cloner ----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/IR/Argument.h"
+#include "llvm/IR/Constant.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+class CloneInstruction : public ::testing::Test {
+protected:
+ void SetUp() override { V = nullptr; }
+
+ template <typename T>
+ T *clone(T *V1) {
+ Value *V2 = V1->clone();
+ Orig.insert(V1);
+ Clones.insert(V2);
+ return cast<T>(V2);
+ }
+
+ void eraseClones() {
+ DeleteContainerPointers(Clones);
+ }
+
+ void TearDown() override {
+ eraseClones();
+ DeleteContainerPointers(Orig);
+ delete V;
+ }
+
+ SmallPtrSet<Value *, 4> Orig; // Erase on exit
+ SmallPtrSet<Value *, 4> Clones; // Erase in eraseClones
+
+ LLVMContext context;
+ Value *V;
+};
+
+TEST_F(CloneInstruction, OverflowBits) {
+ V = new Argument(Type::getInt32Ty(context));
+
+ BinaryOperator *Add = BinaryOperator::Create(Instruction::Add, V, V);
+ BinaryOperator *Sub = BinaryOperator::Create(Instruction::Sub, V, V);
+ BinaryOperator *Mul = BinaryOperator::Create(Instruction::Mul, V, V);
+
+ BinaryOperator *AddClone = this->clone(Add);
+ BinaryOperator *SubClone = this->clone(Sub);
+ BinaryOperator *MulClone = this->clone(Mul);
+
+ EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(AddClone->hasNoSignedWrap());
+ EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(SubClone->hasNoSignedWrap());
+ EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(MulClone->hasNoSignedWrap());
+
+ eraseClones();
+
+ Add->setHasNoUnsignedWrap();
+ Sub->setHasNoUnsignedWrap();
+ Mul->setHasNoUnsignedWrap();
+
+ AddClone = this->clone(Add);
+ SubClone = this->clone(Sub);
+ MulClone = this->clone(Mul);
+
+ EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(AddClone->hasNoSignedWrap());
+ EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(SubClone->hasNoSignedWrap());
+ EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
+ EXPECT_FALSE(MulClone->hasNoSignedWrap());
+
+ eraseClones();
+
+ Add->setHasNoSignedWrap();
+ Sub->setHasNoSignedWrap();
+ Mul->setHasNoSignedWrap();
+
+ AddClone = this->clone(Add);
+ SubClone = this->clone(Sub);
+ MulClone = this->clone(Mul);
+
+ EXPECT_TRUE(AddClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(AddClone->hasNoSignedWrap());
+ EXPECT_TRUE(SubClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(SubClone->hasNoSignedWrap());
+ EXPECT_TRUE(MulClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(MulClone->hasNoSignedWrap());
+
+ eraseClones();
+
+ Add->setHasNoUnsignedWrap(false);
+ Sub->setHasNoUnsignedWrap(false);
+ Mul->setHasNoUnsignedWrap(false);
+
+ AddClone = this->clone(Add);
+ SubClone = this->clone(Sub);
+ MulClone = this->clone(Mul);
+
+ EXPECT_FALSE(AddClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(AddClone->hasNoSignedWrap());
+ EXPECT_FALSE(SubClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(SubClone->hasNoSignedWrap());
+ EXPECT_FALSE(MulClone->hasNoUnsignedWrap());
+ EXPECT_TRUE(MulClone->hasNoSignedWrap());
+}
+
+TEST_F(CloneInstruction, Inbounds) {
+ V = new Argument(Type::getInt32PtrTy(context));
+
+ Constant *Z = Constant::getNullValue(Type::getInt32Ty(context));
+ std::vector<Value *> ops;
+ ops.push_back(Z);
+ GetElementPtrInst *GEP =
+ GetElementPtrInst::Create(Type::getInt32Ty(context), V, ops);
+ EXPECT_FALSE(this->clone(GEP)->isInBounds());
+
+ GEP->setIsInBounds();
+ EXPECT_TRUE(this->clone(GEP)->isInBounds());
+}
+
+TEST_F(CloneInstruction, Exact) {
+ V = new Argument(Type::getInt32Ty(context));
+
+ BinaryOperator *SDiv = BinaryOperator::Create(Instruction::SDiv, V, V);
+ EXPECT_FALSE(this->clone(SDiv)->isExact());
+
+ SDiv->setIsExact(true);
+ EXPECT_TRUE(this->clone(SDiv)->isExact());
+}
+
+TEST_F(CloneInstruction, Attributes) {
+ Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
+ FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
+
+ Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
+ BasicBlock *BB = BasicBlock::Create(context, "", F1);
+ IRBuilder<> Builder(BB);
+ Builder.CreateRetVoid();
+
+ Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
+
+ Attribute::AttrKind AK[] = { Attribute::NoCapture };
+ AttributeSet AS = AttributeSet::get(context, 0, AK);
+ Argument *A = &*F1->arg_begin();
+ A->addAttr(AS);
+
+ SmallVector<ReturnInst*, 4> Returns;
+ ValueToValueMapTy VMap;
+ VMap[A] = UndefValue::get(A->getType());
+
+ CloneFunctionInto(F2, F1, VMap, false, Returns);
+ EXPECT_FALSE(F2->arg_begin()->hasNoCaptureAttr());
+
+ delete F1;
+ delete F2;
+}
+
+TEST_F(CloneInstruction, CallingConvention) {
+ Type *ArgTy1[] = { Type::getInt32PtrTy(context) };
+ FunctionType *FT1 = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
+
+ Function *F1 = Function::Create(FT1, Function::ExternalLinkage);
+ F1->setCallingConv(CallingConv::Cold);
+ BasicBlock *BB = BasicBlock::Create(context, "", F1);
+ IRBuilder<> Builder(BB);
+ Builder.CreateRetVoid();
+
+ Function *F2 = Function::Create(FT1, Function::ExternalLinkage);
+
+ SmallVector<ReturnInst*, 4> Returns;
+ ValueToValueMapTy VMap;
+ VMap[&*F1->arg_begin()] = &*F2->arg_begin();
+
+ CloneFunctionInto(F2, F1, VMap, false, Returns);
+ EXPECT_EQ(CallingConv::Cold, F2->getCallingConv());
+
+ delete F1;
+ delete F2;
+}
+
+class CloneFunc : public ::testing::Test {
+protected:
+ void SetUp() override {
+ SetupModule();
+ CreateOldFunc();
+ CreateNewFunc();
+ SetupFinder();
+ }
+
+ void TearDown() override { delete Finder; }
+
+ void SetupModule() {
+ M = new Module("", C);
+ }
+
+ void CreateOldFunc() {
+ FunctionType* FuncType = FunctionType::get(Type::getVoidTy(C), false);
+ OldFunc = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", M);
+ CreateOldFunctionBodyAndDI();
+ }
+
+ void CreateOldFunctionBodyAndDI() {
+ DIBuilder DBuilder(*M);
+ IRBuilder<> IBuilder(C);
+
+ // Function DI
+ auto *File = DBuilder.createFile("filename.c", "/file/dir/");
+ DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray(None);
+ DISubroutineType *FuncType =
+ DBuilder.createSubroutineType(ParamTypes);
+ auto *CU =
+ DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c",
+ "/file/dir", "CloneFunc", false, "", 0);
+
+ auto *Subprogram = DBuilder.createFunction(
+ CU, "f", "f", File, 4, FuncType, true, true, 3, 0, false);
+ OldFunc->setSubprogram(Subprogram);
+
+ // Function body
+ BasicBlock* Entry = BasicBlock::Create(C, "", OldFunc);
+ IBuilder.SetInsertPoint(Entry);
+ DebugLoc Loc = DebugLoc::get(3, 2, Subprogram);
+ IBuilder.SetCurrentDebugLocation(Loc);
+ AllocaInst* Alloca = IBuilder.CreateAlloca(IntegerType::getInt32Ty(C));
+ IBuilder.SetCurrentDebugLocation(DebugLoc::get(4, 2, Subprogram));
+ Value* AllocaContent = IBuilder.getInt32(1);
+ Instruction* Store = IBuilder.CreateStore(AllocaContent, Alloca);
+ IBuilder.SetCurrentDebugLocation(DebugLoc::get(5, 2, Subprogram));
+ Instruction* Terminator = IBuilder.CreateRetVoid();
+
+ // Create a local variable around the alloca
+ auto *IntType =
+ DBuilder.createBasicType("int", 32, 0, dwarf::DW_ATE_signed);
+ auto *E = DBuilder.createExpression();
+ auto *Variable =
+ DBuilder.createAutoVariable(Subprogram, "x", File, 5, IntType, true);
+ auto *DL = DILocation::get(Subprogram->getContext(), 5, 0, Subprogram);
+ DBuilder.insertDeclare(Alloca, Variable, E, DL, Store);
+ DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, DL,
+ Terminator);
+ // Finalize the debug info
+ DBuilder.finalize();
+
+
+ // Create another, empty, compile unit
+ DIBuilder DBuilder2(*M);
+ DBuilder2.createCompileUnit(dwarf::DW_LANG_C99,
+ "extra.c", "/file/dir", "CloneFunc", false, "", 0);
+ DBuilder2.finalize();
+ }
+
+ void CreateNewFunc() {
+ ValueToValueMapTy VMap;
+ NewFunc = CloneFunction(OldFunc, VMap, true, nullptr);
+ M->getFunctionList().push_back(NewFunc);
+ }
+
+ void SetupFinder() {
+ Finder = new DebugInfoFinder();
+ Finder->processModule(*M);
+ }
+
+ LLVMContext C;
+ Function* OldFunc;
+ Function* NewFunc;
+ Module* M;
+ DebugInfoFinder* Finder;
+};
+
+// Test that a new, distinct function was created.
+TEST_F(CloneFunc, NewFunctionCreated) {
+ EXPECT_NE(OldFunc, NewFunc);
+}
+
+// Test that a new subprogram entry was added and is pointing to the new
+// function, while the original subprogram still points to the old one.
+TEST_F(CloneFunc, Subprogram) {
+ EXPECT_FALSE(verifyModule(*M));
+
+ unsigned SubprogramCount = Finder->subprogram_count();
+ EXPECT_EQ(2U, SubprogramCount);
+
+ auto Iter = Finder->subprograms().begin();
+ auto *Sub1 = cast<DISubprogram>(*Iter);
+ Iter++;
+ auto *Sub2 = cast<DISubprogram>(*Iter);
+
+ EXPECT_TRUE(
+ (Sub1 == OldFunc->getSubprogram() && Sub2 == NewFunc->getSubprogram()) ||
+ (Sub1 == NewFunc->getSubprogram() && Sub2 == OldFunc->getSubprogram()));
+}
+
+// Test that the new subprogram entry was not added to the CU which doesn't
+// contain the old subprogram entry.
+TEST_F(CloneFunc, SubprogramInRightCU) {
+ EXPECT_FALSE(verifyModule(*M));
+
+ EXPECT_EQ(2U, Finder->compile_unit_count());
+
+ auto Iter = Finder->compile_units().begin();
+ auto *CU1 = cast<DICompileUnit>(*Iter);
+ Iter++;
+ auto *CU2 = cast<DICompileUnit>(*Iter);
+ EXPECT_TRUE(CU1->getSubprograms().size() == 0 ||
+ CU2->getSubprograms().size() == 0);
+}
+
+// Test that instructions in the old function still belong to it in the
+// metadata, while instruction in the new function belong to the new one.
+TEST_F(CloneFunc, InstructionOwnership) {
+ EXPECT_FALSE(verifyModule(*M));
+
+ inst_iterator OldIter = inst_begin(OldFunc);
+ inst_iterator OldEnd = inst_end(OldFunc);
+ inst_iterator NewIter = inst_begin(NewFunc);
+ inst_iterator NewEnd = inst_end(NewFunc);
+ while (OldIter != OldEnd && NewIter != NewEnd) {
+ Instruction& OldI = *OldIter;
+ Instruction& NewI = *NewIter;
+ EXPECT_NE(&OldI, &NewI);
+
+ EXPECT_EQ(OldI.hasMetadata(), NewI.hasMetadata());
+ if (OldI.hasMetadata()) {
+ const DebugLoc& OldDL = OldI.getDebugLoc();
+ const DebugLoc& NewDL = NewI.getDebugLoc();
+
+ // Verify that the debug location data is the same
+ EXPECT_EQ(OldDL.getLine(), NewDL.getLine());
+ EXPECT_EQ(OldDL.getCol(), NewDL.getCol());
+
+ // But that they belong to different functions
+ auto *OldSubprogram = cast<DISubprogram>(OldDL.getScope());
+ auto *NewSubprogram = cast<DISubprogram>(NewDL.getScope());
+ EXPECT_EQ(OldFunc->getSubprogram(), OldSubprogram);
+ EXPECT_EQ(NewFunc->getSubprogram(), NewSubprogram);
+ }
+
+ ++OldIter;
+ ++NewIter;
+ }
+ EXPECT_EQ(OldEnd, OldIter);
+ EXPECT_EQ(NewEnd, NewIter);
+}
+
+// Test that the arguments for debug intrinsics in the new function were
+// properly cloned
+TEST_F(CloneFunc, DebugIntrinsics) {
+ EXPECT_FALSE(verifyModule(*M));
+
+ inst_iterator OldIter = inst_begin(OldFunc);
+ inst_iterator OldEnd = inst_end(OldFunc);
+ inst_iterator NewIter = inst_begin(NewFunc);
+ inst_iterator NewEnd = inst_end(NewFunc);
+ while (OldIter != OldEnd && NewIter != NewEnd) {
+ Instruction& OldI = *OldIter;
+ Instruction& NewI = *NewIter;
+ if (DbgDeclareInst* OldIntrin = dyn_cast<DbgDeclareInst>(&OldI)) {
+ DbgDeclareInst* NewIntrin = dyn_cast<DbgDeclareInst>(&NewI);
+ EXPECT_TRUE(NewIntrin);
+
+ // Old address must belong to the old function
+ EXPECT_EQ(OldFunc, cast<AllocaInst>(OldIntrin->getAddress())->
+ getParent()->getParent());
+ // New address must belong to the new function
+ EXPECT_EQ(NewFunc, cast<AllocaInst>(NewIntrin->getAddress())->
+ getParent()->getParent());
+
+ // Old variable must belong to the old function
+ EXPECT_EQ(OldFunc->getSubprogram(),
+ cast<DISubprogram>(OldIntrin->getVariable()->getScope()));
+ // New variable must belong to the New function
+ EXPECT_EQ(NewFunc->getSubprogram(),
+ cast<DISubprogram>(NewIntrin->getVariable()->getScope()));
+ } else if (DbgValueInst* OldIntrin = dyn_cast<DbgValueInst>(&OldI)) {
+ DbgValueInst* NewIntrin = dyn_cast<DbgValueInst>(&NewI);
+ EXPECT_TRUE(NewIntrin);
+
+ // Old variable must belong to the old function
+ EXPECT_EQ(OldFunc->getSubprogram(),
+ cast<DISubprogram>(OldIntrin->getVariable()->getScope()));
+ // New variable must belong to the New function
+ EXPECT_EQ(NewFunc->getSubprogram(),
+ cast<DISubprogram>(NewIntrin->getVariable()->getScope()));
+ }
+
+ ++OldIter;
+ ++NewIter;
+ }
+}
+
+class CloneModule : public ::testing::Test {
+protected:
+ void SetUp() override {
+ SetupModule();
+ CreateOldModule();
+ CreateNewModule();
+ }
+
+ void SetupModule() { OldM = new Module("", C); }
+
+ void CreateOldModule() {
+ IRBuilder<> IBuilder(C);
+
+ auto *FuncType = FunctionType::get(Type::getVoidTy(C), false);
+ auto *PersFn = Function::Create(FuncType, GlobalValue::ExternalLinkage,
+ "persfn", OldM);
+ auto *F =
+ Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", OldM);
+ F->setPersonalityFn(PersFn);
+ auto *Entry = BasicBlock::Create(C, "", F);
+ IBuilder.SetInsertPoint(Entry);
+ IBuilder.CreateRetVoid();
+ }
+
+ void CreateNewModule() { NewM = llvm::CloneModule(OldM).release(); }
+
+ LLVMContext C;
+ Module *OldM;
+ Module *NewM;
+};
+
+TEST_F(CloneModule, Verify) {
+ EXPECT_FALSE(verifyModule(*NewM));
+}
+
+}
diff --git a/gnu/llvm/unittests/Transforms/Utils/IntegerDivision.cpp b/gnu/llvm/unittests/Transforms/Utils/IntegerDivision.cpp
new file mode 100644
index 00000000000..4cda2b4e589
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/IntegerDivision.cpp
@@ -0,0 +1,264 @@
+//===- IntegerDivision.cpp - Unit tests for the integer division code -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/IntegerDivision.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Module.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+
+TEST(IntegerDivision, SDiv) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Div = Builder.CreateSDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, UDiv) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Div = Builder.CreateUDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
+}
+
+TEST(IntegerDivision, SRem) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Rem = Builder.CreateSRem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, URem) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt32Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt32Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Rem = Builder.CreateURem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
+
+TEST(IntegerDivision, SDiv64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Div = Builder.CreateSDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, UDiv64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test division", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Div = Builder.CreateUDiv(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::UDiv);
+
+ Value *Ret = Builder.CreateRet(Div);
+
+ expandDivision(cast<BinaryOperator>(Div));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Quotient = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Quotient && Quotient->getOpcode() == Instruction::PHI);
+}
+
+TEST(IntegerDivision, SRem64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Rem = Builder.CreateSRem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::SRem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::AShr);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
+TEST(IntegerDivision, URem64) {
+ LLVMContext &C(getGlobalContext());
+ Module M("test remainder", C);
+ IRBuilder<> Builder(C);
+
+ SmallVector<Type*, 2> ArgTys(2, Builder.getInt64Ty());
+ Function *F = Function::Create(FunctionType::get(Builder.getInt64Ty(),
+ ArgTys, false),
+ GlobalValue::ExternalLinkage, "F", &M);
+ assert(F->getArgumentList().size() == 2);
+
+ BasicBlock *BB = BasicBlock::Create(C, "", F);
+ Builder.SetInsertPoint(BB);
+
+ Function::arg_iterator AI = F->arg_begin();
+ Value *A = &*AI++;
+ Value *B = &*AI++;
+
+ Value *Rem = Builder.CreateURem(A, B);
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::URem);
+
+ Value *Ret = Builder.CreateRet(Rem);
+
+ expandRemainder(cast<BinaryOperator>(Rem));
+ EXPECT_TRUE(BB->front().getOpcode() == Instruction::ICmp);
+
+ Instruction* Remainder = dyn_cast<Instruction>(cast<User>(Ret)->getOperand(0));
+ EXPECT_TRUE(Remainder && Remainder->getOpcode() == Instruction::Sub);
+}
+
+}
diff --git a/gnu/llvm/unittests/Transforms/Utils/Local.cpp b/gnu/llvm/unittests/Transforms/Utils/Local.cpp
new file mode 100644
index 00000000000..2ff56047555
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/Local.cpp
@@ -0,0 +1,97 @@
+//===- Local.cpp - Unit tests for Local -----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LLVMContext.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+TEST(Local, RecursivelyDeleteDeadPHINodes) {
+ LLVMContext &C(getGlobalContext());
+
+ IRBuilder<> builder(C);
+
+ // Make blocks
+ BasicBlock *bb0 = BasicBlock::Create(C);
+ BasicBlock *bb1 = BasicBlock::Create(C);
+
+ builder.SetInsertPoint(bb0);
+ PHINode *phi = builder.CreatePHI(Type::getInt32Ty(C), 2);
+ BranchInst *br0 = builder.CreateCondBr(builder.getTrue(), bb0, bb1);
+
+ builder.SetInsertPoint(bb1);
+ BranchInst *br1 = builder.CreateBr(bb0);
+
+ phi->addIncoming(phi, bb0);
+ phi->addIncoming(phi, bb1);
+
+ // The PHI will be removed
+ EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
+
+ // Make sure the blocks only contain the branches
+ EXPECT_EQ(&bb0->front(), br0);
+ EXPECT_EQ(&bb1->front(), br1);
+
+ builder.SetInsertPoint(bb0);
+ phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
+
+ EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
+
+ builder.SetInsertPoint(bb0);
+ phi = builder.CreatePHI(Type::getInt32Ty(C), 0);
+ builder.CreateAdd(phi, phi);
+
+ EXPECT_TRUE(RecursivelyDeleteDeadPHINode(phi));
+
+ bb0->dropAllReferences();
+ bb1->dropAllReferences();
+ delete bb0;
+ delete bb1;
+}
+
+TEST(Local, RemoveDuplicatePHINodes) {
+ LLVMContext &C(getGlobalContext());
+ IRBuilder<> B(C);
+
+ std::unique_ptr<Function> F(
+ Function::Create(FunctionType::get(B.getVoidTy(), false),
+ GlobalValue::ExternalLinkage, "F"));
+ BasicBlock *Entry(BasicBlock::Create(C, "", F.get()));
+ BasicBlock *BB(BasicBlock::Create(C, "", F.get()));
+ BranchInst::Create(BB, Entry);
+
+ B.SetInsertPoint(BB);
+
+ AssertingVH<PHINode> P1 = B.CreatePHI(Type::getInt32Ty(C), 2);
+ P1->addIncoming(B.getInt32(42), Entry);
+
+ PHINode *P2 = B.CreatePHI(Type::getInt32Ty(C), 2);
+ P2->addIncoming(B.getInt32(42), Entry);
+
+ AssertingVH<PHINode> P3 = B.CreatePHI(Type::getInt32Ty(C), 2);
+ P3->addIncoming(B.getInt32(42), Entry);
+ P3->addIncoming(B.getInt32(23), BB);
+
+ PHINode *P4 = B.CreatePHI(Type::getInt32Ty(C), 2);
+ P4->addIncoming(B.getInt32(42), Entry);
+ P4->addIncoming(B.getInt32(23), BB);
+
+ P1->addIncoming(P3, BB);
+ P2->addIncoming(P4, BB);
+ BranchInst::Create(BB, BB);
+
+ // Verify that we can eliminate PHIs that become duplicates after chaning PHIs
+ // downstream.
+ EXPECT_TRUE(EliminateDuplicatePHINodes(BB));
+ EXPECT_EQ(3U, BB->size());
+}
diff --git a/gnu/llvm/unittests/Transforms/Utils/Makefile b/gnu/llvm/unittests/Transforms/Utils/Makefile
new file mode 100644
index 00000000000..e6c2a2c133a
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Transforms/Utils/Makefile -----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+TESTNAME = Utils
+LINK_COMPONENTS := TransformUtils
+
+include $(LEVEL)/Makefile.config
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
diff --git a/gnu/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp b/gnu/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp
new file mode 100644
index 00000000000..9dbe4dbc56d
--- /dev/null
+++ b/gnu/llvm/unittests/Transforms/Utils/ValueMapperTest.cpp
@@ -0,0 +1,58 @@
+//===- ValueMapper.cpp - Unit tests for ValueMapper -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/Transforms/Utils/ValueMapper.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+
+TEST(ValueMapperTest, MapMetadataUnresolved) {
+ LLVMContext Context;
+ TempMDTuple T = MDTuple::getTemporary(Context, None);
+
+ ValueToValueMapTy VM;
+ EXPECT_EQ(T.get(), MapMetadata(T.get(), VM, RF_NoModuleLevelChanges));
+}
+
+TEST(ValueMapperTest, MapMetadataDistinct) {
+ LLVMContext Context;
+ auto *D = MDTuple::getDistinct(Context, None);
+
+ {
+ // The node should be cloned.
+ ValueToValueMapTy VM;
+ EXPECT_NE(D, MapMetadata(D, VM, RF_None));
+ }
+ {
+ // The node should be moved.
+ ValueToValueMapTy VM;
+ EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
+ }
+}
+
+TEST(ValueMapperTest, MapMetadataDistinctOperands) {
+ LLVMContext Context;
+ Metadata *Old = MDTuple::getDistinct(Context, None);
+ auto *D = MDTuple::getDistinct(Context, Old);
+ ASSERT_EQ(Old, D->getOperand(0));
+
+ Metadata *New = MDTuple::getDistinct(Context, None);
+ ValueToValueMapTy VM;
+ VM.MD()[Old].reset(New);
+
+ // Make sure operands are updated.
+ EXPECT_EQ(D, MapMetadata(D, VM, RF_MoveDistinctMDs));
+ EXPECT_EQ(New, D->getOperand(0));
+}
+
+}