summaryrefslogtreecommitdiff
path: root/unittests/Support
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:41:05 +0000
commit01095a5d43bbfde13731688ddcf6048ebb8b7721 (patch)
tree4def12e759965de927d963ac65840d663ef9d1ea /unittests/Support
parentf0f4822ed4b66e3579e92a89f368f8fb860e218e (diff)
Diffstat (limited to 'unittests/Support')
-rw-r--r--unittests/Support/AlignOfTest.cpp6
-rw-r--r--unittests/Support/CMakeLists.txt12
-rw-r--r--unittests/Support/CommandLineTest.cpp227
-rw-r--r--unittests/Support/ConvertUTFTest.cpp38
-rw-r--r--unittests/Support/EndianStreamTest.cpp51
-rw-r--r--unittests/Support/ErrorOrTest.cpp42
-rw-r--r--unittests/Support/ErrorTest.cpp627
-rw-r--r--unittests/Support/Makefile15
-rw-r--r--unittests/Support/MathExtrasTest.cpp90
-rw-r--r--unittests/Support/Path.cpp190
-rw-r--r--unittests/Support/ProgramTest.cpp10
-rw-r--r--unittests/Support/StreamingMemoryObject.cpp39
-rw-r--r--unittests/Support/StreamingMemoryObjectTest.cpp68
-rw-r--r--unittests/Support/TargetParserTest.cpp92
-rw-r--r--unittests/Support/TargetRegistry.cpp42
-rw-r--r--unittests/Support/ThreadPool.cpp2
-rw-r--r--unittests/Support/TrailingObjectsTest.cpp13
-rw-r--r--unittests/Support/TypeNameTest.cpp49
-rw-r--r--unittests/Support/YAMLIOTest.cpp107
-rw-r--r--unittests/Support/YAMLParserTest.cpp1
-rw-r--r--unittests/Support/raw_ostream_test.cpp8
-rw-r--r--unittests/Support/raw_sha1_ostream_test.cpp71
22 files changed, 1645 insertions, 155 deletions
diff --git a/unittests/Support/AlignOfTest.cpp b/unittests/Support/AlignOfTest.cpp
index be208f7d28ea8..74b03f0e7dfd3 100644
--- a/unittests/Support/AlignOfTest.cpp
+++ b/unittests/Support/AlignOfTest.cpp
@@ -1,4 +1,4 @@
-//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ----===//
+//=== - llvm/unittest/Support/AlignOfTest.cpp - Alignment utility tests ---===//
//
// The LLVM Compiler Infrastructure
//
@@ -97,7 +97,7 @@ struct Abstract1 {
};
struct Abstract2 : Abstract1 {
- virtual ~Abstract2() {}
+ ~Abstract2() override = default;
double d;
};
@@ -354,4 +354,4 @@ TEST(AlignOfTest, BasicAlignedArray) {
EXPECT_EQ(2u, sizeof(AlignedCharArray<2, 2>));
EXPECT_EQ(16u, sizeof(AlignedCharArray<2, 16>));
}
-}
+} // end anonymous namespace
diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt
index 3ab98d58d5f0d..9a4a144509115 100644
--- a/unittests/Support/CMakeLists.txt
+++ b/unittests/Support/CMakeLists.txt
@@ -1,5 +1,4 @@
set(LLVM_LINK_COMPONENTS
- ${LLVM_TARGETS_TO_BUILD}
Support
)
@@ -17,6 +16,7 @@ add_llvm_unittest(SupportTests
DwarfTest.cpp
EndianStreamTest.cpp
EndianTest.cpp
+ ErrorTest.cpp
ErrorOrTest.cpp
FileOutputBufferTest.cpp
IteratorTest.cpp
@@ -36,14 +36,15 @@ add_llvm_unittest(SupportTests
ScaledNumberTest.cpp
SourceMgrTest.cpp
SpecialCaseListTest.cpp
- StreamingMemoryObject.cpp
+ StreamingMemoryObjectTest.cpp
StringPool.cpp
SwapByteOrderTest.cpp
- TargetRegistry.cpp
+ TargetParserTest.cpp
ThreadLocalTest.cpp
ThreadPool.cpp
TimerTest.cpp
TimeValueTest.cpp
+ TypeNameTest.cpp
TrailingObjectsTest.cpp
UnicodeTest.cpp
YAMLIOTest.cpp
@@ -51,9 +52,8 @@ add_llvm_unittest(SupportTests
formatted_raw_ostream_test.cpp
raw_ostream_test.cpp
raw_pwrite_stream_test.cpp
+ raw_sha1_ostream_test.cpp
)
# ManagedStatic.cpp uses <pthread>.
-if(LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD)
- target_link_libraries(SupportTests pthread)
-endif()
+target_link_libraries(SupportTests ${PTHREAD_LIB})
diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp
index eac669f467b7d..9b24c1e40bcad 100644
--- a/unittests/Support/CommandLineTest.cpp
+++ b/unittests/Support/CommandLineTest.cpp
@@ -67,6 +67,22 @@ public:
: Base(M0, M1, M2, M3) {}
~StackOption() override { this->removeArgument(); }
+
+ template <class DT> StackOption<T> &operator=(const DT &V) {
+ this->setValue(V);
+ return *this;
+ }
+};
+
+class StackSubCommand : public cl::SubCommand {
+public:
+ StackSubCommand(const char *const Name,
+ const char *const Description = nullptr)
+ : SubCommand(Name, Description) {}
+
+ StackSubCommand() : SubCommand() {}
+
+ ~StackSubCommand() { unregisterSubCommand(); }
};
@@ -78,7 +94,8 @@ TEST(CommandLineTest, ModifyExisitingOption) {
const char ArgString[] = "new-test-option";
const char ValueString[] = "Integer";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_TRUE(Map.count("test-option") == 1) <<
"Could not find option in map.";
@@ -165,11 +182,12 @@ void testCommandLineTokenizer(ParserFunction *parse, const char *Input,
}
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" };
+ const char *Input =
+ "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) "
+ "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\"";
+ const char *const Output[] = {
+ "foo bar", "foo bar", "foo bar", "foo\\bar",
+ "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"};
testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
array_lengthof(Output));
}
@@ -236,7 +254,8 @@ TEST(CommandLineTest, HideUnrelatedOptions) {
ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
<< "Hid extra option that should be visable.";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
<< "Hid default option that should be visable.";
}
@@ -260,9 +279,201 @@ TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
<< "Hid extra option that should be visable.";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
<< "Hid default option that should be visable.";
}
+TEST(CommandLineTest, SetValueInSubcategories) {
+ cl::ResetCommandLineParser();
+
+ StackSubCommand SC1("sc1", "First subcommand");
+ StackSubCommand SC2("sc2", "Second subcommand");
+
+ StackOption<bool> TopLevelOpt("top-level", cl::init(false));
+ StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
+ StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
+
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_FALSE(SC1Opt);
+ EXPECT_FALSE(SC2Opt);
+ const char *args[] = {"prog", "-top-level"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+ EXPECT_TRUE(TopLevelOpt);
+ EXPECT_FALSE(SC1Opt);
+ EXPECT_FALSE(SC2Opt);
+
+ TopLevelOpt = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_FALSE(SC1Opt);
+ EXPECT_FALSE(SC2Opt);
+ const char *args2[] = {"prog", "sc1", "-sc1"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_TRUE(SC1Opt);
+ EXPECT_FALSE(SC2Opt);
+
+ SC1Opt = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_FALSE(SC1Opt);
+ EXPECT_FALSE(SC2Opt);
+ const char *args3[] = {"prog", "sc2", "-sc2"};
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true));
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_FALSE(SC1Opt);
+ EXPECT_TRUE(SC2Opt);
+}
+
+TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
+ cl::ResetCommandLineParser();
+
+ StackSubCommand SC1("sc1", "First subcommand");
+ StackSubCommand SC2("sc2", "Second subcommand");
+
+ StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
+ StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
+
+ const char *args[] = {"prog", "sc1", "-sc2"};
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true));
+}
+
+TEST(CommandLineTest, AddToAllSubCommands) {
+ cl::ResetCommandLineParser();
+
+ StackSubCommand SC1("sc1", "First subcommand");
+ StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands),
+ cl::init(false));
+ StackSubCommand SC2("sc2", "Second subcommand");
+
+ const char *args[] = {"prog", "-everywhere"};
+ const char *args2[] = {"prog", "sc1", "-everywhere"};
+ const char *args3[] = {"prog", "sc2", "-everywhere"};
+
+ EXPECT_FALSE(AllOpt);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+ EXPECT_TRUE(AllOpt);
+
+ AllOpt = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(AllOpt);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
+ EXPECT_TRUE(AllOpt);
+
+ AllOpt = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(AllOpt);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, nullptr, true));
+ EXPECT_TRUE(AllOpt);
+}
+
+TEST(CommandLineTest, ReparseCommandLineOptions) {
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand),
+ cl::init(false));
+
+ const char *args[] = {"prog", "-top-level"};
+
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+ EXPECT_TRUE(TopLevelOpt);
+
+ TopLevelOpt = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(TopLevelOpt);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+ EXPECT_TRUE(TopLevelOpt);
+}
+
+TEST(CommandLineTest, RemoveFromRegularSubCommand) {
+ cl::ResetCommandLineParser();
+
+ StackSubCommand SC("sc", "Subcommand");
+ StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
+ StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
+
+ const char *args[] = {"prog", "sc", "-remove-option"};
+
+ EXPECT_FALSE(RemoveOption);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, nullptr, true));
+ EXPECT_TRUE(RemoveOption);
+
+ RemoveOption.removeArgument();
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, nullptr, true));
+}
+
+TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
+ cl::ResetCommandLineParser();
+
+ StackOption<bool> TopLevelRemove(
+ "top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
+ StackOption<bool> TopLevelKeep(
+ "top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
+
+ const char *args[] = {"prog", "-top-level-remove"};
+
+ EXPECT_FALSE(TopLevelRemove);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+ EXPECT_TRUE(TopLevelRemove);
+
+ TopLevelRemove.removeArgument();
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, nullptr, true));
+}
+
+TEST(CommandLineTest, RemoveFromAllSubCommands) {
+ cl::ResetCommandLineParser();
+
+ StackSubCommand SC1("sc1", "First Subcommand");
+ StackSubCommand SC2("sc2", "Second Subcommand");
+ StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands),
+ cl::init(false));
+ StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands),
+ cl::init(false));
+
+ const char *args0[] = {"prog", "-remove-option"};
+ const char *args1[] = {"prog", "sc1", "-remove-option"};
+ const char *args2[] = {"prog", "sc2", "-remove-option"};
+
+ // It should work for all subcommands including the top-level.
+ EXPECT_FALSE(RemoveOption);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, nullptr, true));
+ EXPECT_TRUE(RemoveOption);
+
+ RemoveOption = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(RemoveOption);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args1, nullptr, true));
+ EXPECT_TRUE(RemoveOption);
+
+ RemoveOption = false;
+
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(RemoveOption);
+ EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
+ EXPECT_TRUE(RemoveOption);
+
+ RemoveOption.removeArgument();
+
+ // It should not work for any subcommands including the top-level.
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(cl::ParseCommandLineOptions(2, args0, nullptr, true));
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args1, nullptr, true));
+ cl::ResetAllOptionOccurrences();
+ EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, nullptr, true));
+}
+
} // anonymous namespace
diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp
index d436fc0228963..0af09e98a2178 100644
--- a/unittests/Support/ConvertUTFTest.cpp
+++ b/unittests/Support/ConvertUTFTest.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Format.h"
#include "gtest/gtest.h"
#include <string>
@@ -59,7 +60,7 @@ TEST(ConvertUTFTest, OddLengthInput) {
TEST(ConvertUTFTest, Empty) {
std::string Result;
- bool Success = convertUTF16ToUTF8String(None, Result);
+ bool Success = convertUTF16ToUTF8String(llvm::ArrayRef<char>(None), Result);
EXPECT_TRUE(Success);
EXPECT_TRUE(Result.empty());
}
@@ -80,6 +81,41 @@ TEST(ConvertUTFTest, HasUTF16BOM) {
EXPECT_FALSE(HasBOM);
}
+TEST(ConvertUTFTest, UTF16WrappersForConvertUTF16ToUTF8String) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xff\xfe\xa0\x0c_\x00\xa0\x0c";
+ ArrayRef<UTF16> SrcRef = makeArrayRef((const UTF16 *)Src, 4);
+ std::string Result;
+ bool Success = convertUTF16ToUTF8String(SrcRef, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, ConvertUTF8toWide) {
+ // Src is the look of disapproval.
+ static const char Src[] = "\xe0\xb2\xa0_\xe0\xb2\xa0";
+ std::wstring Result;
+ bool Success = ConvertUTF8toWide((const char*)Src, Result);
+ EXPECT_TRUE(Success);
+ std::wstring Expected(L"\x0ca0_\x0ca0");
+ EXPECT_EQ(Expected, Result);
+ Result.clear();
+ Success = ConvertUTF8toWide(StringRef(Src, 7), Result);
+ EXPECT_TRUE(Success);
+ EXPECT_EQ(Expected, Result);
+}
+
+TEST(ConvertUTFTest, convertWideToUTF8) {
+ // Src is the look of disapproval.
+ static const wchar_t Src[] = L"\x0ca0_\x0ca0";
+ std::string Result;
+ bool Success = convertWideToUTF8(Src, Result);
+ EXPECT_TRUE(Success);
+ std::string Expected("\xe0\xb2\xa0_\xe0\xb2\xa0");
+ EXPECT_EQ(Expected, Result);
+}
+
struct ConvertUTFResultContainer {
ConversionResult ErrorCode;
std::vector<unsigned> UnicodeScalars;
diff --git a/unittests/Support/EndianStreamTest.cpp b/unittests/Support/EndianStreamTest.cpp
index 6a69be55f9266..ea6c308c560a7 100644
--- a/unittests/Support/EndianStreamTest.cpp
+++ b/unittests/Support/EndianStreamTest.cpp
@@ -153,5 +153,56 @@ TEST(EndianStream, WriteDoubleBE) {
EXPECT_EQ(static_cast<uint8_t>(data[7]), 0x20);
}
+TEST(EndianStream, WriteArrayLE) {
+ SmallString<16> Data;
+
+ {
+ raw_svector_ostream OS(Data);
+ endian::Writer<little> LE(OS);
+ LE.write<uint16_t>({0x1234, 0x5678});
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(Data[0]), 0x34);
+ EXPECT_EQ(static_cast<uint8_t>(Data[1]), 0x12);
+ EXPECT_EQ(static_cast<uint8_t>(Data[2]), 0x78);
+ EXPECT_EQ(static_cast<uint8_t>(Data[3]), 0x56);
+}
+
+TEST(EndianStream, WriteVectorLE) {
+ SmallString<16> Data;
+
+ {
+ raw_svector_ostream OS(Data);
+ endian::Writer<little> LE(OS);
+ std::vector<uint16_t> Vec{0x1234, 0x5678};
+ LE.write<uint16_t>(Vec);
+ }
+
+ EXPECT_EQ(static_cast<uint8_t>(Data[0]), 0x34);
+ EXPECT_EQ(static_cast<uint8_t>(Data[1]), 0x12);
+ EXPECT_EQ(static_cast<uint8_t>(Data[2]), 0x78);
+ EXPECT_EQ(static_cast<uint8_t>(Data[3]), 0x56);
+}
+
+TEST(EndianStream, WriteFloatArrayLE) {
+ SmallString<16> Data;
+
+ {
+ raw_svector_ostream OS(Data);
+ endian::Writer<little> LE(OS);
+ LE.write<float>({12345.0f, 12346.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);
+
+ EXPECT_EQ(static_cast<uint8_t>(Data[4]), 0x00);
+ EXPECT_EQ(static_cast<uint8_t>(Data[5]), 0xE8);
+ EXPECT_EQ(static_cast<uint8_t>(Data[6]), 0x40);
+ EXPECT_EQ(static_cast<uint8_t>(Data[7]), 0x46);
+}
+
} // end anon namespace
diff --git a/unittests/Support/ErrorOrTest.cpp b/unittests/Support/ErrorOrTest.cpp
index 73d0e3f2bb711..87dcab7b181ec 100644
--- a/unittests/Support/ErrorOrTest.cpp
+++ b/unittests/Support/ErrorOrTest.cpp
@@ -16,7 +16,7 @@ using namespace llvm;
namespace {
-ErrorOr<int> t1() {return 1;}
+ErrorOr<int> t1() { return 1; }
ErrorOr<int> t2() { return errc::invalid_argument; }
TEST(ErrorOr, SimpleValue) {
@@ -71,6 +71,46 @@ TEST(ErrorOr, Comparison) {
EXPECT_EQ(x, errc::no_such_file_or_directory);
}
+TEST(ErrorOr, ImplicitConversion) {
+ ErrorOr<std::string> x("string literal");
+ EXPECT_TRUE(!!x);
+}
+
+TEST(ErrorOr, ImplicitConversionCausesMove) {
+ struct Source {};
+ struct Destination {
+ Destination(const Source&) {}
+ Destination(Source&&) = delete;
+ };
+ Source s;
+ ErrorOr<Destination> x = s;
+ EXPECT_TRUE(!!x);
+}
+
+TEST(ErrorOr, ImplicitConversionNoAmbiguity) {
+ struct CastsToErrorCode {
+ CastsToErrorCode() = default;
+ CastsToErrorCode(std::error_code) {}
+ operator std::error_code() { return errc::invalid_argument; }
+ } casts_to_error_code;
+ ErrorOr<CastsToErrorCode> x1(casts_to_error_code);
+ ErrorOr<CastsToErrorCode> x2 = casts_to_error_code;
+ ErrorOr<CastsToErrorCode> x3 = {casts_to_error_code};
+ ErrorOr<CastsToErrorCode> x4{casts_to_error_code};
+ ErrorOr<CastsToErrorCode> x5(errc::no_such_file_or_directory);
+ ErrorOr<CastsToErrorCode> x6 = errc::no_such_file_or_directory;
+ ErrorOr<CastsToErrorCode> x7 = {errc::no_such_file_or_directory};
+ ErrorOr<CastsToErrorCode> x8{errc::no_such_file_or_directory};
+ EXPECT_TRUE(!!x1);
+ EXPECT_TRUE(!!x2);
+ EXPECT_TRUE(!!x3);
+ EXPECT_TRUE(!!x4);
+ EXPECT_FALSE(x5);
+ EXPECT_FALSE(x6);
+ EXPECT_FALSE(x7);
+ EXPECT_FALSE(x8);
+}
+
// ErrorOr<int*> x(nullptr);
// ErrorOr<std::unique_ptr<int>> y = x; // invalid conversion
static_assert(
diff --git a/unittests/Support/ErrorTest.cpp b/unittests/Support/ErrorTest.cpp
new file mode 100644
index 0000000000000..2050926837440
--- /dev/null
+++ b/unittests/Support/ErrorTest.cpp
@@ -0,0 +1,627 @@
+//===----- unittests/ErrorTest.cpp - Error.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/Error.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+
+namespace {
+
+// Custom error class with a default base class and some random 'info' attached.
+class CustomError : public ErrorInfo<CustomError> {
+public:
+ // Create an error with some info attached.
+ CustomError(int Info) : Info(Info) {}
+
+ // Get the info attached to this error.
+ int getInfo() const { return Info; }
+
+ // Log this error to a stream.
+ void log(raw_ostream &OS) const override {
+ OS << "CustomError { " << getInfo() << "}";
+ }
+
+ std::error_code convertToErrorCode() const override {
+ llvm_unreachable("CustomError doesn't support ECError conversion");
+ }
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+protected:
+ // This error is subclassed below, but we can't use inheriting constructors
+ // yet, so we can't propagate the constructors through ErrorInfo. Instead
+ // we have to have a default constructor and have the subclass initialize all
+ // fields.
+ CustomError() : Info(0) {}
+
+ int Info;
+};
+
+char CustomError::ID = 0;
+
+// Custom error class with a custom base class and some additional random
+// 'info'.
+class CustomSubError : public ErrorInfo<CustomSubError, CustomError> {
+public:
+ // Create a sub-error with some info attached.
+ CustomSubError(int Info, int ExtraInfo) : ExtraInfo(ExtraInfo) {
+ this->Info = Info;
+ }
+
+ // Get the extra info attached to this error.
+ int getExtraInfo() const { return ExtraInfo; }
+
+ // Log this error to a stream.
+ void log(raw_ostream &OS) const override {
+ OS << "CustomSubError { " << getInfo() << ", " << getExtraInfo() << "}";
+ }
+
+ std::error_code convertToErrorCode() const override {
+ llvm_unreachable("CustomSubError doesn't support ECError conversion");
+ }
+
+ // Used by ErrorInfo::classID.
+ static char ID;
+
+protected:
+ int ExtraInfo;
+};
+
+char CustomSubError::ID = 0;
+
+static Error handleCustomError(const CustomError &CE) { return Error(); }
+
+static void handleCustomErrorVoid(const CustomError &CE) {}
+
+static Error handleCustomErrorUP(std::unique_ptr<CustomError> CE) {
+ return Error();
+}
+
+static void handleCustomErrorUPVoid(std::unique_ptr<CustomError> CE) {}
+
+// Test that success values implicitly convert to false, and don't cause crashes
+// once they've been implicitly converted.
+TEST(Error, CheckedSuccess) {
+ Error E;
+ EXPECT_FALSE(E) << "Unexpected error while testing Error 'Success'";
+}
+
+// Test that unchecked succes values cause an abort.
+#ifndef NDEBUG
+TEST(Error, UncheckedSuccess) {
+ EXPECT_DEATH({ Error E; }, "Program aborted due to an unhandled Error:")
+ << "Unchecked Error Succes value did not cause abort()";
+}
+#endif
+
+// ErrorAsOutParameter tester.
+void errAsOutParamHelper(Error &Err) {
+ ErrorAsOutParameter ErrAsOutParam(Err);
+ // Verify that checked flag is raised - assignment should not crash.
+ Err = Error::success();
+ // Raise the checked bit manually - caller should still have to test the
+ // error.
+ (void)!!Err;
+}
+
+// Test that ErrorAsOutParameter sets the checked flag on construction.
+TEST(Error, ErrorAsOutParameterChecked) {
+ Error E;
+ errAsOutParamHelper(E);
+ (void)!!E;
+}
+
+// Test that ErrorAsOutParameter clears the checked flag on destruction.
+#ifndef NDEBUG
+TEST(Error, ErrorAsOutParameterUnchecked) {
+ EXPECT_DEATH({ Error E; errAsOutParamHelper(E); },
+ "Program aborted due to an unhandled Error:")
+ << "ErrorAsOutParameter did not clear the checked flag on destruction.";
+}
+#endif
+
+// Check that we abort on unhandled failure cases. (Force conversion to bool
+// to make sure that we don't accidentally treat checked errors as handled).
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, UncheckedError) {
+ auto DropUnhandledError = []() {
+ Error E = make_error<CustomError>(42);
+ (void)!E;
+ };
+ EXPECT_DEATH(DropUnhandledError(),
+ "Program aborted due to an unhandled Error:")
+ << "Unhandled Error failure value did not cause abort()";
+}
+#endif
+
+// Check 'Error::isA<T>' method handling.
+TEST(Error, IsAHandling) {
+ // Check 'isA' handling.
+ Error E = make_error<CustomError>(1);
+ Error F = make_error<CustomSubError>(1, 2);
+ Error G = Error::success();
+
+ EXPECT_TRUE(E.isA<CustomError>());
+ EXPECT_FALSE(E.isA<CustomSubError>());
+ EXPECT_TRUE(F.isA<CustomError>());
+ EXPECT_TRUE(F.isA<CustomSubError>());
+ EXPECT_FALSE(G.isA<CustomError>());
+
+ consumeError(std::move(E));
+ consumeError(std::move(F));
+ consumeError(std::move(G));
+}
+
+// Check that we can handle a custom error.
+TEST(Error, HandleCustomError) {
+ int CaughtErrorInfo = 0;
+ handleAllErrors(make_error<CustomError>(42), [&](const CustomError &CE) {
+ CaughtErrorInfo = CE.getInfo();
+ });
+
+ EXPECT_TRUE(CaughtErrorInfo == 42) << "Wrong result from CustomError handler";
+}
+
+// Check that handler type deduction also works for handlers
+// of the following types:
+// void (const Err&)
+// Error (const Err&) mutable
+// void (const Err&) mutable
+// Error (Err&)
+// void (Err&)
+// Error (Err&) mutable
+// void (Err&) mutable
+// Error (unique_ptr<Err>)
+// void (unique_ptr<Err>)
+// Error (unique_ptr<Err>) mutable
+// void (unique_ptr<Err>) mutable
+TEST(Error, HandlerTypeDeduction) {
+
+ handleAllErrors(make_error<CustomError>(42), [](const CustomError &CE) {});
+
+ handleAllErrors(
+ make_error<CustomError>(42),
+ [](const CustomError &CE) mutable { return Error::success(); });
+
+ handleAllErrors(make_error<CustomError>(42),
+ [](const CustomError &CE) mutable {});
+
+ handleAllErrors(make_error<CustomError>(42),
+ [](CustomError &CE) { return Error::success(); });
+
+ handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) {});
+
+ handleAllErrors(make_error<CustomError>(42),
+ [](CustomError &CE) mutable { return Error::success(); });
+
+ handleAllErrors(make_error<CustomError>(42), [](CustomError &CE) mutable {});
+
+ handleAllErrors(
+ make_error<CustomError>(42),
+ [](std::unique_ptr<CustomError> CE) { return Error::success(); });
+
+ handleAllErrors(make_error<CustomError>(42),
+ [](std::unique_ptr<CustomError> CE) {});
+
+ handleAllErrors(
+ make_error<CustomError>(42),
+ [](std::unique_ptr<CustomError> CE) mutable { return Error::success(); });
+
+ handleAllErrors(make_error<CustomError>(42),
+ [](std::unique_ptr<CustomError> CE) mutable {});
+
+ // Check that named handlers of type 'Error (const Err&)' work.
+ handleAllErrors(make_error<CustomError>(42), handleCustomError);
+
+ // Check that named handlers of type 'void (const Err&)' work.
+ handleAllErrors(make_error<CustomError>(42), handleCustomErrorVoid);
+
+ // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
+ handleAllErrors(make_error<CustomError>(42), handleCustomErrorUP);
+
+ // Check that named handlers of type 'Error (std::unique_ptr<Err>)' work.
+ handleAllErrors(make_error<CustomError>(42), handleCustomErrorUPVoid);
+}
+
+// Test that we can handle errors with custom base classes.
+TEST(Error, HandleCustomErrorWithCustomBaseClass) {
+ int CaughtErrorInfo = 0;
+ int CaughtErrorExtraInfo = 0;
+ handleAllErrors(make_error<CustomSubError>(42, 7),
+ [&](const CustomSubError &SE) {
+ CaughtErrorInfo = SE.getInfo();
+ CaughtErrorExtraInfo = SE.getExtraInfo();
+ });
+
+ EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7)
+ << "Wrong result from CustomSubError handler";
+}
+
+// Check that we trigger only the first handler that applies.
+TEST(Error, FirstHandlerOnly) {
+ int DummyInfo = 0;
+ int CaughtErrorInfo = 0;
+ int CaughtErrorExtraInfo = 0;
+
+ handleAllErrors(make_error<CustomSubError>(42, 7),
+ [&](const CustomSubError &SE) {
+ CaughtErrorInfo = SE.getInfo();
+ CaughtErrorExtraInfo = SE.getExtraInfo();
+ },
+ [&](const CustomError &CE) { DummyInfo = CE.getInfo(); });
+
+ EXPECT_TRUE(CaughtErrorInfo == 42 && CaughtErrorExtraInfo == 7 &&
+ DummyInfo == 0)
+ << "Activated the wrong Error handler(s)";
+}
+
+// Check that general handlers shadow specific ones.
+TEST(Error, HandlerShadowing) {
+ int CaughtErrorInfo = 0;
+ int DummyInfo = 0;
+ int DummyExtraInfo = 0;
+
+ handleAllErrors(
+ make_error<CustomSubError>(42, 7),
+ [&](const CustomError &CE) { CaughtErrorInfo = CE.getInfo(); },
+ [&](const CustomSubError &SE) {
+ DummyInfo = SE.getInfo();
+ DummyExtraInfo = SE.getExtraInfo();
+ });
+
+ EXPECT_TRUE(CaughtErrorInfo == 42 && DummyInfo == 0 && DummyExtraInfo == 0)
+ << "General Error handler did not shadow specific handler";
+}
+
+// Test joinErrors.
+TEST(Error, CheckJoinErrors) {
+ int CustomErrorInfo1 = 0;
+ int CustomErrorInfo2 = 0;
+ int CustomErrorExtraInfo = 0;
+ Error E =
+ joinErrors(make_error<CustomError>(7), make_error<CustomSubError>(42, 7));
+
+ handleAllErrors(std::move(E),
+ [&](const CustomSubError &SE) {
+ CustomErrorInfo2 = SE.getInfo();
+ CustomErrorExtraInfo = SE.getExtraInfo();
+ },
+ [&](const CustomError &CE) {
+ // Assert that the CustomError instance above is handled
+ // before the
+ // CustomSubError - joinErrors should preserve error
+ // ordering.
+ EXPECT_EQ(CustomErrorInfo2, 0)
+ << "CustomErrorInfo2 should be 0 here. "
+ "joinErrors failed to preserve ordering.\n";
+ CustomErrorInfo1 = CE.getInfo();
+ });
+
+ EXPECT_TRUE(CustomErrorInfo1 == 7 && CustomErrorInfo2 == 42 &&
+ CustomErrorExtraInfo == 7)
+ << "Failed handling compound Error.";
+
+ // Test appending a single item to a list.
+ {
+ int Sum = 0;
+ handleAllErrors(
+ joinErrors(
+ joinErrors(make_error<CustomError>(7),
+ make_error<CustomError>(7)),
+ make_error<CustomError>(7)),
+ [&](const CustomError &CE) {
+ Sum += CE.getInfo();
+ });
+ EXPECT_EQ(Sum, 21) << "Failed to correctly append error to error list.";
+ }
+
+ // Test prepending a single item to a list.
+ {
+ int Sum = 0;
+ handleAllErrors(
+ joinErrors(
+ make_error<CustomError>(7),
+ joinErrors(make_error<CustomError>(7),
+ make_error<CustomError>(7))),
+ [&](const CustomError &CE) {
+ Sum += CE.getInfo();
+ });
+ EXPECT_EQ(Sum, 21) << "Failed to correctly prepend error to error list.";
+ }
+
+ // Test concatenating two error lists.
+ {
+ int Sum = 0;
+ handleAllErrors(
+ joinErrors(
+ joinErrors(
+ make_error<CustomError>(7),
+ make_error<CustomError>(7)),
+ joinErrors(
+ make_error<CustomError>(7),
+ make_error<CustomError>(7))),
+ [&](const CustomError &CE) {
+ Sum += CE.getInfo();
+ });
+ EXPECT_EQ(Sum, 28) << "Failed to correctly concatenate erorr lists.";
+ }
+}
+
+// Test that we can consume success values.
+TEST(Error, ConsumeSuccess) {
+ Error E;
+ consumeError(std::move(E));
+}
+
+TEST(Error, ConsumeError) {
+ Error E = make_error<CustomError>(7);
+ consumeError(std::move(E));
+}
+
+// Test that handleAllUnhandledErrors crashes if an error is not caught.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, FailureToHandle) {
+ auto FailToHandle = []() {
+ handleAllErrors(make_error<CustomError>(7), [&](const CustomSubError &SE) {
+ errs() << "This should never be called";
+ exit(1);
+ });
+ };
+
+ EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:")
+ << "Unhandled Error in handleAllErrors call did not cause an "
+ "abort()";
+}
+#endif
+
+// Test that handleAllUnhandledErrors crashes if an error is returned from a
+// handler.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, FailureFromHandler) {
+ auto ReturnErrorFromHandler = []() {
+ handleAllErrors(make_error<CustomError>(7),
+ [&](std::unique_ptr<CustomSubError> SE) {
+ return Error(std::move(SE));
+ });
+ };
+
+ EXPECT_DEATH(ReturnErrorFromHandler(),
+ "Program aborted due to an unhandled Error:")
+ << " Error returned from handler in handleAllErrors call did not "
+ "cause abort()";
+}
+#endif
+
+// Test that we can return values from handleErrors.
+TEST(Error, CatchErrorFromHandler) {
+ int ErrorInfo = 0;
+
+ Error E = handleErrors(
+ make_error<CustomError>(7),
+ [&](std::unique_ptr<CustomError> CE) { return Error(std::move(CE)); });
+
+ handleAllErrors(std::move(E),
+ [&](const CustomError &CE) { ErrorInfo = CE.getInfo(); });
+
+ EXPECT_EQ(ErrorInfo, 7)
+ << "Failed to handle Error returned from handleErrors.";
+}
+
+TEST(Error, StringError) {
+ std::string Msg;
+ raw_string_ostream S(Msg);
+ logAllUnhandledErrors(make_error<StringError>("foo" + Twine(42),
+ inconvertibleErrorCode()),
+ S, "");
+ EXPECT_EQ(S.str(), "foo42\n") << "Unexpected StringError log result";
+
+ auto EC =
+ errorToErrorCode(make_error<StringError>("", errc::invalid_argument));
+ EXPECT_EQ(EC, errc::invalid_argument)
+ << "Failed to convert StringError to error_code.";
+}
+
+// Test that the ExitOnError utility works as expected.
+TEST(Error, ExitOnError) {
+ ExitOnError ExitOnErr;
+ ExitOnErr.setBanner("Error in tool:");
+ ExitOnErr.setExitCodeMapper([](const Error &E) {
+ if (E.isA<CustomSubError>())
+ return 2;
+ return 1;
+ });
+
+ // Make sure we don't bail on success.
+ ExitOnErr(Error::success());
+ EXPECT_EQ(ExitOnErr(Expected<int>(7)), 7)
+ << "exitOnError returned an invalid value for Expected";
+
+ int A = 7;
+ int &B = ExitOnErr(Expected<int&>(A));
+ EXPECT_EQ(&A, &B) << "ExitOnError failed to propagate reference";
+
+ // Exit tests.
+ EXPECT_EXIT(ExitOnErr(make_error<CustomError>(7)),
+ ::testing::ExitedWithCode(1), "Error in tool:")
+ << "exitOnError returned an unexpected error result";
+
+ EXPECT_EXIT(ExitOnErr(Expected<int>(make_error<CustomSubError>(0, 0))),
+ ::testing::ExitedWithCode(2), "Error in tool:")
+ << "exitOnError returned an unexpected error result";
+}
+
+// Test Checked Expected<T> in success mode.
+TEST(Error, CheckedExpectedInSuccessMode) {
+ Expected<int> A = 7;
+ EXPECT_TRUE(!!A) << "Expected with non-error value doesn't convert to 'true'";
+ // Access is safe in second test, since we checked the error in the first.
+ EXPECT_EQ(*A, 7) << "Incorrect Expected non-error value";
+}
+
+// Test Expected with reference type.
+TEST(Error, ExpectedWithReferenceType) {
+ int A = 7;
+ Expected<int&> B = A;
+ // 'Check' B.
+ (void)!!B;
+ int &C = *B;
+ EXPECT_EQ(&A, &C) << "Expected failed to propagate reference";
+}
+
+// Test Unchecked Expected<T> in success mode.
+// We expect this to blow up the same way Error would.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, UncheckedExpectedInSuccessModeDestruction) {
+ EXPECT_DEATH({ Expected<int> A = 7; },
+ "Expected<T> must be checked before access or destruction.")
+ << "Unchecekd Expected<T> success value did not cause an abort().";
+}
+#endif
+
+// Test Unchecked Expected<T> in success mode.
+// We expect this to blow up the same way Error would.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, UncheckedExpectedInSuccessModeAccess) {
+ EXPECT_DEATH({ Expected<int> A = 7; *A; },
+ "Expected<T> must be checked before access or destruction.")
+ << "Unchecekd Expected<T> success value did not cause an abort().";
+}
+#endif
+
+// Test Unchecked Expected<T> in success mode.
+// We expect this to blow up the same way Error would.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, UncheckedExpectedInSuccessModeAssignment) {
+ EXPECT_DEATH({ Expected<int> A = 7; A = 7; },
+ "Expected<T> must be checked before access or destruction.")
+ << "Unchecekd Expected<T> success value did not cause an abort().";
+}
+#endif
+
+// Test Expected<T> in failure mode.
+TEST(Error, ExpectedInFailureMode) {
+ Expected<int> A = make_error<CustomError>(42);
+ EXPECT_FALSE(!!A) << "Expected with error value doesn't convert to 'false'";
+ Error E = A.takeError();
+ EXPECT_TRUE(E.isA<CustomError>()) << "Incorrect Expected error value";
+ consumeError(std::move(E));
+}
+
+// Check that an Expected instance with an error value doesn't allow access to
+// operator*.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, AccessExpectedInFailureMode) {
+ Expected<int> A = make_error<CustomError>(42);
+ EXPECT_DEATH(*A, "Expected<T> must be checked before access or destruction.")
+ << "Incorrect Expected error value";
+ consumeError(A.takeError());
+}
+#endif
+
+// Check that an Expected instance with an error triggers an abort if
+// unhandled.
+// Test runs in debug mode only.
+#ifndef NDEBUG
+TEST(Error, UnhandledExpectedInFailureMode) {
+ EXPECT_DEATH({ Expected<int> A = make_error<CustomError>(42); },
+ "Expected<T> must be checked before access or destruction.")
+ << "Unchecked Expected<T> failure value did not cause an abort()";
+}
+#endif
+
+// Test covariance of Expected.
+TEST(Error, ExpectedCovariance) {
+ class B {};
+ class D : public B {};
+
+ Expected<B *> A1(Expected<D *>(nullptr));
+ // Check A1 by converting to bool before assigning to it.
+ (void)!!A1;
+ A1 = Expected<D *>(nullptr);
+ // Check A1 again before destruction.
+ (void)!!A1;
+
+ Expected<std::unique_ptr<B>> A2(Expected<std::unique_ptr<D>>(nullptr));
+ // Check A2 by converting to bool before assigning to it.
+ (void)!!A2;
+ A2 = Expected<std::unique_ptr<D>>(nullptr);
+ // Check A2 again before destruction.
+ (void)!!A2;
+}
+
+TEST(Error, ErrorCodeConversions) {
+ // Round-trip a success value to check that it converts correctly.
+ EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())),
+ std::error_code())
+ << "std::error_code() should round-trip via Error conversions";
+
+ // Round-trip an error value to check that it converts correctly.
+ EXPECT_EQ(errorToErrorCode(errorCodeToError(errc::invalid_argument)),
+ errc::invalid_argument)
+ << "std::error_code error value should round-trip via Error "
+ "conversions";
+
+ // Round-trip a success value through ErrorOr/Expected to check that it
+ // converts correctly.
+ {
+ auto Orig = ErrorOr<int>(42);
+ auto RoundTripped =
+ expectedToErrorOr(errorOrToExpected(ErrorOr<int>(42)));
+ EXPECT_EQ(*Orig, *RoundTripped)
+ << "ErrorOr<T> success value should round-trip via Expected<T> "
+ "conversions.";
+ }
+
+ // Round-trip a failure value through ErrorOr/Expected to check that it
+ // converts correctly.
+ {
+ auto Orig = ErrorOr<int>(errc::invalid_argument);
+ auto RoundTripped =
+ expectedToErrorOr(
+ errorOrToExpected(ErrorOr<int>(errc::invalid_argument)));
+ EXPECT_EQ(Orig.getError(), RoundTripped.getError())
+ << "ErrorOr<T> failure value should round-trip via Expected<T> "
+ "conversions.";
+ }
+}
+
+// Test that error messages work.
+TEST(Error, ErrorMessage) {
+ EXPECT_EQ(toString(Error::success()).compare(""), 0);
+
+ Error E1 = make_error<CustomError>(0);
+ EXPECT_EQ(toString(std::move(E1)).compare("CustomError { 0}"), 0);
+
+ Error E2 = make_error<CustomError>(0);
+ handleAllErrors(std::move(E2), [](const CustomError &CE) {
+ EXPECT_EQ(CE.message().compare("CustomError { 0}"), 0);
+ });
+
+ Error E3 = joinErrors(make_error<CustomError>(0), make_error<CustomError>(1));
+ EXPECT_EQ(toString(std::move(E3))
+ .compare("CustomError { 0}\n"
+ "CustomError { 1}"),
+ 0);
+}
+
+} // end anon namespace
diff --git a/unittests/Support/Makefile b/unittests/Support/Makefile
deleted file mode 100644
index 21657f12e3dc1..0000000000000
--- a/unittests/Support/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- 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/unittests/Support/MathExtrasTest.cpp b/unittests/Support/MathExtrasTest.cpp
index 97309f8d31f5e..d373030881ec7 100644
--- a/unittests/Support/MathExtrasTest.cpp
+++ b/unittests/Support/MathExtrasTest.cpp
@@ -106,6 +106,40 @@ TEST(MathExtras, findLastSet) {
EXPECT_EQ(5u, findLastSet(NZ64));
}
+TEST(MathExtras, isIntN) {
+ EXPECT_TRUE(isIntN(16, 32767));
+ EXPECT_FALSE(isIntN(16, 32768));
+}
+
+TEST(MathExtras, isUIntN) {
+ EXPECT_TRUE(isUIntN(16, 65535));
+ EXPECT_FALSE(isUIntN(16, 65536));
+ EXPECT_TRUE(isUIntN(1, 0));
+ EXPECT_TRUE(isUIntN(6, 63));
+}
+
+TEST(MathExtras, maxIntN) {
+ EXPECT_EQ(32767, maxIntN(16));
+ EXPECT_EQ(2147483647, maxIntN(32));
+ EXPECT_EQ(std::numeric_limits<int32_t>::max(), maxIntN(32));
+ EXPECT_EQ(std::numeric_limits<int64_t>::max(), maxIntN(64));
+}
+
+TEST(MathExtras, minIntN) {
+ EXPECT_EQ(-32768LL, minIntN(16));
+ EXPECT_EQ(-64LL, minIntN(7));
+ EXPECT_EQ(std::numeric_limits<int32_t>::min(), minIntN(32));
+ EXPECT_EQ(std::numeric_limits<int64_t>::min(), minIntN(64));
+}
+
+TEST(MathExtras, maxUIntN) {
+ EXPECT_EQ(0xffffULL, maxUIntN(16));
+ EXPECT_EQ(0xffffffffULL, maxUIntN(32));
+ EXPECT_EQ(0xffffffffffffffffULL, maxUIntN(64));
+ EXPECT_EQ(1ULL, maxUIntN(1));
+ EXPECT_EQ(0x0fULL, maxUIntN(4));
+}
+
TEST(MathExtras, reverseBits) {
uint8_t NZ8 = 42;
uint16_t NZ16 = 42;
@@ -163,7 +197,7 @@ TEST(MathExtras, FloatBits) {
TEST(MathExtras, DoubleBits) {
static const double kValue = 87987234.983498;
- EXPECT_FLOAT_EQ(kValue, BitsToDouble(DoubleToBits(kValue)));
+ EXPECT_DOUBLE_EQ(kValue, BitsToDouble(DoubleToBits(kValue)));
}
TEST(MathExtras, MinAlign) {
@@ -179,15 +213,15 @@ TEST(MathExtras, NextPowerOf2) {
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));
+TEST(MathExtras, alignTo) {
+ EXPECT_EQ(8u, alignTo(5, 8));
+ EXPECT_EQ(24u, alignTo(17, 8));
+ EXPECT_EQ(0u, alignTo(~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));
+ EXPECT_EQ(7u, alignTo(5, 8, 7));
+ EXPECT_EQ(17u, alignTo(17, 8, 1));
+ EXPECT_EQ(3u, alignTo(~0LL, 8, 3));
+ EXPECT_EQ(552u, alignTo(321, 255, 42));
}
template<typename T>
@@ -358,4 +392,42 @@ TEST(MathExtras, SaturatingMultiplyAdd) {
SaturatingMultiplyAddTestHelper<uint64_t>();
}
+TEST(MathExtras, IsShiftedUInt) {
+ EXPECT_TRUE((isShiftedUInt<1, 0>(0)));
+ EXPECT_TRUE((isShiftedUInt<1, 0>(1)));
+ EXPECT_FALSE((isShiftedUInt<1, 0>(2)));
+ EXPECT_FALSE((isShiftedUInt<1, 0>(3)));
+ EXPECT_FALSE((isShiftedUInt<1, 0>(0x8000000000000000)));
+ EXPECT_TRUE((isShiftedUInt<1, 63>(0x8000000000000000)));
+ EXPECT_TRUE((isShiftedUInt<2, 62>(0xC000000000000000)));
+ EXPECT_FALSE((isShiftedUInt<2, 62>(0xE000000000000000)));
+
+ // 0x201 is ten bits long and has a 1 in the MSB and LSB.
+ EXPECT_TRUE((isShiftedUInt<10, 5>(uint64_t(0x201) << 5)));
+ EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 4)));
+ EXPECT_FALSE((isShiftedUInt<10, 5>(uint64_t(0x201) << 6)));
}
+
+TEST(MathExtras, IsShiftedInt) {
+ EXPECT_TRUE((isShiftedInt<1, 0>(0)));
+ EXPECT_TRUE((isShiftedInt<1, 0>(-1)));
+ EXPECT_FALSE((isShiftedInt<1, 0>(2)));
+ EXPECT_FALSE((isShiftedInt<1, 0>(3)));
+ EXPECT_FALSE((isShiftedInt<1, 0>(0x8000000000000000)));
+ EXPECT_TRUE((isShiftedInt<1, 63>(0x8000000000000000)));
+ EXPECT_TRUE((isShiftedInt<2, 62>(0xC000000000000000)));
+ EXPECT_FALSE((isShiftedInt<2, 62>(0xE000000000000000)));
+
+ // 0x201 is ten bits long and has a 1 in the MSB and LSB.
+ EXPECT_TRUE((isShiftedInt<11, 5>(int64_t(0x201) << 5)));
+ EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 3)));
+ EXPECT_FALSE((isShiftedInt<11, 5>(int64_t(0x201) << 6)));
+ EXPECT_TRUE((isShiftedInt<11, 5>(-(int64_t(0x201) << 5))));
+ EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 3))));
+ EXPECT_FALSE((isShiftedInt<11, 5>(-(int64_t(0x201) << 6))));
+
+ EXPECT_TRUE((isShiftedInt<6, 10>(-(int64_t(1) << 15))));
+ EXPECT_FALSE((isShiftedInt<6, 10>(int64_t(1) << 15)));
+}
+
+} // namespace
diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp
index 3f626f87888a3..1a6ffa50e983e 100644
--- a/unittests/Support/Path.cpp
+++ b/unittests/Support/Path.cpp
@@ -17,6 +17,7 @@
#include "gtest/gtest.h"
#ifdef LLVM_ON_WIN32
+#include "llvm/ADT/ArrayRef.h"
#include <windows.h>
#include <winerror.h>
#endif
@@ -416,7 +417,7 @@ TEST(SupportDeathTest, TempDirectoryOnWindows) {
SmallString<270> Expected{"C:\\Temp\\AB\\123456789"};
while (Expected.size() < 260)
Expected.append("\\DirNameWith19Charss");
- ASSERT_EQ(260, Expected.size());
+ ASSERT_EQ(260U, Expected.size());
EXPECT_TEMP_DIR(_putenv_s("TMP", Expected.c_str()), Expected.c_str());
}
#endif
@@ -715,6 +716,20 @@ TEST_F(FileSystemTest, DirectoryIteration) {
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"));
+
+ // Test recursive_directory_iterator level()
+ ASSERT_NO_ERROR(
+ fs::create_directories(Twine(TestDirectory) + "/reclevel/a/b/c"));
+ fs::recursive_directory_iterator I(Twine(TestDirectory) + "/reclevel", ec), E;
+ for (int l = 0; I != E; I.increment(ec), ++l) {
+ ASSERT_NO_ERROR(ec);
+ EXPECT_EQ(I.level(), l);
+ }
+ EXPECT_EQ(I, E);
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b/c"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a/b"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel/a"));
+ ASSERT_NO_ERROR(fs::remove(Twine(TestDirectory) + "/reclevel"));
}
const char archive[] = "!<arch>\x0A";
@@ -725,22 +740,30 @@ const char coff_bigobj[] = "\x00\x00\xff\xff\x00\x02......"
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_universal_binary[] = "\xca\xfe\xba\xbe...\x00";
+const char macho_object[] =
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x01............";
+const char macho_executable[] =
+ "\xfe\xed\xfa\xce........\x00\x00\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";
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x03............";
+const char macho_core[] =
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x04............";
+const char macho_preload_executable[] =
+ "\xfe\xed\xfa\xce........\x00\x00\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";
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x06............";
+const char macho_dynamic_linker[] =
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x07............";
+const char macho_bundle[] =
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x08............";
+const char macho_dsym_companion[] =
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x0a............";
+const char macho_kext_bundle[] =
+ "\xfe\xed\xfa\xce........\x00\x00\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";
+ "\xfe\xed\xfa\xce........\x00\x00\x00\x09............";
TEST_F(FileSystemTest, Magic) {
struct type {
@@ -947,4 +970,145 @@ TEST(Support, RemoveDots) {
EXPECT_EQ("c", Path1);
#endif
}
+
+TEST(Support, ReplacePathPrefix) {
+ SmallString<64> Path1("/foo");
+ SmallString<64> Path2("/old/foo");
+ SmallString<64> OldPrefix("/old");
+ SmallString<64> NewPrefix("/new");
+ SmallString<64> NewPrefix2("/longernew");
+ SmallString<64> EmptyPrefix("");
+
+ SmallString<64> Path = Path1;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/foo");
+ Path = Path2;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/foo");
+ Path = Path2;
+ path::replace_path_prefix(Path, OldPrefix, NewPrefix2);
+ EXPECT_EQ(Path, "/longernew/foo");
+ Path = Path1;
+ path::replace_path_prefix(Path, EmptyPrefix, NewPrefix);
+ EXPECT_EQ(Path, "/new/foo");
+ Path = Path2;
+ path::replace_path_prefix(Path, OldPrefix, EmptyPrefix);
+ EXPECT_EQ(Path, "/foo");
+}
+
+TEST_F(FileSystemTest, PathFromFD) {
+ // 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)));
+
+ // Try to get the path from the file descriptor
+ SmallString<64> ResultPath;
+ std::error_code ErrorCode =
+ fs::getPathFromOpenFD(FileDescriptor, ResultPath);
+
+ // If we succeeded, check that the paths are the same (modulo case):
+ if (!ErrorCode) {
+ // The paths returned by createTemporaryFile and getPathFromOpenFD
+ // should reference the same file on disk.
+ fs::UniqueID D1, D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
+ ASSERT_EQ(D1, D2);
+ }
+
+ ::close(FileDescriptor);
+}
+
+TEST_F(FileSystemTest, PathFromFDWin32) {
+ // 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)));
+
+ SmallVector<char, 8> ResultPath;
+ std::error_code ErrorCode =
+ fs::getPathFromOpenFD(FileDescriptor, ResultPath);
+
+ if (!ErrorCode) {
+ // Now that we know how much space is required for the path, create a path
+ // buffer with exactly enough space (sans null terminator, which should not
+ // be present), and call getPathFromOpenFD again to ensure that the API
+ // properly handles exactly-sized buffers.
+ SmallVector<char, 8> ExactSizedPath(ResultPath.size());
+ ErrorCode = fs::getPathFromOpenFD(FileDescriptor, ExactSizedPath);
+ ResultPath = ExactSizedPath;
+ }
+
+ if (!ErrorCode) {
+ fs::UniqueID D1, D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
+ ASSERT_EQ(D1, D2);
+ }
+ ::close(FileDescriptor);
+}
+
+TEST_F(FileSystemTest, PathFromFDUnicode) {
+ // Create a temp file.
+ int FileDescriptor;
+ SmallString<64> TempPath;
+
+ // Test Unicode: "<temp directory>/(pi)r^2<temp rand chars>.aleth.0"
+ ASSERT_NO_ERROR(
+ fs::createTemporaryFile("\xCF\x80r\xC2\xB2",
+ "\xE2\x84\xB5.0", FileDescriptor, TempPath));
+
+ // Make sure it exists.
+ ASSERT_TRUE(sys::fs::exists(Twine(TempPath)));
+
+ SmallVector<char, 8> ResultPath;
+ std::error_code ErrorCode =
+ fs::getPathFromOpenFD(FileDescriptor, ResultPath);
+
+ if (!ErrorCode) {
+ fs::UniqueID D1, D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
+ ASSERT_EQ(D1, D2);
+ }
+ ::close(FileDescriptor);
+}
+
+TEST_F(FileSystemTest, OpenFileForRead) {
+ // 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)));
+
+ // Open the file for read
+ int FileDescriptor2;
+ SmallString<64> ResultPath;
+ ASSERT_NO_ERROR(
+ fs::openFileForRead(Twine(TempPath), FileDescriptor2, &ResultPath))
+
+ // If we succeeded, check that the paths are the same (modulo case):
+ if (!ResultPath.empty()) {
+ // The paths returned by createTemporaryFile and getPathFromOpenFD
+ // should reference the same file on disk.
+ fs::UniqueID D1, D2;
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(TempPath), D1));
+ ASSERT_NO_ERROR(fs::getUniqueID(Twine(ResultPath), D2));
+ ASSERT_EQ(D1, D2);
+ }
+
+ ::close(FileDescriptor);
+}
} // anonymous namespace
diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp
index 47a3dbb5fb1f1..886ead8305bc1 100644
--- a/unittests/Support/ProgramTest.cpp
+++ b/unittests/Support/ProgramTest.cpp
@@ -223,7 +223,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0,
&Error, &ExecutionFailed);
ASSERT_FALSE(ExecutionFailed) << Error;
- ASSERT_NE(PI1.Pid, 0) << "Invalid process id";
+ ASSERT_NE(PI1.Pid, ProcessInfo::InvalidPid) << "Invalid process id";
unsigned LoopCount = 0;
@@ -231,7 +231,7 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
// LoopCount should only be incremented once.
while (true) {
++LoopCount;
- ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
+ ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error);
ASSERT_TRUE(Error.empty());
if (WaitResult.Pid == PI1.Pid)
break;
@@ -242,13 +242,13 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {
ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0,
&Error, &ExecutionFailed);
ASSERT_FALSE(ExecutionFailed) << Error;
- ASSERT_NE(PI2.Pid, 0) << "Invalid process id";
+ ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "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);
+ ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error);
ASSERT_TRUE(Error.empty());
if (WaitResult.Pid == PI2.Pid)
break;
@@ -304,7 +304,7 @@ TEST(ProgramTest, TestExecuteNegative) {
bool ExecutionFailed;
ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0,
&Error, &ExecutionFailed);
- ASSERT_EQ(PI.Pid, 0)
+ ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid)
<< "On error ExecuteNoWait should return an invalid ProcessInfo";
ASSERT_TRUE(ExecutionFailed);
ASSERT_FALSE(Error.empty());
diff --git a/unittests/Support/StreamingMemoryObject.cpp b/unittests/Support/StreamingMemoryObject.cpp
deleted file mode 100644
index e86aa9cae51e8..0000000000000
--- a/unittests/Support/StreamingMemoryObject.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- 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/unittests/Support/StreamingMemoryObjectTest.cpp b/unittests/Support/StreamingMemoryObjectTest.cpp
new file mode 100644
index 0000000000000..836dfa9084f5b
--- /dev/null
+++ b/unittests/Support/StreamingMemoryObjectTest.cpp
@@ -0,0 +1,68 @@
+//===- unittests/Support/StreamingMemoryObjectTest.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/STLExtras.h"
+#include "llvm/ADT/StringRef.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 *Buffer, size_t Length) override {
+ memset(Buffer, 0, Length);
+ return Length;
+ }
+};
+
+class BufferStreamer : public DataStreamer {
+ StringRef Buffer;
+
+public:
+ BufferStreamer(StringRef Buffer) : Buffer(Buffer) {}
+ size_t GetBytes(unsigned char *OutBuffer, size_t Length) override {
+ if (Length >= Buffer.size())
+ Length = Buffer.size();
+
+ std::copy(Buffer.begin(), Buffer.begin() + Length, OutBuffer);
+ Buffer = Buffer.drop_front(Length);
+ return Length;
+ }
+};
+
+TEST(StreamingMemoryObjectTest, isValidAddress) {
+ auto DS = make_unique<NullDataStreamer>();
+ StreamingMemoryObject O(std::move(DS));
+ EXPECT_TRUE(O.isValidAddress(32 * 1024));
+}
+
+TEST(StreamingMemoryObjectTest, setKnownObjectSize) {
+ auto DS = make_unique<NullDataStreamer>();
+ StreamingMemoryObject O(std::move(DS));
+ uint8_t Buf[32];
+ EXPECT_EQ(16u, O.readBytes(Buf, 16, 0));
+ O.setKnownObjectSize(24);
+ EXPECT_EQ(8u, O.readBytes(Buf, 16, 16));
+}
+
+TEST(StreamingMemoryObjectTest, getPointer) {
+ uint8_t InputBuffer[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07};
+ StreamingMemoryObject O(make_unique<BufferStreamer>(StringRef(
+ reinterpret_cast<const char *>(InputBuffer), sizeof(InputBuffer))));
+
+ EXPECT_TRUE(std::equal(InputBuffer + 1, InputBuffer + 2, O.getPointer(1, 2)));
+ EXPECT_TRUE(std::equal(InputBuffer + 3, InputBuffer + 7, O.getPointer(3, 4)));
+ EXPECT_TRUE(std::equal(InputBuffer + 4, InputBuffer + 8, O.getPointer(4, 5)));
+ EXPECT_TRUE(std::equal(InputBuffer, InputBuffer + 8, O.getPointer(0, 20)));
+}
+
+} // end namespace
diff --git a/unittests/Support/TargetParserTest.cpp b/unittests/Support/TargetParserTest.cpp
new file mode 100644
index 0000000000000..21994f27b73cd
--- /dev/null
+++ b/unittests/Support/TargetParserTest.cpp
@@ -0,0 +1,92 @@
+//===----------- TargetParser.cpp - Target Parser -------------------------===//
+//
+// 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/TargetParser.h"
+
+using namespace llvm;
+
+namespace {
+static const unsigned kAArch64ArchKinds[] = {
+#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, \
+ ARCH_BASE_EXT) \
+ llvm::ARM::ID,
+#include "llvm/Support/AArch64TargetParser.def"
+#undef AARCH64_ARCH
+};
+
+template <typename T, size_t N>
+bool contains(const T (&array)[N], const T element) {
+ return std::find(std::begin(array), std::end(array), element) !=
+ std::end(array);
+}
+
+TEST(TargetParserTest, ARMArchName) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE(AK == ARM::AK_LAST ? ARM::getArchName(AK).empty()
+ : !ARM::getArchName(AK).empty());
+}
+
+TEST(TargetParserTest, ARMCPUAttr) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_LAST)
+ ? ARM::getCPUAttr(AK).empty()
+ : !ARM::getCPUAttr(AK).empty());
+}
+
+TEST(TargetParserTest, ARMSubArch) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE((AK == ARM::AK_INVALID || AK == ARM::AK_IWMMXT ||
+ AK == ARM::AK_IWMMXT2 || AK == ARM::AK_LAST)
+ ? ARM::getSubArch(AK).empty()
+ : !ARM::getSubArch(AK).empty());
+}
+
+TEST(TargetParserTest, ARMFPUName) {
+ for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);
+ FK <= ARM::FPUKind::FK_LAST;
+ FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1))
+ EXPECT_TRUE(FK == ARM::FK_LAST ? ARM::getFPUName(FK).empty()
+ : !ARM::getFPUName(FK).empty());
+}
+
+TEST(TargetParserTest, AArch64ArchName) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK))
+ ? !AArch64::getArchName(AK).empty()
+ : AArch64::getArchName(AK).empty());
+}
+
+TEST(TargetParserTest, AArch64CPUAttr) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK))
+ ? !AArch64::getCPUAttr(AK).empty()
+ : AArch64::getCPUAttr(AK).empty());
+}
+
+TEST(TargetParserTest, AArch64SubArch) {
+ for (ARM::ArchKind AK = static_cast<ARM::ArchKind>(0);
+ AK <= ARM::ArchKind::AK_LAST;
+ AK = static_cast<ARM::ArchKind>(static_cast<unsigned>(AK) + 1))
+ EXPECT_TRUE(contains(kAArch64ArchKinds, static_cast<unsigned>(AK))
+ ? !AArch64::getSubArch(AK).empty()
+ : AArch64::getSubArch(AK).empty());
+}
+}
+
diff --git a/unittests/Support/TargetRegistry.cpp b/unittests/Support/TargetRegistry.cpp
deleted file mode 100644
index ae89c8b649303..0000000000000
--- a/unittests/Support/TargetRegistry.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- 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/unittests/Support/ThreadPool.cpp b/unittests/Support/ThreadPool.cpp
index 0f36c383d494c..69a24bc5444c0 100644
--- a/unittests/Support/ThreadPool.cpp
+++ b/unittests/Support/ThreadPool.cpp
@@ -135,7 +135,7 @@ TEST_F(ThreadPoolTest, Async) {
TEST_F(ThreadPoolTest, GetFuture) {
CHECK_UNSUPPORTED();
- ThreadPool Pool;
+ ThreadPool Pool{2};
std::atomic_int i{0};
Pool.async([this, &i] {
waitForMainThread();
diff --git a/unittests/Support/TrailingObjectsTest.cpp b/unittests/Support/TrailingObjectsTest.cpp
index 866ff1e6e88d8..a1d3e7b3c8645 100644
--- a/unittests/Support/TrailingObjectsTest.cpp
+++ b/unittests/Support/TrailingObjectsTest.cpp
@@ -34,6 +34,7 @@ public:
void *Mem = ::operator new(totalSizeToAlloc<short>(NumShorts));
return new (Mem) Class1(ShortArray, NumShorts);
}
+ void operator delete(void *p) { ::operator delete(p); }
short get(unsigned Num) const { return getTrailingObjects<short>()[Num]; }
@@ -78,6 +79,7 @@ public:
*C->getTrailingObjects<double>() = D;
return C;
}
+ void operator delete(void *p) { ::operator delete(p); }
short getShort() const {
if (!HasShort)
@@ -118,8 +120,8 @@ 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(sizeof(Class2),
+ llvm::alignTo(sizeof(bool) * 2, llvm::alignOf<double>()));
EXPECT_EQ(llvm::alignOf<Class2>(), llvm::alignOf<double>());
EXPECT_EQ((Class2::additionalSizeToAlloc<double, short>(1, 0)),
@@ -162,8 +164,7 @@ class Class3 final : public TrailingObjects<Class3, double, short, bool> {
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>()));
+ EXPECT_EQ(sizeof(Class3), llvm::alignTo(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));
@@ -183,8 +184,8 @@ class Class4 final : public TrailingObjects<Class4, char, long> {
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>()));
+ llvm::alignTo(sizeof(long) + 1, llvm::alignOf<long>()));
+ EXPECT_EQ(sizeof(Class4), llvm::alignTo(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));
diff --git a/unittests/Support/TypeNameTest.cpp b/unittests/Support/TypeNameTest.cpp
new file mode 100644
index 0000000000000..63381d46f02fe
--- /dev/null
+++ b/unittests/Support/TypeNameTest.cpp
@@ -0,0 +1,49 @@
+//===- TypeNameTest.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/TypeName.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+namespace N1 {
+struct S1 {};
+class C1 {};
+union U1 {};
+}
+
+TEST(TypeNameTest, Names) {
+ struct S2 {};
+
+ StringRef S1Name = getTypeName<N1::S1>();
+ StringRef C1Name = getTypeName<N1::C1>();
+ StringRef U1Name = getTypeName<N1::U1>();
+ StringRef S2Name = getTypeName<S2>();
+
+#if defined(__clang__) || defined(__GNUC__) || defined(__INTEL_COMPILER) || \
+ defined(_MSC_VER)
+ EXPECT_TRUE(S1Name.endswith("::N1::S1")) << S1Name.str();
+ EXPECT_TRUE(C1Name.endswith("::N1::C1")) << C1Name.str();
+ EXPECT_TRUE(U1Name.endswith("::N1::U1")) << U1Name.str();
+#ifdef __clang__
+ EXPECT_TRUE(S2Name.endswith("S2")) << S2Name.str();
+#else
+ EXPECT_TRUE(S2Name.endswith("::S2")) << S2Name.str();
+#endif
+#else
+ EXPECT_EQ("UNKNOWN_TYPE", S1Name);
+ EXPECT_EQ("UNKNOWN_TYPE", C1Name);
+ EXPECT_EQ("UNKNOWN_TYPE", U1Name);
+ EXPECT_EQ("UNKNOWN_TYPE", S2Name);
+#endif
+}
+
+} // end anonymous namespace
diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp
index e7affa1698dcc..5f35a802caa5e 100644
--- a/unittests/Support/YAMLIOTest.cpp
+++ b/unittests/Support/YAMLIOTest.cpp
@@ -7,9 +7,9 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Endian.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/YAMLTraits.h"
#include "gtest/gtest.h"
@@ -389,6 +389,111 @@ TEST(YAMLIO, TestReadWriteBuiltInTypes) {
}
}
+//===----------------------------------------------------------------------===//
+// Test endian-aware types
+//===----------------------------------------------------------------------===//
+
+struct EndianTypes {
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ float, llvm::support::little, llvm::support::unaligned>
+ ulittle_float;
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ double, llvm::support::little, llvm::support::unaligned>
+ ulittle_double;
+
+ llvm::support::ulittle64_t u64;
+ llvm::support::ulittle32_t u32;
+ llvm::support::ulittle16_t u16;
+ llvm::support::little64_t s64;
+ llvm::support::little32_t s32;
+ llvm::support::little16_t s16;
+ ulittle_float f;
+ ulittle_double d;
+};
+
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<EndianTypes> {
+ static void mapping(IO &io, EndianTypes &et) {
+ io.mapRequired("u64", et.u64);
+ io.mapRequired("u32", et.u32);
+ io.mapRequired("u16", et.u16);
+ io.mapRequired("s64", et.s64);
+ io.mapRequired("s32", et.s32);
+ io.mapRequired("s16", et.s16);
+ io.mapRequired("f", et.f);
+ io.mapRequired("d", et.d);
+ }
+};
+}
+}
+
+//
+// Test the reading of all endian scalar conversions
+//
+TEST(YAMLIO, TestReadEndianTypes) {
+ EndianTypes map;
+ Input yin("---\n"
+ "u64: 5000000000\n"
+ "u32: 4000000000\n"
+ "u16: 65000\n"
+ "s64: -5000000000\n"
+ "s32: -2000000000\n"
+ "s16: -32000\n"
+ "f: 3.25\n"
+ "d: -2.8625\n"
+ "...\n");
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(map.u64, 5000000000ULL);
+ EXPECT_EQ(map.u32, 4000000000U);
+ EXPECT_EQ(map.u16, 65000);
+ EXPECT_EQ(map.s64, -5000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.f, 3.25f);
+ EXPECT_EQ(map.d, -2.8625);
+}
+
+//
+// Test writing then reading back all endian-aware scalar types
+//
+TEST(YAMLIO, TestReadWriteEndianTypes) {
+ std::string intermediate;
+ {
+ EndianTypes map;
+ map.u64 = 6000000000ULL;
+ map.u32 = 3000000000U;
+ map.u16 = 50000;
+ map.s64 = -6000000000LL;
+ map.s32 = -2000000000;
+ map.s16 = -32000;
+ map.f = 3.25f;
+ map.d = -2.8625;
+
+ llvm::raw_string_ostream ostr(intermediate);
+ Output yout(ostr);
+ yout << map;
+ }
+
+ {
+ Input yin(intermediate);
+ EndianTypes map;
+ yin >> map;
+
+ EXPECT_FALSE(yin.error());
+ EXPECT_EQ(map.u64, 6000000000ULL);
+ EXPECT_EQ(map.u32, 3000000000U);
+ EXPECT_EQ(map.u16, 50000);
+ EXPECT_EQ(map.s64, -6000000000LL);
+ EXPECT_EQ(map.s32, -2000000000L);
+ EXPECT_EQ(map.s16, -32000);
+ EXPECT_EQ(map.f, 3.25f);
+ EXPECT_EQ(map.d, -2.8625);
+ }
+}
+
struct StringTypes {
llvm::StringRef str1;
llvm::StringRef str2;
diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp
index 41ad649699caa..3f12a53fd9c59 100644
--- a/unittests/Support/YAMLParserTest.cpp
+++ b/unittests/Support/YAMLParserTest.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/MemoryBuffer.h"
diff --git a/unittests/Support/raw_ostream_test.cpp b/unittests/Support/raw_ostream_test.cpp
index ff986025b2ccb..ed6ddabe46348 100644
--- a/unittests/Support/raw_ostream_test.cpp
+++ b/unittests/Support/raw_ostream_test.cpp
@@ -70,8 +70,8 @@ TEST(raw_ostreamTest, Types_Buffered) {
// void*
EXPECT_EQ("0x0", printToString((void*) nullptr));
- EXPECT_EQ("0xbeef", printToString((void*) 0xbeef));
- EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeef));
+ EXPECT_EQ("0xbeef", printToString((void*) 0xbeefLL));
+ EXPECT_EQ("0xdeadbeef", printToString((void*) 0xdeadbeefLL));
// Min and max.
EXPECT_EQ("18446744073709551615", printToString(UINT64_MAX));
@@ -101,8 +101,8 @@ TEST(raw_ostreamTest, Types_Unbuffered) {
// void*
EXPECT_EQ("0x0", printToStringUnbuffered((void*) nullptr));
- EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeef));
- EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeef));
+ EXPECT_EQ("0xbeef", printToStringUnbuffered((void*) 0xbeefLL));
+ EXPECT_EQ("0xdeadbeef", printToStringUnbuffered((void*) 0xdeadbeefLL));
// Min and max.
EXPECT_EQ("18446744073709551615", printToStringUnbuffered(UINT64_MAX));
diff --git a/unittests/Support/raw_sha1_ostream_test.cpp b/unittests/Support/raw_sha1_ostream_test.cpp
new file mode 100644
index 0000000000000..db2a3e9ab643e
--- /dev/null
+++ b/unittests/Support/raw_sha1_ostream_test.cpp
@@ -0,0 +1,71 @@
+//===- 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/Support/Format.h"
+#include "llvm/Support/raw_sha1_ostream.h"
+
+#include <string>
+
+using namespace llvm;
+
+static std::string toHex(StringRef Input) {
+ static const char *const LUT = "0123456789ABCDEF";
+ size_t Length = Input.size();
+
+ std::string Output;
+ Output.reserve(2 * Length);
+ for (size_t i = 0; i < Length; ++i) {
+ const unsigned char c = Input[i];
+ Output.push_back(LUT[c >> 4]);
+ Output.push_back(LUT[c & 15]);
+ }
+ return Output;
+}
+
+TEST(raw_sha1_ostreamTest, Basic) {
+ llvm::raw_sha1_ostream Sha1Stream;
+ Sha1Stream << "Hello World!";
+ auto Hash = toHex(Sha1Stream.sha1());
+
+ ASSERT_EQ("2EF7BDE608CE5404E97D5F042F95F89F1C232871", Hash);
+}
+
+// Check that getting the intermediate hash in the middle of the stream does
+// not invalidate the final result.
+TEST(raw_sha1_ostreamTest, Intermediate) {
+ llvm::raw_sha1_ostream Sha1Stream;
+ Sha1Stream << "Hello";
+ auto Hash = toHex(Sha1Stream.sha1());
+
+ ASSERT_EQ("F7FF9E8B7BB2E09B70935A5D785E0CC5D9D0ABF0", Hash);
+ Sha1Stream << " World!";
+ Hash = toHex(Sha1Stream.sha1());
+
+ // Compute the non-split hash separately as a reference.
+ llvm::raw_sha1_ostream NonSplitSha1Stream;
+ NonSplitSha1Stream << "Hello World!";
+ auto NonSplitHash = toHex(NonSplitSha1Stream.sha1());
+
+ ASSERT_EQ(NonSplitHash, Hash);
+}
+
+TEST(raw_sha1_ostreamTest, Reset) {
+ llvm::raw_sha1_ostream Sha1Stream;
+ Sha1Stream << "Hello";
+ auto Hash = toHex(Sha1Stream.sha1());
+
+ ASSERT_EQ("F7FF9E8B7BB2E09B70935A5D785E0CC5D9D0ABF0", Hash);
+
+ Sha1Stream.resetHash();
+ Sha1Stream << " World!";
+ Hash = toHex(Sha1Stream.sha1());
+
+ ASSERT_EQ("7447F2A5A42185C8CF91E632789C431830B59067", Hash);
+}