diff options
Diffstat (limited to 'unittests/Support')
27 files changed, 1225 insertions, 434 deletions
| diff --git a/unittests/Support/ARMAttributeParser.cpp b/unittests/Support/ARMAttributeParser.cpp index 1df03db6d07f..994011872b96 100644 --- a/unittests/Support/ARMAttributeParser.cpp +++ b/unittests/Support/ARMAttributeParser.cpp @@ -1,6 +1,5 @@  #include "llvm/Support/ARMAttributeParser.h"  #include "llvm/Support/ARMBuildAttributes.h" -#include "llvm/Support/LEB128.h"  #include "gtest/gtest.h"  #include <string> diff --git a/unittests/Support/BinaryStreamTest.cpp b/unittests/Support/BinaryStreamTest.cpp index e257583e4b12..35a010e73c7b 100644 --- a/unittests/Support/BinaryStreamTest.cpp +++ b/unittests/Support/BinaryStreamTest.cpp @@ -17,8 +17,6 @@  #include "gtest/gtest.h" -#include <unordered_map> -#include <utility>  using namespace llvm;  using namespace llvm::support; @@ -36,7 +34,7 @@ public:    Error readBytes(uint32_t Offset, uint32_t Size,                    ArrayRef<uint8_t> &Buffer) override { -    if (auto EC = checkOffset(Offset, Size)) +    if (auto EC = checkOffsetForRead(Offset, Size))        return EC;      uint32_t S = startIndex(Offset);      auto Ref = Data.drop_front(S); @@ -55,7 +53,7 @@ public:    Error readLongestContiguousChunk(uint32_t Offset,                                     ArrayRef<uint8_t> &Buffer) override { -    if (auto EC = checkOffset(Offset, 1)) +    if (auto EC = checkOffsetForRead(Offset, 1))        return EC;      uint32_t S = startIndex(Offset);      Buffer = Data.drop_front(S); @@ -65,7 +63,7 @@ public:    uint32_t getLength() override { return Data.size(); }    Error writeBytes(uint32_t Offset, ArrayRef<uint8_t> SrcData) override { -    if (auto EC = checkOffset(Offset, SrcData.size())) +    if (auto EC = checkOffsetForWrite(Offset, SrcData.size()))        return EC;      if (SrcData.empty())        return Error::success(); @@ -267,6 +265,56 @@ TEST_F(BinaryStreamTest, StreamRefBounds) {    }  } +TEST_F(BinaryStreamTest, StreamRefDynamicSize) { +  StringRef Strings[] = {"1", "2", "3", "4"}; +  AppendingBinaryByteStream Stream(support::little); + +  BinaryStreamWriter Writer(Stream); +  BinaryStreamReader Reader(Stream); +  const uint8_t *Byte; +  StringRef Str; + +  // When the stream is empty, it should report a 0 length and we should get an +  // error trying to read even 1 byte from it. +  BinaryStreamRef ConstRef(Stream); +  EXPECT_EQ(0U, ConstRef.getLength()); +  EXPECT_THAT_ERROR(Reader.readObject(Byte), Failed()); + +  // But if we write to it, its size should increase and we should be able to +  // read not just a byte, but the string that was written. +  EXPECT_THAT_ERROR(Writer.writeCString(Strings[0]), Succeeded()); +  EXPECT_EQ(2U, ConstRef.getLength()); +  EXPECT_THAT_ERROR(Reader.readObject(Byte), Succeeded()); + +  Reader.setOffset(0); +  EXPECT_THAT_ERROR(Reader.readCString(Str), Succeeded()); +  EXPECT_EQ(Str, Strings[0]); + +  // If we drop some bytes from the front, we should still track the length as +  // the +  // underlying stream grows. +  BinaryStreamRef Dropped = ConstRef.drop_front(1); +  EXPECT_EQ(1U, Dropped.getLength()); + +  EXPECT_THAT_ERROR(Writer.writeCString(Strings[1]), Succeeded()); +  EXPECT_EQ(4U, ConstRef.getLength()); +  EXPECT_EQ(3U, Dropped.getLength()); + +  // If we drop zero bytes from the back, we should continue tracking the +  // length. +  Dropped = Dropped.drop_back(0); +  EXPECT_THAT_ERROR(Writer.writeCString(Strings[2]), Succeeded()); +  EXPECT_EQ(6U, ConstRef.getLength()); +  EXPECT_EQ(5U, Dropped.getLength()); + +  // If we drop non-zero bytes from the back, we should stop tracking the +  // length. +  Dropped = Dropped.drop_back(1); +  EXPECT_THAT_ERROR(Writer.writeCString(Strings[3]), Succeeded()); +  EXPECT_EQ(8U, ConstRef.getLength()); +  EXPECT_EQ(4U, Dropped.getLength()); +} +  TEST_F(BinaryStreamTest, DropOperations) {    std::vector<uint8_t> InputData = {1, 2, 3, 4, 5, 4, 3, 2, 1};    auto RefData = makeArrayRef(InputData); @@ -314,7 +362,6 @@ TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {    // For every combination of input stream and output stream.    for (auto &Stream : Streams) { -    MutableArrayRef<uint8_t> Buffer;      ASSERT_EQ(InputData.size(), Stream.Input->getLength());      // 1. Try two reads that are supposed to work.  One from offset 0, and one @@ -346,6 +393,25 @@ TEST_F(BinaryStreamTest, MutableBinaryByteStreamBounds) {    }  } +TEST_F(BinaryStreamTest, AppendingStream) { +  AppendingBinaryByteStream Stream(llvm::support::little); +  EXPECT_EQ(0U, Stream.getLength()); + +  std::vector<uint8_t> InputData = {'T', 'e', 's', 't', 'T', 'e', 's', 't'}; +  auto Test = makeArrayRef(InputData).take_front(4); +  // Writing past the end of the stream is an error. +  EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Failed()); + +  // Writing exactly at the end of the stream is ok. +  EXPECT_THAT_ERROR(Stream.writeBytes(0, Test), Succeeded()); +  EXPECT_EQ(Test, Stream.data()); + +  // And now that the end of the stream is where we couldn't write before, now +  // we can write. +  EXPECT_THAT_ERROR(Stream.writeBytes(4, Test), Succeeded()); +  EXPECT_EQ(MutableArrayRef<uint8_t>(InputData), Stream.data()); +} +  // Test that FixedStreamArray works correctly.  TEST_F(BinaryStreamTest, FixedStreamArray) {    std::vector<uint32_t> Ints = {90823, 12908, 109823, 209823}; @@ -355,7 +421,6 @@ TEST_F(BinaryStreamTest, FixedStreamArray) {    initializeInput(IntBytes, alignof(uint32_t));    for (auto &Stream : Streams) { -    MutableArrayRef<uint8_t> Buffer;      ASSERT_EQ(InputData.size(), Stream.Input->getLength());      FixedStreamArray<uint32_t> Array(*Stream.Input); @@ -535,7 +600,6 @@ TEST_F(BinaryStreamTest, StreamReaderEnum) {      BinaryStreamReader Reader(*Stream.Input); -    ArrayRef<MyEnum> Array;      FixedStreamArray<MyEnum> FSA;      for (size_t I = 0; I < Enums.size(); ++I) { @@ -696,6 +760,23 @@ TEST_F(BinaryStreamTest, StringWriterStrings) {      EXPECT_EQ(makeArrayRef(Strings), makeArrayRef(InStrings));    }  } + +TEST_F(BinaryStreamTest, StreamWriterAppend) { +  StringRef Strings[] = {"First", "Second", "Third", "Fourth"}; +  AppendingBinaryByteStream Stream(support::little); +  BinaryStreamWriter Writer(Stream); + +  for (auto &Str : Strings) { +    EXPECT_THAT_ERROR(Writer.writeCString(Str), Succeeded()); +  } + +  BinaryStreamReader Reader(Stream); +  for (auto &Str : Strings) { +    StringRef S; +    EXPECT_THAT_ERROR(Reader.readCString(S), Succeeded()); +    EXPECT_EQ(Str, S); +  } +}  }  namespace { diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index 641163e39ed3..299106e0dbf7 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -42,6 +42,7 @@ add_llvm_unittest(SupportTests    ProcessTest.cpp    ProgramTest.cpp    RegexTest.cpp +  ReverseIterationTest.cpp    ReplaceFileTest.cpp    ScaledNumberTest.cpp    SourceMgrTest.cpp @@ -67,12 +68,14 @@ add_llvm_unittest(SupportTests    xxhashTest.cpp    ) +target_link_libraries(SupportTests PRIVATE LLVMTestingSupport) +  # Disable all warning for AlignOfTest.cpp,  # as it does things intentionally, and there is no reliable way of  # disabling all warnings for all the compilers by using pragmas.  set_source_files_properties(AlignOfTest.cpp PROPERTIES COMPILE_FLAGS -w)  # ManagedStatic.cpp uses <pthread>. -target_link_libraries(SupportTests LLVMTestingSupport ${LLVM_PTHREAD_LIB}) +target_link_libraries(SupportTests PRIVATE LLVMTestingSupport ${LLVM_PTHREAD_LIB})  add_subdirectory(DynamicLibrary) diff --git a/unittests/Support/Chrono.cpp b/unittests/Support/Chrono.cpp index 1410baf848bb..a6b76c81a9c0 100644 --- a/unittests/Support/Chrono.cpp +++ b/unittests/Support/Chrono.cpp @@ -31,33 +31,35 @@ TEST(Chrono, TimeTConversion) {    EXPECT_EQ(TP, toTimePoint(toTimeT(TP)));  } -TEST(Chrono, StringConversion) { +TEST(Chrono, TimePointFormat) { +  using namespace std::chrono; +  struct tm TM {}; +  TM.tm_year = 106; +  TM.tm_mon = 0; +  TM.tm_mday = 2; +  TM.tm_hour = 15; +  TM.tm_min = 4; +  TM.tm_sec = 5; +  TM.tm_isdst = -1; +  TimePoint<> T = +      system_clock::from_time_t(mktime(&TM)) + nanoseconds(123456789); + +  // operator<< uses the format YYYY-MM-DD HH:MM:SS.NNNNNNNNN    std::string S;    raw_string_ostream OS(S); -  OS << system_clock::now(); - -  // Do a basic sanity check on the output. -  // The format we expect is YYYY-MM-DD HH:MM:SS.MMMUUUNNN -  StringRef Date, Time; -  std::tie(Date, Time) = StringRef(OS.str()).split(' '); - -  SmallVector<StringRef, 3> Components; -  Date.split(Components, '-'); -  ASSERT_EQ(3u, Components.size()); -  EXPECT_EQ(4u, Components[0].size()); -  EXPECT_EQ(2u, Components[1].size()); -  EXPECT_EQ(2u, Components[2].size()); - -  StringRef Sec, Nano; -  std::tie(Sec, Nano) = Time.split('.'); - -  Components.clear(); -  Sec.split(Components, ':'); -  ASSERT_EQ(3u, Components.size()); -  EXPECT_EQ(2u, Components[0].size()); -  EXPECT_EQ(2u, Components[1].size()); -  EXPECT_EQ(2u, Components[2].size()); -  EXPECT_EQ(9u, Nano.size()); +  OS << T; +  EXPECT_EQ("2006-01-02 15:04:05.123456789", OS.str()); + +  // formatv default style matches operator<<. +  EXPECT_EQ("2006-01-02 15:04:05.123456789", formatv("{0}", T).str()); +  // formatv supports strftime-style format strings. +  EXPECT_EQ("15:04:05", formatv("{0:%H:%M:%S}", T).str()); +  // formatv supports our strftime extensions for sub-second precision. +  EXPECT_EQ("123", formatv("{0:%L}", T).str()); +  EXPECT_EQ("123456", formatv("{0:%f}", T).str()); +  EXPECT_EQ("123456789", formatv("{0:%N}", T).str()); +  // our extensions don't interfere with %% escaping. +  EXPECT_EQ("%foo", formatv("{0:%%foo}", T).str());  }  // Test that toTimePoint and toTimeT can be called with a arguments with varying diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index 660df11446ac..1fb0213b4d18 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -613,4 +613,39 @@ TEST(CommandLineTest, ResponseFiles) {    llvm::sys::fs::remove(TestDir);  } +TEST(CommandLineTest, SetDefautValue) { +  cl::ResetCommandLineParser(); + +  StackOption<std::string> Opt1("opt1", cl::init("true")); +  StackOption<bool> Opt2("opt2", cl::init(true)); +  cl::alias Alias("alias", llvm::cl::aliasopt(Opt2)); +  StackOption<int> Opt3("opt3", cl::init(3)); + +  const char *args[] = {"prog", "-opt1=false", "-opt2", "-opt3"}; + +  EXPECT_TRUE( +    cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls())); + +  EXPECT_TRUE(Opt1 == "false"); +  EXPECT_TRUE(Opt2); +  EXPECT_TRUE(Opt3 == 3); + +  Opt2 = false; +  Opt3 = 1; + +  cl::ResetAllOptionOccurrences(); + +  for (auto &OM : cl::getRegisteredOptions(*cl::TopLevelSubCommand)) { +    cl::Option *O = OM.second; +    if (O->ArgStr == "opt2") { +      continue; +    } +    O->setDefault(); +  } + +  EXPECT_TRUE(Opt1 == "true"); +  EXPECT_TRUE(Opt2); +  EXPECT_TRUE(Opt3 == 3); +} +  }  // anonymous namespace diff --git a/unittests/Support/ConvertUTFTest.cpp b/unittests/Support/ConvertUTFTest.cpp index 0af09e98a217..dd6e0df3688f 100644 --- a/unittests/Support/ConvertUTFTest.cpp +++ b/unittests/Support/ConvertUTFTest.cpp @@ -9,10 +9,8 @@  #include "llvm/Support/ConvertUTF.h"  #include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/Format.h"  #include "gtest/gtest.h"  #include <string> -#include <utility>  #include <vector>  using namespace llvm; diff --git a/unittests/Support/DynamicLibrary/CMakeLists.txt b/unittests/Support/DynamicLibrary/CMakeLists.txt index b5844381362e..4f060e4020d1 100644 --- a/unittests/Support/DynamicLibrary/CMakeLists.txt +++ b/unittests/Support/DynamicLibrary/CMakeLists.txt @@ -1,13 +1,15 @@  set(LLVM_LINK_COMPONENTS Support)  add_library(DynamicLibraryLib STATIC ExportedFuncs.cxx) +set_target_properties(DynamicLibraryLib PROPERTIES FOLDER "Tests")  add_llvm_unittest(DynamicLibraryTests DynamicLibraryTest.cpp) -target_link_libraries(DynamicLibraryTests DynamicLibraryLib) +target_link_libraries(DynamicLibraryTests PRIVATE DynamicLibraryLib)  export_executable_symbols(DynamicLibraryTests)  function(dynlib_add_module NAME)    add_library(${NAME} SHARED PipSqueak.cxx) +  set_target_properties(${NAME} PROPERTIES FOLDER "Tests")    set_output_directory(${NAME}      BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR} @@ -22,5 +24,12 @@ function(dynlib_add_module NAME)    add_dependencies(DynamicLibraryTests ${NAME})  endfunction(dynlib_add_module) +# Revert -Wl,-z,nodelete on this test since it relies on the file +# being unloaded. +if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") +  string(REPLACE "-Wl,-z,nodelete" "" CMAKE_SHARED_LINKER_FLAGS +    ${CMAKE_SHARED_LINKER_FLAGS}) +endif() +  dynlib_add_module(PipSqueak)  dynlib_add_module(SecondLib) diff --git a/unittests/Support/ErrorTest.cpp b/unittests/Support/ErrorTest.cpp index a762cf023f9c..2629e640f79c 100644 --- a/unittests/Support/ErrorTest.cpp +++ b/unittests/Support/ErrorTest.cpp @@ -12,6 +12,8 @@  #include "llvm/ADT/Twine.h"  #include "llvm/Support/Errc.h"  #include "llvm/Support/ErrorHandling.h" +#include "llvm/Testing/Support/Error.h" +#include "gtest/gtest-spi.h"  #include "gtest/gtest.h"  #include <memory> @@ -386,7 +388,8 @@ TEST(Error, FailureToHandle) {      });    }; -  EXPECT_DEATH(FailToHandle(), "Program aborted due to an unhandled Error:") +  EXPECT_DEATH(FailToHandle(), +               "Failure value returned from cantFail wrapped call")        << "Unhandled Error in handleAllErrors call did not cause an "           "abort()";  } @@ -405,7 +408,7 @@ TEST(Error, FailureFromHandler) {    };    EXPECT_DEATH(ReturnErrorFromHandler(), -               "Program aborted due to an unhandled Error:") +               "Failure value returned from cantFail wrapped call")        << " Error returned from handler in handleAllErrors call did not "           "cause abort()";  } @@ -482,11 +485,12 @@ TEST(Error, CantFailSuccess) {  }  // Test that cantFail results in a crash if you pass it a failure value. -#if LLVM_ENABLE_ABI_BREAKING_CHECKS +#if LLVM_ENABLE_ABI_BREAKING_CHECKS && !defined(NDEBUG)  TEST(Error, CantFailDeath) {    EXPECT_DEATH( -      cantFail(make_error<StringError>("foo", inconvertibleErrorCode())), -      "Failure value returned from cantFail wrapped call") +      cantFail(make_error<StringError>("foo", inconvertibleErrorCode()), +               "Cantfail call failed"), +      "Cantfail call failed")      << "cantFail(Error) did not cause an abort for failure value";    EXPECT_DEATH( @@ -604,6 +608,59 @@ TEST(Error, ExpectedCovariance) {    (void)!!A2;  } +// Test that handleExpected just returns success values. +TEST(Error, HandleExpectedSuccess) { +  auto ValOrErr = +    handleExpected(Expected<int>(42), +                   []() { return Expected<int>(43); }); +  EXPECT_TRUE(!!ValOrErr) +    << "handleExpected should have returned a success value here"; +  EXPECT_EQ(*ValOrErr, 42) +    << "handleExpected should have returned the original success value here"; +} + +enum FooStrategy { Aggressive, Conservative }; + +static Expected<int> foo(FooStrategy S) { +  if (S == Aggressive) +    return make_error<CustomError>(7); +  return 42; +} + +// Test that handleExpected invokes the error path if errors are not handled. +TEST(Error, HandleExpectedUnhandledError) { +  // foo(Aggressive) should return a CustomError which should pass through as +  // there is no handler for CustomError. +  auto ValOrErr = +    handleExpected( +      foo(Aggressive), +      []() { return foo(Conservative); }); + +  EXPECT_FALSE(!!ValOrErr) +    << "handleExpected should have returned an error here"; +  auto Err = ValOrErr.takeError(); +  EXPECT_TRUE(Err.isA<CustomError>()) +    << "handleExpected should have returned the CustomError generated by " +    "foo(Aggressive) here"; +  consumeError(std::move(Err)); +} + +// Test that handleExpected invokes the fallback path if errors are handled. +TEST(Error, HandleExpectedHandledError) { +  // foo(Aggressive) should return a CustomError which should handle triggering +  // the fallback path. +  auto ValOrErr = +    handleExpected( +      foo(Aggressive), +      []() { return foo(Conservative); }, +      [](const CustomError&) { /* do nothing */ }); + +  EXPECT_TRUE(!!ValOrErr) +    << "handleExpected should have returned a success value here"; +  EXPECT_EQ(*ValOrErr, 42) +    << "handleExpected returned the wrong success value"; +} +  TEST(Error, ErrorCodeConversions) {    // Round-trip a success value to check that it converts correctly.    EXPECT_EQ(errorToErrorCode(errorCodeToError(std::error_code())), @@ -659,4 +716,53 @@ TEST(Error, ErrorMessage) {              0);  } +TEST(Error, ErrorMatchers) { +  EXPECT_THAT_ERROR(Error::success(), Succeeded()); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_ERROR(make_error<CustomError>(0), Succeeded()), +      "Expected: succeeded\n  Actual: failed  (CustomError { 0})"); + +  EXPECT_THAT_ERROR(make_error<CustomError>(0), Failed()); +  EXPECT_NONFATAL_FAILURE(EXPECT_THAT_ERROR(Error::success(), Failed()), +                          "Expected: failed\n  Actual: succeeded"); + +  EXPECT_THAT_EXPECTED(Expected<int>(0), Succeeded()); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), +                           Succeeded()), +      "Expected: succeeded\n  Actual: failed  (CustomError { 0})"); + +  EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), Failed()); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(0), Failed()), +      "Expected: failed\n  Actual: succeeded with value 0"); + +  EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(0)); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), +                           HasValue(0)), +      "Expected: succeeded with value (is equal to 0)\n" +      "  Actual: failed  (CustomError { 0})"); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(0)), +      "Expected: succeeded with value (is equal to 0)\n" +      "  Actual: succeeded with value 1, (isn't equal to 0)"); + +  EXPECT_THAT_EXPECTED(Expected<int &>(make_error<CustomError>(0)), Failed()); +  int a = 1; +  EXPECT_THAT_EXPECTED(Expected<int &>(a), Succeeded()); +  EXPECT_THAT_EXPECTED(Expected<int &>(a), HasValue(testing::Eq(1))); + +  EXPECT_THAT_EXPECTED(Expected<int>(1), HasValue(testing::Gt(0))); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(0), HasValue(testing::Gt(1))), +      "Expected: succeeded with value (is > 1)\n" +      "  Actual: succeeded with value 0, (isn't > 1)"); +  EXPECT_NONFATAL_FAILURE( +      EXPECT_THAT_EXPECTED(Expected<int>(make_error<CustomError>(0)), +                           HasValue(testing::Gt(1))), +      "Expected: succeeded with value (is > 1)\n" +      "  Actual: failed  (CustomError { 0})"); +} +  } // end anon namespace diff --git a/unittests/Support/FileOutputBufferTest.cpp b/unittests/Support/FileOutputBufferTest.cpp index 5f20634d66c2..e7f1fd765bde 100644 --- a/unittests/Support/FileOutputBufferTest.cpp +++ b/unittests/Support/FileOutputBufferTest.cpp @@ -40,18 +40,18 @@ TEST(FileOutputBuffer, Test) {    // TEST 1: Verify commit case.    SmallString<128> File1(TestDirectory); -	File1.append("/file1"); +  File1.append("/file1");    { -    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = +    Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =          FileOutputBuffer::create(File1, 8192); -    ASSERT_NO_ERROR(BufferOrErr.getError()); +    ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));      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()); +    ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));    }    // Verify file is correct size. @@ -64,9 +64,9 @@ TEST(FileOutputBuffer, Test) {    SmallString<128> File2(TestDirectory);    File2.append("/file2");    { -    ErrorOr<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr = +    Expected<std::unique_ptr<FileOutputBuffer>> Buffer2OrErr =          FileOutputBuffer::create(File2, 8192); -    ASSERT_NO_ERROR(Buffer2OrErr.getError()); +    ASSERT_NO_ERROR(errorToErrorCode(Buffer2OrErr.takeError()));      std::unique_ptr<FileOutputBuffer> &Buffer2 = *Buffer2OrErr;      // Fill buffer with special header.      memcpy(Buffer2->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20); @@ -79,17 +79,17 @@ TEST(FileOutputBuffer, Test) {    // TEST 3: Verify sizing down case.    SmallString<128> File3(TestDirectory); -	File3.append("/file3"); +  File3.append("/file3");    { -    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = +    Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =          FileOutputBuffer::create(File3, 8192000); -    ASSERT_NO_ERROR(BufferOrErr.getError()); +    ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));      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()); +    ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));    }    // Verify file is correct size. @@ -100,16 +100,16 @@ TEST(FileOutputBuffer, Test) {    // TEST 4: Verify file can be made executable.    SmallString<128> File4(TestDirectory); -	File4.append("/file4"); +  File4.append("/file4");    { -    ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr = +    Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =          FileOutputBuffer::create(File4, 8192, FileOutputBuffer::F_executable); -    ASSERT_NO_ERROR(BufferOrErr.getError()); +    ASSERT_NO_ERROR(errorToErrorCode(BufferOrErr.takeError()));      std::unique_ptr<FileOutputBuffer> &Buffer = *BufferOrErr;      // Start buffer with special header.      memcpy(Buffer->getBufferStart(), "AABBCCDDEEFFGGHHIIJJ", 20);      // Commit buffer. -    ASSERT_NO_ERROR(Buffer->commit()); +    ASSERT_NO_ERROR(errorToErrorCode(Buffer->commit()));    }    // Verify file exists and is executable.    fs::file_status Status; diff --git a/unittests/Support/FormatVariadicTest.cpp b/unittests/Support/FormatVariadicTest.cpp index bfbe556b31a7..ddecffdeed1d 100644 --- a/unittests/Support/FormatVariadicTest.cpp +++ b/unittests/Support/FormatVariadicTest.cpp @@ -578,3 +578,34 @@ TEST(FormatVariadicTest, FormatAdapter) {    // const Format cvar(1);    // EXPECT_EQ("Format", formatv("{0}", cvar).str());  } + +TEST(FormatVariadicTest, FormatFormatvObject) { +  EXPECT_EQ("Format", formatv("F{0}t", formatv("o{0}a", "rm")).str()); +  EXPECT_EQ("[   ! ]", formatv("[{0,+5}]", formatv("{0,-2}", "!")).str()); +} + +namespace { +struct Recorder { +  int Copied = 0, Moved = 0; +  Recorder() = default; +  Recorder(const Recorder &Copy) : Copied(1 + Copy.Copied), Moved(Copy.Moved) {} +  Recorder(const Recorder &&Move) +      : Copied(Move.Copied), Moved(1 + Move.Moved) {} +}; +} // namespace +namespace llvm { +template <> struct format_provider<Recorder> { +  static void format(const Recorder &R, raw_ostream &OS, StringRef style) { +    OS << R.Copied << "C " << R.Moved << "M"; +  } +}; +} // namespace + +TEST(FormatVariadicTest, CopiesAndMoves) { +  Recorder R; +  EXPECT_EQ("0C 0M", formatv("{0}", R).str()); +  EXPECT_EQ("0C 3M", formatv("{0}", std::move(R)).str()); +  EXPECT_EQ("0C 3M", formatv("{0}", Recorder()).str()); +  EXPECT_EQ(0, R.Copied); +  EXPECT_EQ(0, R.Moved); +} diff --git a/unittests/Support/GlobPatternTest.cpp b/unittests/Support/GlobPatternTest.cpp index 44d77266db1f..d7016ab218d3 100644 --- a/unittests/Support/GlobPatternTest.cpp +++ b/unittests/Support/GlobPatternTest.cpp @@ -67,4 +67,13 @@ TEST_F(GlobPatternTest, Invalid) {    EXPECT_FALSE((bool)Pat1);    handleAllErrors(Pat1.takeError(), [&](ErrorInfoBase &EIB) {});  } + +TEST_F(GlobPatternTest, ExtSym) { +  Expected<GlobPattern> Pat1 = GlobPattern::create("a*\xFF"); +  EXPECT_TRUE((bool)Pat1); +  EXPECT_TRUE(Pat1->match("axxx\xFF")); +  Expected<GlobPattern> Pat2 = GlobPattern::create("[\xFF-\xFF]"); +  EXPECT_TRUE((bool)Pat2); +  EXPECT_TRUE(Pat2->match("\xFF")); +}  } diff --git a/unittests/Support/Host.cpp b/unittests/Support/Host.cpp index 7c018ac50423..736b04c2049c 100644 --- a/unittests/Support/Host.cpp +++ b/unittests/Support/Host.cpp @@ -106,8 +106,17 @@ TEST(getLinuxHostCPUName, AArch64) {                                                "CPU part        : 0x201"),              "kryo");    EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" +                                              "CPU part        : 0x800"), +            "cortex-a73"); +  EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" +                                              "CPU part        : 0x801"), +            "cortex-a73"); +  EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n"                                                "CPU part        : 0xc00"),              "falkor"); +  EXPECT_EQ(sys::detail::getHostCPUNameForARM("CPU implementer : 0x51\n" +                                              "CPU part        : 0xc01"), +            "saphira");    // MSM8992/4 weirdness    StringRef MSM8992ProcCpuInfo = R"( @@ -130,6 +139,37 @@ Hardware        : Qualcomm Technologies, Inc MSM8992    EXPECT_EQ(sys::detail::getHostCPUNameForARM(MSM8992ProcCpuInfo),              "cortex-a53"); + +  // Exynos big.LITTLE weirdness +  const std::string ExynosProcCpuInfo = R"( +processor       : 0 +Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x41 +CPU architecture: 8 +CPU variant     : 0x0 +CPU part        : 0xd03 + +processor       : 1 +Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 +CPU implementer : 0x53 +CPU architecture: 8 +)"; + +  // Verify default for Exynos. +  EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + +                                              "CPU variant     : 0xc\n" +                                              "CPU part        : 0xafe"), +            "exynos-m1"); +  // Verify Exynos M1. +  EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + +                                              "CPU variant     : 0x1\n" +                                              "CPU part        : 0x001"), +            "exynos-m1"); +  // Verify Exynos M2. +  EXPECT_EQ(sys::detail::getHostCPUNameForARM(ExynosProcCpuInfo + +                                              "CPU variant     : 0x4\n" +                                              "CPU part        : 0x001"), +            "exynos-m2");  }  #if defined(__APPLE__) @@ -147,8 +187,9 @@ TEST_F(HostTest, getMacOSHostVersion) {    const char *SwVersPath = "/usr/bin/sw_vers";    const char *argv[] = {SwVersPath, "-productVersion", nullptr};    StringRef OutputPath = OutputFile.str(); -  const StringRef *Redirects[] = {/*STDIN=*/nullptr, /*STDOUT=*/&OutputPath, -                                  /*STDERR=*/nullptr}; +  const Optional<StringRef> Redirects[] = {/*STDIN=*/None, +                                           /*STDOUT=*/OutputPath, +                                           /*STDERR=*/None};    int RetCode = ExecuteAndWait(SwVersPath, argv, /*env=*/nullptr, Redirects);    ASSERT_EQ(0, RetCode); diff --git a/unittests/Support/LEB128Test.cpp b/unittests/Support/LEB128Test.cpp index 09db6dfdc593..1c9b5dbd2bd9 100644 --- a/unittests/Support/LEB128Test.cpp +++ b/unittests/Support/LEB128Test.cpp @@ -46,16 +46,17 @@ TEST(LEB128Test, EncodeSLEB128) {    EXPECT_SLEB128_EQ("\xc0\x00", 64, 0);    // Encode SLEB128 with some extra padding bytes -  EXPECT_SLEB128_EQ("\x80\x00", 0, 1); -  EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 2); -  EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 1); -  EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 2); -  EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 1); -  EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 2); -  EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 1); -  EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 2); -  EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 1); -  EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 2); +  EXPECT_SLEB128_EQ("\x80\x00", 0, 2); +  EXPECT_SLEB128_EQ("\x80\x80\x00", 0, 3); +  EXPECT_SLEB128_EQ("\xff\x80\x00", 0x7f, 3); +  EXPECT_SLEB128_EQ("\xff\x80\x80\x00", 0x7f, 4); +  EXPECT_SLEB128_EQ("\x80\x81\x00", 0x80, 3); +  EXPECT_SLEB128_EQ("\x80\x81\x80\x00", 0x80, 4); +  EXPECT_SLEB128_EQ("\xc0\x7f", -0x40, 2); + +  EXPECT_SLEB128_EQ("\xc0\xff\x7f", -0x40, 3); +  EXPECT_SLEB128_EQ("\x80\xff\x7f", -0x80, 3); +  EXPECT_SLEB128_EQ("\x80\xff\xff\x7f", -0x80, 4);  #undef EXPECT_SLEB128_EQ  } @@ -93,12 +94,12 @@ TEST(LEB128Test, EncodeULEB128) {    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); +  EXPECT_ULEB128_EQ("\x80\x00", 0, 2); +  EXPECT_ULEB128_EQ("\x80\x80\x00", 0, 3); +  EXPECT_ULEB128_EQ("\xff\x00", 0x7f, 2); +  EXPECT_ULEB128_EQ("\xff\x80\x00", 0x7f, 3); +  EXPECT_ULEB128_EQ("\x80\x81\x00", 0x80, 3); +  EXPECT_ULEB128_EQ("\x80\x81\x80\x00", 0x80, 4);  #undef EXPECT_ULEB128_EQ  } diff --git a/unittests/Support/ManagedStatic.cpp b/unittests/Support/ManagedStatic.cpp index 4e2e93036a83..07e324cdfb65 100644 --- a/unittests/Support/ManagedStatic.cpp +++ b/unittests/Support/ManagedStatic.cpp @@ -8,7 +8,6 @@  //===----------------------------------------------------------------------===//  #include "llvm/Support/ManagedStatic.h"  #include "llvm/Config/config.h" -#include "llvm/Support/Threading.h"  #ifdef HAVE_PTHREAD_H  #include <pthread.h>  #endif diff --git a/unittests/Support/MemoryTest.cpp b/unittests/Support/MemoryTest.cpp index 140219ffd1d6..650be7b6f1dd 100644 --- a/unittests/Support/MemoryTest.cpp +++ b/unittests/Support/MemoryTest.cpp @@ -1,6 +1,6 @@  //===- llvm/unittest/Support/AllocatorTest.cpp - BumpPtrAllocator tests ---===//  // -//		       The LLVM Compiler Infrastructure +//                     The LLVM Compiler Infrastructure  //  // This file is distributed under the University of Illinois Open Source  // License. See LICENSE.TXT for details. @@ -350,16 +350,16 @@ TEST_P(MappedMemoryTest, UnalignedNear) {  // 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 -			 }; +                           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),); +                        MappedMemoryTest, +                        ::testing::ValuesIn(MemoryFlags),);  }  // anonymous namespace diff --git a/unittests/Support/Path.cpp b/unittests/Support/Path.cpp index 3e474f33ca6d..f624626f5e53 100644 --- a/unittests/Support/Path.cpp +++ b/unittests/Support/Path.cpp @@ -564,6 +564,27 @@ TEST_F(FileSystemTest, RealPath) {    ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + "/test1"));  } +TEST_F(FileSystemTest, TempFileKeepDiscard) { +  // We can keep then discard. +  auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); +  ASSERT_TRUE((bool)TempFileOrError); +  fs::TempFile File = std::move(*TempFileOrError); +  ASSERT_FALSE((bool)File.keep(TestDirectory + "/keep")); +  ASSERT_FALSE((bool)File.discard()); +  ASSERT_TRUE(fs::exists(TestDirectory + "/keep")); +  ASSERT_NO_ERROR(fs::remove(TestDirectory + "/keep")); +} + +TEST_F(FileSystemTest, TempFileDiscardDiscard) { +  // We can discard twice. +  auto TempFileOrError = fs::TempFile::create(TestDirectory + "/test-%%%%"); +  ASSERT_TRUE((bool)TempFileOrError); +  fs::TempFile File = std::move(*TempFileOrError); +  ASSERT_FALSE((bool)File.discard()); +  ASSERT_FALSE((bool)File.discard()); +  ASSERT_FALSE(fs::exists(TestDirectory + "/keep")); +} +  TEST_F(FileSystemTest, TempFiles) {    // Create a temp file.    int FileDescriptor; @@ -699,6 +720,21 @@ TEST_F(FileSystemTest, CreateDir) {      ThisDir = path::parent_path(ThisDir);    } +  // Also verify that paths with Unix separators are handled correctly. +  std::string LongPathWithUnixSeparators(TestDirectory.str()); +  // Add at least one subdirectory to TestDirectory, and replace slashes with +  // backslashes +  do { +    LongPathWithUnixSeparators.append("/DirNameWith19Charss"); +  } while (LongPathWithUnixSeparators.size() < 260); +  std::replace(LongPathWithUnixSeparators.begin(), +               LongPathWithUnixSeparators.end(), +               '\\', '/'); +  ASSERT_NO_ERROR(fs::create_directories(Twine(LongPathWithUnixSeparators))); +  // cleanup +  ASSERT_NO_ERROR(fs::remove_directories(Twine(TestDirectory) + +                                         "/DirNameWith19Charss")); +    // 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]; @@ -854,8 +890,8 @@ TEST_F(FileSystemTest, BrokenSymlinkDirectoryIteration) {         i != e; i.increment(ec)) {      ASSERT_NO_ERROR(ec); -    fs::file_status status; -    if (i->status(status) == +    ErrorOr<fs::basic_file_status> status = i->status(); +    if (status.getError() ==          std::make_error_code(std::errc::no_such_file_or_directory)) {        i.no_push();        continue; @@ -1145,96 +1181,6 @@ TEST(Support, ReplacePathPrefix) {    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)); -  FileRemover Cleanup(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)); -  FileRemover Cleanup(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)); -  FileRemover Cleanup(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; diff --git a/unittests/Support/ProcessTest.cpp b/unittests/Support/ProcessTest.cpp index 298a0a373234..37587bf47996 100644 --- a/unittests/Support/ProcessTest.cpp +++ b/unittests/Support/ProcessTest.cpp @@ -42,10 +42,18 @@ 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, EmptyVal) { +  SetEnvironmentVariableA("__LLVM_TEST_ENVIRON_VAR__", ""); +  Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__")); +  EXPECT_TRUE(val.hasValue()); +  EXPECT_STREQ("", val->c_str()); +} +  TEST(ProcessTest, Wchar) {    SetEnvironmentVariableW(L"__LLVM_TEST_ENVIRON_VAR__", L"abcdefghijklmnopqrs");    Optional<std::string> val(Process::GetEnv("__LLVM_TEST_ENVIRON_VAR__")); diff --git a/unittests/Support/ProgramTest.cpp b/unittests/Support/ProgramTest.cpp index f658980073da..3c272bb980c5 100644 --- a/unittests/Support/ProgramTest.cpp +++ b/unittests/Support/ProgramTest.cpp @@ -145,11 +145,10 @@ TEST_F(ProgramEnvTest, CreateProcessLongPath) {    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 }; +  Optional<StringRef> Redirects[] = {None, LongPath.str(), None};    int RC = ExecuteAndWait(MyExe, ArgV, getEnviron(), Redirects,      /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &Error,      &ExecutionFailed); @@ -192,7 +191,7 @@ TEST_F(ProgramEnvTest, CreateProcessTrailingSlash) {  #else    StringRef nul("/dev/null");  #endif -  const StringRef *redirects[] = { &nul, &nul, nullptr }; +  Optional<StringRef> redirects[] = { nul, nul, None };    int rc = ExecuteAndWait(my_exe, argv, getEnviron(), redirects,                            /*secondsToWait=*/ 10, /*memoryLimit=*/ 0, &error,                            &ExecutionFailed); @@ -221,8 +220,8 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {    std::string Error;    bool ExecutionFailed; -  ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, -                                  &Error, &ExecutionFailed); +  ProcessInfo PI1 = ExecuteNoWait(Executable, argv, getEnviron(), {}, 0, &Error, +                                  &ExecutionFailed);    ASSERT_FALSE(ExecutionFailed) << Error;    ASSERT_NE(PI1.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; @@ -240,8 +239,8 @@ TEST_F(ProgramEnvTest, TestExecuteNoWait) {    EXPECT_EQ(LoopCount, 1u) << "LoopCount should be 1"; -  ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), nullptr, 0, -                                  &Error, &ExecutionFailed); +  ProcessInfo PI2 = ExecuteNoWait(Executable, argv, getEnviron(), {}, 0, &Error, +                                  &ExecutionFailed);    ASSERT_FALSE(ExecutionFailed) << Error;    ASSERT_NE(PI2.Pid, ProcessInfo::InvalidPid) << "Invalid process id"; @@ -280,7 +279,7 @@ TEST_F(ProgramEnvTest, TestExecuteAndWaitTimeout) {    std::string Error;    bool ExecutionFailed;    int RetCode = -      ExecuteAndWait(Executable, argv, getEnviron(), nullptr, /*secondsToWait=*/1, 0, +      ExecuteAndWait(Executable, argv, getEnviron(), {}, /*secondsToWait=*/1, 0,                       &Error, &ExecutionFailed);    ASSERT_EQ(-2, RetCode);  } @@ -292,8 +291,8 @@ TEST(ProgramTest, TestExecuteNegative) {    {      std::string Error;      bool ExecutionFailed; -    int RetCode = ExecuteAndWait(Executable, argv, nullptr, nullptr, 0, 0, -                                 &Error, &ExecutionFailed); +    int RetCode = ExecuteAndWait(Executable, argv, 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); @@ -303,8 +302,8 @@ TEST(ProgramTest, TestExecuteNegative) {    {      std::string Error;      bool ExecutionFailed; -    ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, nullptr, 0, -                                   &Error, &ExecutionFailed); +    ProcessInfo PI = ExecuteNoWait(Executable, argv, nullptr, {}, 0, &Error, +                                   &ExecutionFailed);      ASSERT_EQ(PI.Pid, ProcessInfo::InvalidPid)          << "On error ExecuteNoWait should return an invalid ProcessInfo";      ASSERT_TRUE(ExecutionFailed); diff --git a/unittests/Support/RegexTest.cpp b/unittests/Support/RegexTest.cpp index 5e3ce39f0057..7e44a3c0614a 100644 --- a/unittests/Support/RegexTest.cpp +++ b/unittests/Support/RegexTest.cpp @@ -171,4 +171,12 @@ TEST_F(RegexTest, MatchInvalid) {    EXPECT_FALSE(r1.match("X"));  } +// https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=3727 +TEST_F(RegexTest, OssFuzz3727Regression) { +  // Wrap in a StringRef so the NUL byte doesn't terminate the string +  Regex r(StringRef("[[[=GS\x00[=][", 10)); +  std::string Error; +  EXPECT_FALSE(r.isValid(Error)); +} +  } diff --git a/unittests/Support/ReplaceFileTest.cpp b/unittests/Support/ReplaceFileTest.cpp index 8b16daf3233c..794f36b1f654 100644 --- a/unittests/Support/ReplaceFileTest.cpp +++ b/unittests/Support/ReplaceFileTest.cpp @@ -52,6 +52,21 @@ class ScopedFD {    ~ScopedFD() { Process::SafelyCloseFileDescriptor(FD); }  }; +bool FDHasContent(int FD, StringRef Content) { +  auto Buffer = MemoryBuffer::getOpenFile(FD, "", -1); +  assert(Buffer); +  return Buffer.get()->getBuffer() == Content; +} + +bool FileHasContent(StringRef File, StringRef Content) { +  int FD = 0; +  auto EC = fs::openFileForRead(File, FD); +  (void)EC; +  assert(!EC); +  ScopedFD EventuallyCloseIt(FD); +  return FDHasContent(FD, Content); +} +  TEST(rename, FileOpenedForReadingCanBeReplaced) {    // Create unique temporary directory for this test.    SmallString<128> TestDirectory; @@ -79,25 +94,15 @@ TEST(rename, FileOpenedForReadingCanBeReplaced) {      // 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!!"); +    EXPECT_TRUE(FDHasContent(ReadFD, "!!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!!"); -  } +  // If we obtain a new descriptor for the target file, we should find that it +  // contains the content that was in the source file. +  EXPECT_TRUE(FileHasContent(TargetFileName, "!!source!!"));    // Rename the target file back to the source file name to confirm that rename    // still works if the destination does not already exist. @@ -110,4 +115,59 @@ TEST(rename, FileOpenedForReadingCanBeReplaced) {    ASSERT_NO_ERROR(fs::remove(TestDirectory.str()));  } +TEST(rename, ExistingTemp) { +  // Test that existing .tmpN files don't get deleted by the Windows +  // sys::fs::rename implementation. +  SmallString<128> TestDirectory; +  ASSERT_NO_ERROR( +      fs::createUniqueDirectory("ExistingTemp-test", TestDirectory)); + +  SmallString<128> SourceFileName(TestDirectory); +  path::append(SourceFileName, "source"); + +  SmallString<128> TargetFileName(TestDirectory); +  path::append(TargetFileName, "target"); + +  SmallString<128> TargetTmp0FileName(TestDirectory); +  path::append(TargetTmp0FileName, "target.tmp0"); + +  SmallString<128> TargetTmp1FileName(TestDirectory); +  path::append(TargetTmp1FileName, "target.tmp1"); + +  ASSERT_NO_ERROR(CreateFileWithContent(SourceFileName, "!!source!!")); +  ASSERT_NO_ERROR(CreateFileWithContent(TargetFileName, "!!target!!")); +  ASSERT_NO_ERROR(CreateFileWithContent(TargetTmp0FileName, "!!target.tmp0!!")); + +  { +    // Use mapped_file_region to make sure that the destination file is mmap'ed. +    // This will cause SetInformationByHandle to fail when renaming to the +    // destination, and we will follow the code path that tries to give target +    // a temporary name. +    int TargetFD; +    std::error_code EC; +    ASSERT_NO_ERROR(fs::openFileForRead(TargetFileName, TargetFD)); +    ScopedFD X(TargetFD); +    sys::fs::mapped_file_region MFR( +        TargetFD, sys::fs::mapped_file_region::readonly, 10, 0, EC); +    ASSERT_FALSE(EC); + +    ASSERT_NO_ERROR(fs::rename(SourceFileName, TargetFileName)); + +#ifdef _WIN32 +    // Make sure that target was temporarily renamed to target.tmp1 on Windows. +    // This is signified by a permission denied error as opposed to no such file +    // or directory when trying to open it. +    int Tmp1FD; +    EXPECT_EQ(errc::permission_denied, +              fs::openFileForRead(TargetTmp1FileName, Tmp1FD)); +#endif +  } + +  EXPECT_TRUE(FileHasContent(TargetTmp0FileName, "!!target.tmp0!!")); + +  ASSERT_NO_ERROR(fs::remove(TargetFileName)); +  ASSERT_NO_ERROR(fs::remove(TargetTmp0FileName)); +  ASSERT_NO_ERROR(fs::remove(TestDirectory.str())); +} +  }  // anonymous namespace diff --git a/unittests/Support/ReverseIterationTest.cpp b/unittests/Support/ReverseIterationTest.cpp new file mode 100644 index 000000000000..930bd43d11b2 --- /dev/null +++ b/unittests/Support/ReverseIterationTest.cpp @@ -0,0 +1,110 @@ +//===- llvm/unittest/Support/ReverseIterationTest.cpp ---------------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// +// Reverse Iteration unit tests. +// +//===---------------------------------------------------------------------===// + +#include "llvm/Support/ReverseIteration.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "gtest/gtest.h" + +using namespace llvm; + +TEST(ReverseIterationTest, DenseMapTest1) { +  static_assert(detail::IsPointerLike<int *>::value, +                "int * is pointer-like"); +  static_assert(detail::IsPointerLike<uintptr_t>::value, +                "uintptr_t is pointer-like"); +  static_assert(!detail::IsPointerLike<int>::value, +                "int is not pointer-like"); +  static_assert(detail::IsPointerLike<void *>::value, +                "void * is pointer-like"); +  struct IncompleteType; +  static_assert(detail::IsPointerLike<IncompleteType *>::value, +                "incomplete * is pointer-like"); + +  // For a DenseMap with non-pointer-like keys, forward iteration equals +  // reverse iteration. +  DenseMap<int, int> Map; +  int Keys[] = { 1, 2, 3, 4 }; + +  // Insert keys into the DenseMap. +  for (auto Key: Keys) +    Map[Key] = 0; + +  // Note: This is the observed order of keys in the DenseMap. +  // If there is any change in the behavior of the DenseMap, this order +  // would need to be adjusted accordingly. +  int IterKeys[] = { 2, 4, 1, 3 }; + +  // Check that the DenseMap is iterated in the expected order. +  for (const auto &Tuple : zip(Map, IterKeys)) +    ASSERT_EQ(std::get<0>(Tuple).first, std::get<1>(Tuple)); + +  // Check operator++ (post-increment). +  int i = 0; +  for (auto iter = Map.begin(), end = Map.end(); iter != end; iter++, ++i) +    ASSERT_EQ(iter->first, IterKeys[i]); +} + +// Define a pointer-like int. +struct PtrLikeInt { int value; }; + +namespace llvm { + +template<> struct DenseMapInfo<PtrLikeInt *> { +  static PtrLikeInt *getEmptyKey() { +    static PtrLikeInt EmptyKey; +    return &EmptyKey; +  } + +  static PtrLikeInt *getTombstoneKey() { +    static PtrLikeInt TombstoneKey; +    return &TombstoneKey; +  } + +  static int getHashValue(const PtrLikeInt *P) { +    return P->value; +  } + +  static bool isEqual(const PtrLikeInt *LHS, const PtrLikeInt *RHS) { +    return LHS == RHS; +  } +}; + +} // end namespace llvm + +TEST(ReverseIterationTest, DenseMapTest2) { +  static_assert(detail::IsPointerLike<PtrLikeInt *>::value, +                "PtrLikeInt * is pointer-like"); + +  PtrLikeInt a = {4}, b = {8}, c = {12}, d = {16}; +  PtrLikeInt *Keys[] = { &a, &b, &c, &d }; + +  // Insert keys into the DenseMap. +  DenseMap<PtrLikeInt *, int> Map; +  for (auto *Key : Keys) +    Map[Key] = Key->value; + +  // Note: If there is any change in the behavior of the DenseMap, +  // the observed order of keys would need to be adjusted accordingly. +  if (shouldReverseIterate<PtrLikeInt *>()) +    std::reverse(&Keys[0], &Keys[4]); + +  // Check that the DenseMap is iterated in the expected order. +  for (const auto &Tuple : zip(Map, Keys)) +    ASSERT_EQ(std::get<0>(Tuple).second, std::get<1>(Tuple)->value); + +  // Check operator++ (post-increment). +  int i = 0; +  for (auto iter = Map.begin(), end = Map.end(); iter != end; iter++, ++i) +    ASSERT_EQ(iter->second, Keys[i]->value); +} diff --git a/unittests/Support/SourceMgrTest.cpp b/unittests/Support/SourceMgrTest.cpp index 79c2d7278f12..2a84a89912ad 100644 --- a/unittests/Support/SourceMgrTest.cpp +++ b/unittests/Support/SourceMgrTest.cpp @@ -67,6 +67,16 @@ TEST_F(SourceMgrTest, BasicWarning) {              Output);  } +TEST_F(SourceMgrTest, BasicRemark) { +  setMainBuffer("aaa bbb\nccc ddd\n", "file.in"); +  printMessage(getLoc(4), SourceMgr::DK_Remark, "message", None, None); + +  EXPECT_EQ("file.in:1:5: remark: 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); diff --git a/unittests/Support/SpecialCaseListTest.cpp b/unittests/Support/SpecialCaseListTest.cpp index 130848845e45..060703e102fc 100644 --- a/unittests/Support/SpecialCaseListTest.cpp +++ b/unittests/Support/SpecialCaseListTest.cpp @@ -51,47 +51,102 @@ TEST_F(SpecialCaseListTest, Basic) {                            "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")); +  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")); + +  EXPECT_EQ(3u, SCL->inSectionBlame("", "src", "hello")); +  EXPECT_EQ(4u, SCL->inSectionBlame("", "src", "bye")); +  EXPECT_EQ(5u, SCL->inSectionBlame("", "src", "hi", "category")); +  EXPECT_EQ(6u, SCL->inSectionBlame("", "src", "zzzz", "category")); +  EXPECT_EQ(0u, SCL->inSectionBlame("", "src", "hi")); +  EXPECT_EQ(0u, SCL->inSectionBlame("", "fun", "hello")); +  EXPECT_EQ(0u, SCL->inSectionBlame("", "src", "hello", "category")); +} + +TEST_F(SpecialCaseListTest, CorrectErrorLineNumberWithBlankLine) { +  std::string Error; +  EXPECT_EQ(nullptr, makeSpecialCaseList("# This is a comment.\n" +                                         "\n" +                                         "[not valid\n", +                                         Error)); +  EXPECT_TRUE( +      ((StringRef)Error).startswith("malformed section header on line 3:")); + +  EXPECT_EQ(nullptr, makeSpecialCaseList("\n\n\n" +                                         "[not valid\n", +                                         Error)); +  EXPECT_TRUE( +      ((StringRef)Error).startswith("malformed section header on line 4:")); +} + +TEST_F(SpecialCaseListTest, SectionRegexErrorHandling) { +  std::string Error; +  EXPECT_EQ(makeSpecialCaseList("[address", Error), nullptr); +  EXPECT_TRUE(((StringRef)Error).startswith("malformed section header ")); + +  EXPECT_EQ(makeSpecialCaseList("[[]", Error), nullptr); +  EXPECT_TRUE(((StringRef)Error).startswith("malformed regex for section [: ")); + +  EXPECT_EQ(makeSpecialCaseList("src:=", Error), nullptr); +  EXPECT_TRUE(((StringRef)Error).endswith("Supplied regexp was blank")); +} + +TEST_F(SpecialCaseListTest, Section) { +  std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:global\n" +                                                             "[sect1|sect2]\n" +                                                             "src:test1\n" +                                                             "[sect3*]\n" +                                                             "src:test2\n"); +  EXPECT_TRUE(SCL->inSection("arbitrary", "src", "global")); +  EXPECT_TRUE(SCL->inSection("", "src", "global")); +  EXPECT_TRUE(SCL->inSection("sect1", "src", "test1")); +  EXPECT_FALSE(SCL->inSection("sect1-arbitrary", "src", "test1")); +  EXPECT_FALSE(SCL->inSection("sect", "src", "test1")); +  EXPECT_FALSE(SCL->inSection("sect1", "src", "test2")); +  EXPECT_TRUE(SCL->inSection("sect2", "src", "test1")); +  EXPECT_TRUE(SCL->inSection("sect3", "src", "test2")); +  EXPECT_TRUE(SCL->inSection("sect3-arbitrary", "src", "test2")); +  EXPECT_FALSE(SCL->inSection("", "src", "test1")); +  EXPECT_FALSE(SCL->inSection("", "src", "test2"));  }  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")); +  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")); +  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")); +  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")); +  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")); +  EXPECT_TRUE(SCL->inSection("", "fun", "tomfoolery")); +  EXPECT_TRUE(SCL->inSection("", "fun", "foobar"));  }  TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) { @@ -113,7 +168,7 @@ TEST_F(SpecialCaseListTest, InvalidSpecialCaseList) {  TEST_F(SpecialCaseListTest, EmptySpecialCaseList) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList(""); -  EXPECT_FALSE(SCL->inSection("foo", "bar")); +  EXPECT_FALSE(SCL->inSection("", "foo", "bar"));  }  TEST_F(SpecialCaseListTest, MultipleBlacklists) { @@ -124,12 +179,12 @@ TEST_F(SpecialCaseListTest, MultipleBlacklists) {    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")); +  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"));    for (auto &Path : Files)      sys::fs::remove(Path);  } @@ -137,35 +192,35 @@ TEST_F(SpecialCaseListTest, MultipleBlacklists) {  TEST_F(SpecialCaseListTest, NoTrigramsInRules) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:b.r\n"                                                               "fun:za*az\n"); -  EXPECT_TRUE(SCL->inSection("fun", "bar")); -  EXPECT_FALSE(SCL->inSection("fun", "baz")); -  EXPECT_TRUE(SCL->inSection("fun", "zakaz")); -  EXPECT_FALSE(SCL->inSection("fun", "zaraza")); +  EXPECT_TRUE(SCL->inSection("", "fun", "bar")); +  EXPECT_FALSE(SCL->inSection("", "fun", "baz")); +  EXPECT_TRUE(SCL->inSection("", "fun", "zakaz")); +  EXPECT_FALSE(SCL->inSection("", "fun", "zaraza"));  }  TEST_F(SpecialCaseListTest, NoTrigramsInARule) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*\n"                                                               "fun:za*az\n"); -  EXPECT_TRUE(SCL->inSection("fun", "abara")); -  EXPECT_FALSE(SCL->inSection("fun", "bor")); -  EXPECT_TRUE(SCL->inSection("fun", "zakaz")); -  EXPECT_FALSE(SCL->inSection("fun", "zaraza")); +  EXPECT_TRUE(SCL->inSection("", "fun", "abara")); +  EXPECT_FALSE(SCL->inSection("", "fun", "bor")); +  EXPECT_TRUE(SCL->inSection("", "fun", "zakaz")); +  EXPECT_FALSE(SCL->inSection("", "fun", "zaraza"));  }  TEST_F(SpecialCaseListTest, RepetitiveRule) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("fun:*bar*bar*bar*bar*\n"                                                               "fun:bar*\n"); -  EXPECT_TRUE(SCL->inSection("fun", "bara")); -  EXPECT_FALSE(SCL->inSection("fun", "abara")); -  EXPECT_TRUE(SCL->inSection("fun", "barbarbarbar")); -  EXPECT_TRUE(SCL->inSection("fun", "abarbarbarbar")); -  EXPECT_FALSE(SCL->inSection("fun", "abarbarbar")); +  EXPECT_TRUE(SCL->inSection("", "fun", "bara")); +  EXPECT_FALSE(SCL->inSection("", "fun", "abara")); +  EXPECT_TRUE(SCL->inSection("", "fun", "barbarbarbar")); +  EXPECT_TRUE(SCL->inSection("", "fun", "abarbarbarbar")); +  EXPECT_FALSE(SCL->inSection("", "fun", "abarbarbar"));  }  TEST_F(SpecialCaseListTest, SpecialSymbolRule) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n"); -  EXPECT_TRUE(SCL->inSection("src", "c++abi")); -  EXPECT_FALSE(SCL->inSection("src", "c\\+\\+abi")); +  EXPECT_TRUE(SCL->inSection("", "src", "c++abi")); +  EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi"));  }  TEST_F(SpecialCaseListTest, PopularTrigram) { @@ -173,20 +228,20 @@ TEST_F(SpecialCaseListTest, PopularTrigram) {                                                               "fun:*aaaaa*\n"                                                               "fun:*aaaa*\n"                                                               "fun:*aaa*\n"); -  EXPECT_TRUE(SCL->inSection("fun", "aaa")); -  EXPECT_TRUE(SCL->inSection("fun", "aaaa")); -  EXPECT_TRUE(SCL->inSection("fun", "aaaabbbaaa")); +  EXPECT_TRUE(SCL->inSection("", "fun", "aaa")); +  EXPECT_TRUE(SCL->inSection("", "fun", "aaaa")); +  EXPECT_TRUE(SCL->inSection("", "fun", "aaaabbbaaa"));  }  TEST_F(SpecialCaseListTest, EscapedSymbols) {    std::unique_ptr<SpecialCaseList> SCL = makeSpecialCaseList("src:*c\\+\\+abi*\n"                                                               "src:*hello\\\\world*\n"); -  EXPECT_TRUE(SCL->inSection("src", "dir/c++abi")); -  EXPECT_FALSE(SCL->inSection("src", "dir/c\\+\\+abi")); -  EXPECT_FALSE(SCL->inSection("src", "c\\+\\+abi")); -  EXPECT_TRUE(SCL->inSection("src", "C:\\hello\\world")); -  EXPECT_TRUE(SCL->inSection("src", "hello\\world")); -  EXPECT_FALSE(SCL->inSection("src", "hello\\\\world")); +  EXPECT_TRUE(SCL->inSection("", "src", "dir/c++abi")); +  EXPECT_FALSE(SCL->inSection("", "src", "dir/c\\+\\+abi")); +  EXPECT_FALSE(SCL->inSection("", "src", "c\\+\\+abi")); +  EXPECT_TRUE(SCL->inSection("", "src", "C:\\hello\\world")); +  EXPECT_TRUE(SCL->inSection("", "src", "hello\\world")); +  EXPECT_FALSE(SCL->inSection("", "src", "hello\\\\world"));  }  } diff --git a/unittests/Support/TarWriterTest.cpp b/unittests/Support/TarWriterTest.cpp index 927c8ed9be14..901dd906ca78 100644 --- a/unittests/Support/TarWriterTest.cpp +++ b/unittests/Support/TarWriterTest.cpp @@ -11,6 +11,7 @@  #include "llvm/Support/FileSystem.h"  #include "llvm/Support/MemoryBuffer.h"  #include "gtest/gtest.h" +#include <vector>  using namespace llvm;  namespace { @@ -37,7 +38,7 @@ struct UstarHeader {  class TarWriterTest : public ::testing::Test {}; -static UstarHeader create(StringRef Base, StringRef Filename) { +static std::vector<uint8_t> createTar(StringRef Base, StringRef Filename) {    // Create a temporary file.    SmallString<128> Path;    std::error_code EC = @@ -55,12 +56,25 @@ static UstarHeader create(StringRef Base, StringRef Filename) {    ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);    EXPECT_TRUE((bool)MBOrErr);    std::unique_ptr<MemoryBuffer> MB = std::move(*MBOrErr); +  std::vector<uint8_t> Buf((const uint8_t *)MB->getBufferStart(), +                           (const uint8_t *)MB->getBufferEnd()); + +  // Windows does not allow us to remove a mmap'ed files, so +  // unmap first and then remove the temporary file. +  MB = nullptr;    sys::fs::remove(Path); -  return *reinterpret_cast<const UstarHeader *>(MB->getBufferStart()); + +  return Buf; +} + +static UstarHeader createUstar(StringRef Base, StringRef Filename) { +  std::vector<uint8_t> Buf = createTar(Base, Filename); +  EXPECT_TRUE(Buf.size() >= sizeof(UstarHeader)); +  return *reinterpret_cast<const UstarHeader *>(Buf.data());  }  TEST_F(TarWriterTest, Basics) { -  UstarHeader Hdr = create("base", "file"); +  UstarHeader Hdr = createUstar("base", "file");    EXPECT_EQ("ustar", StringRef(Hdr.Magic));    EXPECT_EQ("00", StringRef(Hdr.Version, 2));    EXPECT_EQ("base/file", StringRef(Hdr.Name)); @@ -68,21 +82,98 @@ TEST_F(TarWriterTest, Basics) {  }  TEST_F(TarWriterTest, LongFilename) { -  UstarHeader Hdr1 = create( -      "012345678", std::string(99, 'x') + "/" + std::string(44, 'x') + "/foo"); -  EXPECT_EQ("foo", StringRef(Hdr1.Name)); -  EXPECT_EQ("012345678/" + std::string(99, 'x') + "/" + std::string(44, 'x'), -            StringRef(Hdr1.Prefix)); - -  UstarHeader Hdr2 = create( -      "012345678", std::string(99, 'x') + "/" + std::string(45, 'x') + "/foo"); -  EXPECT_EQ("foo", StringRef(Hdr2.Name)); -  EXPECT_EQ("012345678/" + std::string(99, 'x') + "/" + std::string(45, 'x'), -            StringRef(Hdr2.Prefix)); - -  UstarHeader Hdr3 = create( -      "012345678", std::string(99, 'x') + "/" + std::string(46, 'x') + "/foo"); -  EXPECT_EQ(std::string(46, 'x') + "/foo", StringRef(Hdr3.Name)); -  EXPECT_EQ("012345678/" + std::string(99, 'x'), StringRef(Hdr3.Prefix)); +  std::string x154(154, 'x'); +  std::string x155(155, 'x'); +  std::string y99(99, 'y'); +  std::string y100(100, 'y'); + +  UstarHeader Hdr1 = createUstar("", x154 + "/" + y99); +  EXPECT_EQ("/" + x154, StringRef(Hdr1.Prefix)); +  EXPECT_EQ(y99, StringRef(Hdr1.Name)); + +  UstarHeader Hdr2 = createUstar("", x155 + "/" + y99); +  EXPECT_EQ("", StringRef(Hdr2.Prefix)); +  EXPECT_EQ("", StringRef(Hdr2.Name)); + +  UstarHeader Hdr3 = createUstar("", x154 + "/" + y100); +  EXPECT_EQ("", StringRef(Hdr3.Prefix)); +  EXPECT_EQ("", StringRef(Hdr3.Name)); + +  UstarHeader Hdr4 = createUstar("", x155 + "/" + y100); +  EXPECT_EQ("", StringRef(Hdr4.Prefix)); +  EXPECT_EQ("", StringRef(Hdr4.Name)); + +  std::string yz = "yyyyyyyyyyyyyyyyyyyy/zzzzzzzzzzzzzzzzzzzz"; +  UstarHeader Hdr5 = createUstar("", x154 + "/" + yz); +  EXPECT_EQ("/" + x154, StringRef(Hdr5.Prefix)); +  EXPECT_EQ(yz, StringRef(Hdr5.Name)); +} + +TEST_F(TarWriterTest, Pax) { +  std::vector<uint8_t> Buf = createTar("", std::string(200, 'x')); +  EXPECT_TRUE(Buf.size() >= 1024); + +  auto *Hdr = reinterpret_cast<const UstarHeader *>(Buf.data()); +  EXPECT_EQ("", StringRef(Hdr->Prefix)); +  EXPECT_EQ("", StringRef(Hdr->Name)); + +  StringRef Pax = StringRef((char *)(Buf.data() + 512), 512); +  EXPECT_TRUE(Pax.startswith("211 path=/" + std::string(200, 'x'))); +} + +TEST_F(TarWriterTest, SingleFile) { +  SmallString<128> Path; +  std::error_code EC = +      sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); +  EXPECT_FALSE((bool)EC); + +  Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); +  EXPECT_TRUE((bool)TarOrErr); +  std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); +  Tar->append("FooPath", "foo"); +  Tar.reset(); + +  uint64_t TarSize; +  EC = sys::fs::file_size(Path, TarSize); +  EXPECT_FALSE((bool)EC); +  EXPECT_EQ(TarSize, 2048ULL); +} + +TEST_F(TarWriterTest, NoDuplicate) { +  SmallString<128> Path; +  std::error_code EC = +      sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); +  EXPECT_FALSE((bool)EC); + +  Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); +  EXPECT_TRUE((bool)TarOrErr); +  std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); +  Tar->append("FooPath", "foo"); +  Tar->append("BarPath", "bar"); +  Tar.reset(); + +  uint64_t TarSize; +  EC = sys::fs::file_size(Path, TarSize); +  EXPECT_FALSE((bool)EC); +  EXPECT_EQ(TarSize, 3072ULL);  } + +TEST_F(TarWriterTest, Duplicate) { +  SmallString<128> Path; +  std::error_code EC = +      sys::fs::createTemporaryFile("TarWriterTest", "tar", Path); +  EXPECT_FALSE((bool)EC); + +  Expected<std::unique_ptr<TarWriter>> TarOrErr = TarWriter::create(Path, ""); +  EXPECT_TRUE((bool)TarOrErr); +  std::unique_ptr<TarWriter> Tar = std::move(*TarOrErr); +  Tar->append("FooPath", "foo"); +  Tar->append("FooPath", "bar"); +  Tar.reset(); + +  uint64_t TarSize; +  EC = sys::fs::file_size(Path, TarSize); +  EXPECT_FALSE((bool)EC); +  EXPECT_EQ(TarSize, 2048ULL);  } +} // namespace diff --git a/unittests/Support/TargetParserTest.cpp b/unittests/Support/TargetParserTest.cpp index b9b725f934b3..dcef40345f05 100644 --- a/unittests/Support/TargetParserTest.cpp +++ b/unittests/Support/TargetParserTest.cpp @@ -25,25 +25,25 @@ const char *ARMArch[] = {      "armv7a",    "armv7ve",      "armv7hl",     "armv7l",       "armv7-r",      "armv7r",    "armv7-m",      "armv7m",      "armv7k",       "armv7s",      "armv7e-m",  "armv7em",      "armv8-a",     "armv8",        "armv8a", -    "armv8.1-a", "armv8.1a",     "armv8.2-a",   "armv8.2a",     "armv8-r", -    "armv8r",    "armv8-m.base", "armv8m.base", "armv8-m.main", "armv8m.main", -    "iwmmxt",    "iwmmxt2",      "xscale"}; +    "armv8.1-a", "armv8.1a",     "armv8.2-a",   "armv8.2a",     "armv8.3-a", +    "armv8.3a",  "armv8-r",      "armv8r",      "armv8-m.base", "armv8m.base", +    "armv8-m.main", "armv8m.main", "iwmmxt",    "iwmmxt2",      "xscale"};  bool testARMCPU(StringRef CPUName, StringRef ExpectedArch,                  StringRef ExpectedFPU, unsigned ExpectedFlags,                  StringRef CPUAttr) { -  unsigned ArchKind = ARM::parseCPUArch(CPUName); -  bool pass = ARM::getArchName(ArchKind).equals(ExpectedArch); -  unsigned FPUKind = ARM::getDefaultFPU(CPUName, ArchKind); +  ARM::ArchKind AK = ARM::parseCPUArch(CPUName); +  bool pass = ARM::getArchName(AK).equals(ExpectedArch); +  unsigned FPUKind = ARM::getDefaultFPU(CPUName, AK);    pass &= ARM::getFPUName(FPUKind).equals(ExpectedFPU); -  unsigned ExtKind = ARM::getDefaultExtensions(CPUName, ArchKind); +  unsigned ExtKind = ARM::getDefaultExtensions(CPUName, AK);    if (ExtKind > 1 && (ExtKind & ARM::AEK_NONE))      pass &= ((ExtKind ^ ARM::AEK_NONE) == ExpectedFlags);    else      pass &= (ExtKind == ExpectedFlags); -  pass &= ARM::getCPUAttr(ArchKind).equals(CPUAttr); +  pass &= ARM::getCPUAttr(AK).equals(CPUAttr);    return pass;  } @@ -218,6 +218,12 @@ TEST(TargetParserTest, testARMCPU) {                               ARM::AEK_VIRT | ARM::AEK_HWDIVARM |                               ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,                           "8-A")); +  EXPECT_TRUE(testARMCPU("cortex-a55", "armv8.2-a", "crypto-neon-fp-armv8", +                         ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | +                         ARM::AEK_VIRT | ARM::AEK_HWDIVARM | +                         ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_FP16 | +                         ARM::AEK_RAS | ARM::AEK_DOTPROD, +                         "8.2-A"));    EXPECT_TRUE(testARMCPU("cortex-a57", "armv8-a", "crypto-neon-fp-armv8",                           ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |                               ARM::AEK_VIRT | ARM::AEK_HWDIVARM | @@ -233,6 +239,12 @@ TEST(TargetParserTest, testARMCPU) {                               ARM::AEK_VIRT | ARM::AEK_HWDIVARM |                               ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP,                           "8-A")); +  EXPECT_TRUE(testARMCPU("cortex-a75", "armv8.2-a", "crypto-neon-fp-armv8", +                         ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP | +                         ARM::AEK_VIRT | ARM::AEK_HWDIVARM | +                         ARM::AEK_HWDIVTHUMB | ARM::AEK_DSP | ARM::AEK_FP16 | +                         ARM::AEK_RAS | ARM::AEK_DOTPROD, +                         "8.2-A"));    EXPECT_TRUE(testARMCPU("cyclone", "armv8-a", "crypto-neon-fp-armv8",                           ARM::AEK_CRC | ARM::AEK_SEC | ARM::AEK_MP |                               ARM::AEK_VIRT | ARM::AEK_HWDIVARM | @@ -268,11 +280,11 @@ TEST(TargetParserTest, testARMCPU) {  bool testARMArch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,                   unsigned ArchAttr) { -  unsigned ArchKind = ARM::parseArch(Arch); -  return (ArchKind != ARM::AK_INVALID) & +  ARM::ArchKind AK = ARM::parseArch(Arch); +  return (AK!= ARM::ArchKind::INVALID) &           ARM::getDefaultCPU(Arch).equals(DefaultCPU) & -         ARM::getSubArch(ArchKind).equals(SubArch) & -         (ARM::getArchAttr(ArchKind) == ArchAttr); +         ARM::getSubArch(AK).equals(SubArch) & +         (ARM::getArchAttr(AK) == ArchAttr);  }  TEST(TargetParserTest, testARMArch) { @@ -343,6 +355,9 @@ TEST(TargetParserTest, testARMArch) {        testARMArch("armv8.2-a", "generic", "v8.2a",                            ARMBuildAttrs::CPUArch::v8_A));    EXPECT_TRUE( +      testARMArch("armv8.3-a", "generic", "v8.3a", +                          ARMBuildAttrs::CPUArch::v8_A)); +  EXPECT_TRUE(        testARMArch("armv8-r", "cortex-r52", "v8r",                            ARMBuildAttrs::CPUArch::v8_R));    EXPECT_TRUE( @@ -368,94 +383,118 @@ TEST(TargetParserTest, testARMArch) {                            ARMBuildAttrs::CPUArch::v7));  } -bool testARMExtension(StringRef CPUName, unsigned ArchKind, StringRef ArchExt) { +bool testARMExtension(StringRef CPUName,ARM::ArchKind ArchKind, StringRef ArchExt) {    return ARM::getDefaultExtensions(CPUName, ArchKind) &           ARM::parseArchExt(ArchExt);  }  TEST(TargetParserTest, testARMExtension) { -  EXPECT_FALSE(testARMExtension("arm2", 0, "thumb")); -  EXPECT_FALSE(testARMExtension("arm3", 0, "thumb")); -  EXPECT_FALSE(testARMExtension("arm6", 0, "thumb")); -  EXPECT_FALSE(testARMExtension("arm7m", 0, "thumb")); -  EXPECT_FALSE(testARMExtension("strongarm", 0, "dsp")); -  EXPECT_FALSE(testARMExtension("arm7tdmi", 0, "dsp")); -  EXPECT_FALSE(testARMExtension("arm10tdmi", 0, "simd")); -  EXPECT_FALSE(testARMExtension("arm1022e", 0, "simd")); -  EXPECT_FALSE(testARMExtension("arm926ej-s", 0, "simd")); -  EXPECT_FALSE(testARMExtension("arm1136jf-s", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("arm1176j-s", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("arm1156t2-s", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("arm1176jzf-s", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("cortex-m0", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("cortex-a8", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("cortex-r4", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("cortex-m3", 0, "crypto")); -  EXPECT_FALSE(testARMExtension("cortex-a53", 0, "ras")); -  EXPECT_FALSE(testARMExtension("cortex-r52", 0, "ras")); -  EXPECT_FALSE(testARMExtension("iwmmxt", 0, "crc")); -  EXPECT_FALSE(testARMExtension("xscale", 0, "crc")); -  EXPECT_FALSE(testARMExtension("swift", 0, "crc")); - -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV2, "thumb")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV2A, "thumb")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV3, "thumb")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV3M, "thumb")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV4, "dsp")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV4T, "dsp")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV5T, "simd")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV5TE, "simd")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV5TEJ, "simd")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV6, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV6K, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV6T2, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV6KZ, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV6M, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7A, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7R, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7M, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7EM, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8A, "ras")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8_1A, "ras")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8_2A, "spe")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8R, "ras")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8MBaseline, "crc")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV8MMainline, "crc")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_IWMMXT, "crc")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_IWMMXT2, "crc")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_XSCALE, "crc")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7S, "crypto")); -  EXPECT_FALSE(testARMExtension("generic", ARM::AK_ARMV7K, "crypto")); +  EXPECT_FALSE(testARMExtension("arm2", ARM::ArchKind::INVALID, "thumb")); +  EXPECT_FALSE(testARMExtension("arm3", ARM::ArchKind::INVALID, "thumb")); +  EXPECT_FALSE(testARMExtension("arm6", ARM::ArchKind::INVALID, "thumb")); +  EXPECT_FALSE(testARMExtension("arm7m", ARM::ArchKind::INVALID, "thumb")); +  EXPECT_FALSE(testARMExtension("strongarm", ARM::ArchKind::INVALID, "dsp")); +  EXPECT_FALSE(testARMExtension("arm7tdmi", ARM::ArchKind::INVALID, "dsp")); +  EXPECT_FALSE(testARMExtension("arm10tdmi", +                                ARM::ArchKind::INVALID, "simd")); +  EXPECT_FALSE(testARMExtension("arm1022e", ARM::ArchKind::INVALID, "simd")); +  EXPECT_FALSE(testARMExtension("arm926ej-s", +                                ARM::ArchKind::INVALID, "simd")); +  EXPECT_FALSE(testARMExtension("arm1136jf-s", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("arm1176j-s", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("arm1156t2-s", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("arm1176jzf-s", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("cortex-m0", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("cortex-a8", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("cortex-r4", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("cortex-m3", +                                ARM::ArchKind::INVALID, "crypto")); +  EXPECT_FALSE(testARMExtension("cortex-a53", +                                ARM::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testARMExtension("cortex-r52", +                                ARM::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testARMExtension("iwmmxt", ARM::ArchKind::INVALID, "crc")); +  EXPECT_FALSE(testARMExtension("xscale", ARM::ArchKind::INVALID, "crc")); +  EXPECT_FALSE(testARMExtension("swift", ARM::ArchKind::INVALID, "crc")); + +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV2, "thumb")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV2A, "thumb")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV3, "thumb")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV3M, "thumb")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV4, "dsp")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV4T, "dsp")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5T, "simd")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5TE, "simd")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV5TEJ, "simd")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6K, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", +                                ARM::ArchKind::ARMV6T2, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", +                                ARM::ArchKind::ARMV6KZ, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV6M, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7A, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7R, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7M, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", +                                ARM::ArchKind::ARMV7EM, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8A, "ras")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_1A, "ras")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8_2A, "spe")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV8R, "ras")); +  EXPECT_FALSE(testARMExtension("generic", +                                ARM::ArchKind::ARMV8MBaseline, "crc")); +  EXPECT_FALSE(testARMExtension("generic", +                                ARM::ArchKind::ARMV8MMainline, "crc")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::IWMMXT, "crc")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::IWMMXT2, "crc")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::XSCALE, "crc")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7S, "crypto")); +  EXPECT_FALSE(testARMExtension("generic", ARM::ArchKind::ARMV7K, "crypto"));  }  TEST(TargetParserTest, ARMFPUVersion) { -  for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0); +  for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);          FK <= ARM::FPUKind::FK_LAST;         FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) -    if (FK == ARM::FK_LAST) -      EXPECT_EQ(0U, ARM::getFPUVersion(FK)); +    if (FK == ARM::FK_LAST || ARM::getFPUName(FK) == "invalid" || +        ARM::getFPUName(FK) == "none" || ARM::getFPUName(FK) == "softvfp") +      EXPECT_EQ(ARM::FPUVersion::NONE, ARM::getFPUVersion(FK));      else -      EXPECT_LE(0U, ARM::getFPUVersion(FK)); +      EXPECT_NE(ARM::FPUVersion::NONE, ARM::getFPUVersion(FK));  }  TEST(TargetParserTest, ARMFPUNeonSupportLevel) {    for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);         FK <= ARM::FPUKind::FK_LAST;         FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) -    if (FK == ARM::FK_LAST) -      EXPECT_EQ(0U, ARM::getFPUNeonSupportLevel(FK)); +    if (FK == ARM::FK_LAST || +        ARM::getFPUName(FK).find("neon") == std::string::npos) +      EXPECT_EQ(ARM::NeonSupportLevel::None, +                 ARM::getFPUNeonSupportLevel(FK));      else -      EXPECT_LE(0U, ARM::getFPUNeonSupportLevel(FK)); +      EXPECT_NE(ARM::NeonSupportLevel::None, +                ARM::getFPUNeonSupportLevel(FK));  }  TEST(TargetParserTest, ARMFPURestriction) {    for (ARM::FPUKind FK = static_cast<ARM::FPUKind>(0);         FK <= ARM::FPUKind::FK_LAST; -       FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) -    if (FK == ARM::FK_LAST) -      EXPECT_EQ(0U, ARM::getFPURestriction(FK)); +       FK = static_cast<ARM::FPUKind>(static_cast<unsigned>(FK) + 1)) { +    if (FK == ARM::FK_LAST || +        (ARM::getFPUName(FK).find("d16") == std::string::npos && +         ARM::getFPUName(FK).find("vfpv3xd") == std::string::npos)) +      EXPECT_EQ(ARM::FPURestriction::None, ARM::getFPURestriction(FK));      else -      EXPECT_LE(0U, ARM::getFPURestriction(FK)); +      EXPECT_NE(ARM::FPURestriction::None, ARM::getFPURestriction(FK)); +  }  }  TEST(TargetParserTest, ARMExtensionFeatures) { @@ -491,6 +530,7 @@ TEST(TargetParserTest, ARMArchExtFeature) {                                {"virt", "novirt", nullptr, nullptr},                                {"fp16", "nofp16", "+fullfp16", "-fullfp16"},                                {"ras", "noras", "+ras", "-ras"}, +                              {"dotprod", "nodotprod", "+dotprod", "-dotprod"},                                {"os", "noos", nullptr, nullptr},                                {"iwmmxt", "noiwmmxt", nullptr, nullptr},                                {"iwmmxt2", "noiwmmxt2", nullptr, nullptr}, @@ -517,7 +557,7 @@ TEST(TargetParserTest, ARMparseArchEndianAndISA) {        "v6kz",   "v6z",   "v6zk",   "v6-m",  "v6m",  "v6sm", "v6s-m", "v7-a",        "v7",     "v7a",   "v7ve",   "v7hl",  "v7l",  "v7-r", "v7r",   "v7-m",        "v7m",    "v7k",   "v7s",    "v7e-m", "v7em", "v8-a", "v8",    "v8a", -      "v8.1-a", "v8.1a", "v8.2-a", "v8.2a", "v8-r"}; +      "v8.1-a", "v8.1a", "v8.2-a", "v8.2a", "v8.3-a", "v8.3a", "v8-r"};    for (unsigned i = 0; i < array_lengthof(Arch); i++) {      std::string arm_1 = "armeb" + (std::string)(Arch[i]); @@ -527,57 +567,60 @@ TEST(TargetParserTest, ARMparseArchEndianAndISA) {      std::string thumb_2 = "thumb" + (std::string)(Arch[i]) + "eb";      std::string thumb_3 = "thumb" + (std::string)(Arch[i]); -    EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(arm_1)); -    EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(arm_2)); -    EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian(arm_3)); +    EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(arm_1)); +    EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(arm_2)); +    EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian(arm_3)); -    EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_1)); -    EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_2)); -    EXPECT_EQ(ARM::IK_ARM, ARM::parseArchISA(arm_3)); +    EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_1)); +    EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_2)); +    EXPECT_EQ(ARM::ISAKind::ARM, ARM::parseArchISA(arm_3));      if (i >= 4) { -      EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(thumb_1)); -      EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian(thumb_2)); -      EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian(thumb_3)); +      EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(thumb_1)); +      EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian(thumb_2)); +      EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian(thumb_3)); -      EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_1)); -      EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_2)); -      EXPECT_EQ(ARM::IK_THUMB, ARM::parseArchISA(thumb_3)); +      EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_1)); +      EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_2)); +      EXPECT_EQ(ARM::ISAKind::THUMB, ARM::parseArchISA(thumb_3));      }    } -  EXPECT_EQ(ARM::EK_LITTLE, ARM::parseArchEndian("aarch64")); -  EXPECT_EQ(ARM::EK_BIG, ARM::parseArchEndian("aarch64_be")); +  EXPECT_EQ(ARM::EndianKind::LITTLE, ARM::parseArchEndian("aarch64")); +  EXPECT_EQ(ARM::EndianKind::BIG, ARM::parseArchEndian("aarch64_be")); -  EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("aarch64")); -  EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("aarch64_be")); -  EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("arm64")); -  EXPECT_EQ(ARM::IK_AARCH64, ARM::parseArchISA("arm64_be")); +  EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("aarch64")); +  EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("aarch64_be")); +  EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("arm64")); +  EXPECT_EQ(ARM::ISAKind::AARCH64, ARM::parseArchISA("arm64_be"));  }  TEST(TargetParserTest, ARMparseArchProfile) {    for (unsigned i = 0; i < array_lengthof(ARMArch); i++) {      switch (ARM::parseArch(ARMArch[i])) { -    case ARM::AK_ARMV6M: -    case ARM::AK_ARMV7M: -    case ARM::AK_ARMV7EM: -    case ARM::AK_ARMV8MMainline: -    case ARM::AK_ARMV8MBaseline: -      EXPECT_EQ(ARM::PK_M, ARM::parseArchProfile(ARMArch[i])); -      continue; -    case ARM::AK_ARMV7R: -    case ARM::AK_ARMV8R: -      EXPECT_EQ(ARM::PK_R, ARM::parseArchProfile(ARMArch[i])); -      continue; -    case ARM::AK_ARMV7A: -    case ARM::AK_ARMV7VE: -    case ARM::AK_ARMV7K: -    case ARM::AK_ARMV8A: -    case ARM::AK_ARMV8_1A: -    case ARM::AK_ARMV8_2A: -      EXPECT_EQ(ARM::PK_A, ARM::parseArchProfile(ARMArch[i])); -      continue; +    case ARM::ArchKind::ARMV6M: +    case ARM::ArchKind::ARMV7M: +    case ARM::ArchKind::ARMV7EM: +    case ARM::ArchKind::ARMV8MMainline: +    case ARM::ArchKind::ARMV8MBaseline: +      EXPECT_EQ(ARM::ProfileKind::M, ARM::parseArchProfile(ARMArch[i])); +      break; +    case ARM::ArchKind::ARMV7R: +    case ARM::ArchKind::ARMV8R: +      EXPECT_EQ(ARM::ProfileKind::R, ARM::parseArchProfile(ARMArch[i])); +      break; +    case ARM::ArchKind::ARMV7A: +    case ARM::ArchKind::ARMV7VE: +    case ARM::ArchKind::ARMV7K: +    case ARM::ArchKind::ARMV8A: +    case ARM::ArchKind::ARMV8_1A: +    case ARM::ArchKind::ARMV8_2A: +    case ARM::ArchKind::ARMV8_3A: +      EXPECT_EQ(ARM::ProfileKind::A, ARM::parseArchProfile(ARMArch[i])); +      break; +    default: +      EXPECT_EQ(ARM::ProfileKind::INVALID, ARM::parseArchProfile(ARMArch[i])); +      break;      } -    EXPECT_EQ(ARM::PK_INVALID, ARM::parseArchProfile(ARMArch[i]));    }  } @@ -592,18 +635,18 @@ TEST(TargetParserTest, ARMparseArchVersion) {  bool testAArch64CPU(StringRef CPUName, StringRef ExpectedArch,                      StringRef ExpectedFPU, unsigned ExpectedFlags,                      StringRef CPUAttr) { -  unsigned ArchKind = AArch64::parseCPUArch(CPUName); -  bool pass = AArch64::getArchName(ArchKind).equals(ExpectedArch); -  unsigned FPUKind = AArch64::getDefaultFPU(CPUName, ArchKind); +  AArch64::ArchKind AK = AArch64::parseCPUArch(CPUName); +  bool pass = AArch64::getArchName(AK).equals(ExpectedArch); +  unsigned FPUKind = AArch64::getDefaultFPU(CPUName, AK);    pass &= AArch64::getFPUName(FPUKind).equals(ExpectedFPU); -  unsigned ExtKind = AArch64::getDefaultExtensions(CPUName, ArchKind); +  unsigned ExtKind = AArch64::getDefaultExtensions(CPUName, AK);    if (ExtKind > 1 && (ExtKind & AArch64::AEK_NONE))      pass &= ((ExtKind ^ AArch64::AEK_NONE) == ExpectedFlags);    else      pass &= (ExtKind == ExpectedFlags); -  pass &= AArch64::getCPUAttr(ArchKind).equals(CPUAttr); +  pass &= AArch64::getCPUAttr(AK).equals(CPUAttr);    return pass;  } @@ -625,6 +668,12 @@ TEST(TargetParserTest, testAArch64CPU) {        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |        AArch64::AEK_SIMD, "8-A"));    EXPECT_TRUE(testAArch64CPU( +      "cortex-a55", "armv8.2-a", "crypto-neon-fp-armv8", +      AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | +      AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | +      AArch64::AEK_RDM | AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | +      AArch64::AEK_RCPC, "8.2-A")); +  EXPECT_TRUE(testAArch64CPU(        "cortex-a57", "armv8-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |        AArch64::AEK_SIMD, "8-A")); @@ -637,6 +686,12 @@ TEST(TargetParserTest, testAArch64CPU) {        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP |        AArch64::AEK_SIMD, "8-A"));    EXPECT_TRUE(testAArch64CPU( +      "cortex-a75", "armv8.2-a", "crypto-neon-fp-armv8", +      AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | +      AArch64::AEK_SIMD | AArch64::AEK_RAS | AArch64::AEK_LSE | +      AArch64::AEK_RDM | AArch64::AEK_FP16 | AArch64::AEK_DOTPROD | +      AArch64::AEK_RCPC, "8.2-A")); +  EXPECT_TRUE(testAArch64CPU(        "cyclone", "armv8-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRYPTO | AArch64::AEK_FP | AArch64::AEK_SIMD, "8-A"));    EXPECT_TRUE(testAArch64CPU( @@ -654,7 +709,7 @@ TEST(TargetParserTest, testAArch64CPU) {    EXPECT_TRUE(testAArch64CPU(        "falkor", "armv8-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | -      AArch64::AEK_SIMD, "8-A")); +      AArch64::AEK_SIMD | AArch64::AEK_RDM, "8-A"));    EXPECT_TRUE(testAArch64CPU(        "kryo", "armv8-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_FP | @@ -662,7 +717,7 @@ TEST(TargetParserTest, testAArch64CPU) {    EXPECT_TRUE(testAArch64CPU(        "thunderx2t99", "armv8.1-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_LSE | -      AArch64::AEK_FP | AArch64::AEK_SIMD, "8.1-A")); +      AArch64::AEK_RDM | AArch64::AEK_FP | AArch64::AEK_SIMD, "8.1-A"));    EXPECT_TRUE(testAArch64CPU(        "thunderx", "armv8-a", "crypto-neon-fp-armv8",        AArch64::AEK_CRC | AArch64::AEK_CRYPTO | AArch64::AEK_SIMD | @@ -687,11 +742,11 @@ TEST(TargetParserTest, testAArch64CPU) {  bool testAArch64Arch(StringRef Arch, StringRef DefaultCPU, StringRef SubArch,                       unsigned ArchAttr) { -  unsigned ArchKind = AArch64::parseArch(Arch); -  return (ArchKind != static_cast<unsigned>(AArch64::ArchKind::AK_INVALID)) & +  AArch64::ArchKind AK = AArch64::parseArch(Arch); +  return (AK != AArch64::ArchKind::INVALID) &           AArch64::getDefaultCPU(Arch).equals(DefaultCPU) & -         AArch64::getSubArch(ArchKind).equals(SubArch) & -         (AArch64::getArchAttr(ArchKind) == ArchAttr); +         AArch64::getSubArch(AK).equals(SubArch) & +         (AArch64::getArchAttr(AK) == ArchAttr);  }  TEST(TargetParserTest, testAArch64Arch) { @@ -701,35 +756,74 @@ TEST(TargetParserTest, testAArch64Arch) {                                ARMBuildAttrs::CPUArch::v8_A));    EXPECT_TRUE(testAArch64Arch("armv8.2-a", "generic", "v8.2a",                                ARMBuildAttrs::CPUArch::v8_A)); +  EXPECT_TRUE(testAArch64Arch("armv8.3-a", "generic", "v8.3a", +                              ARMBuildAttrs::CPUArch::v8_A));  } -bool testAArch64Extension(StringRef CPUName, unsigned ArchKind, +bool testAArch64Extension(StringRef CPUName, AArch64::ArchKind AK,                            StringRef ArchExt) { -  return AArch64::getDefaultExtensions(CPUName, ArchKind) & +  return AArch64::getDefaultExtensions(CPUName, AK) &           AArch64::parseArchExt(ArchExt);  }  TEST(TargetParserTest, testAArch64Extension) { -  EXPECT_FALSE(testAArch64Extension("cortex-a35", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("cortex-a53", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("cortex-a57", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("cortex-a72", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("cortex-a73", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("cyclone", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("exynos-m1", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("kryo", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("thunderx2t99", 0, "ras")); -  EXPECT_FALSE(testAArch64Extension("thunderx", 0, "lse")); -  EXPECT_FALSE(testAArch64Extension("thunderxt81", 0, "lse")); -  EXPECT_FALSE(testAArch64Extension("thunderxt83", 0, "lse")); -  EXPECT_FALSE(testAArch64Extension("thunderxt88", 0, "lse")); +  EXPECT_FALSE(testAArch64Extension("cortex-a35", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("cortex-a53", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_TRUE(testAArch64Extension("cortex-a55", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("cortex-a57", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("cortex-a72", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("cortex-a73", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_TRUE(testAArch64Extension("cortex-a75", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("cyclone", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("exynos-m1", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("exynos-m2", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("exynos-m3", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_TRUE(testAArch64Extension("falkor", +                                   AArch64::ArchKind::INVALID, "rdm")); +  EXPECT_FALSE(testAArch64Extension("kryo", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                    AArch64::ArchKind::INVALID, "crc")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                    AArch64::ArchKind::INVALID, "lse")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                   AArch64::ArchKind::INVALID, "rdm")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                   AArch64::ArchKind::INVALID, "ras")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                   AArch64::ArchKind::INVALID, "rcpc")); +  EXPECT_TRUE(testAArch64Extension("saphira", +                                   AArch64::ArchKind::INVALID, "profile")); +  EXPECT_FALSE(testAArch64Extension("saphira", +                                    AArch64::ArchKind::INVALID, "fullfp16")); +  EXPECT_FALSE(testAArch64Extension("thunderx2t99", +                                    AArch64::ArchKind::INVALID, "ras")); +  EXPECT_FALSE(testAArch64Extension("thunderx", +                                    AArch64::ArchKind::INVALID, "lse")); +  EXPECT_FALSE(testAArch64Extension("thunderxt81", +                                    AArch64::ArchKind::INVALID, "lse")); +  EXPECT_FALSE(testAArch64Extension("thunderxt83", +                                    AArch64::ArchKind::INVALID, "lse")); +  EXPECT_FALSE(testAArch64Extension("thunderxt88", +                                    AArch64::ArchKind::INVALID, "lse"));    EXPECT_FALSE(testAArch64Extension( -      "generic", static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8A), "ras")); +      "generic", AArch64::ArchKind::ARMV8A, "ras"));    EXPECT_FALSE(testAArch64Extension( -      "generic", static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_1A), "ras")); +      "generic", AArch64::ArchKind::ARMV8_1A, "ras"));    EXPECT_FALSE(testAArch64Extension( -      "generic", static_cast<unsigned>(AArch64::ArchKind::AK_ARMV8_2A), "spe")); +      "generic", AArch64::ArchKind::ARMV8_2A, "spe"));  }  TEST(TargetParserTest, AArch64ExtensionFeatures) { @@ -737,7 +831,9 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {    unsigned Extensions = AArch64::AEK_CRC | AArch64::AEK_CRYPTO |                          AArch64::AEK_FP | AArch64::AEK_SIMD |                          AArch64::AEK_FP16 | AArch64::AEK_PROFILE | -                        AArch64::AEK_RAS | AArch64::AEK_SVE; +                        AArch64::AEK_RAS | AArch64::AEK_LSE | +                        AArch64::AEK_RDM | AArch64::AEK_SVE | +                        AArch64::AEK_DOTPROD | AArch64::AEK_RCPC;    for (unsigned i = 0; i <= Extensions; i++)      EXPECT_TRUE(i == 0 ? !AArch64::getExtensionFeatures(i, Features) @@ -746,11 +842,14 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) {  TEST(TargetParserTest, AArch64ArchFeatures) {    std::vector<StringRef> Features; - -  for (unsigned AK = 0; AK < static_cast<unsigned>(AArch64::ArchKind::AK_LAST); -       AK++) -    EXPECT_TRUE((AK == static_cast<unsigned>(AArch64::ArchKind::AK_INVALID) || -                 AK == static_cast<unsigned>(AArch64::ArchKind::AK_LAST)) +  AArch64::ArchKind ArchKinds[] = { +#define AARCH64_ARCH(NAME, ID, CPU_ATTR, SUB_ARCH, ARCH_ATTR, ARCH_FPU, ARCH_BASE_EXT)       \ +     AArch64::ArchKind::ID, +#include "llvm/Support/AArch64TargetParser.def" +  }; + +  for (auto AK : ArchKinds) +    EXPECT_TRUE((AK == AArch64::ArchKind::INVALID)                      ? !AArch64::getArchFeatures(AK, Features)                      : AArch64::getArchFeatures(AK, Features));  } @@ -763,7 +862,11 @@ TEST(TargetParserTest, AArch64ArchExtFeature) {                                {"fp16", "nofp16", "+fullfp16", "-fullfp16"},                                {"profile", "noprofile", "+spe", "-spe"},                                {"ras", "noras", "+ras", "-ras"}, -                              {"sve", "nosve", "+sve", "-sve"}}; +                              {"lse", "nolse", "+lse", "-lse"}, +                              {"rdm", "nordm", "+rdm", "-rdm"}, +                              {"sve", "nosve", "+sve", "-sve"}, +                              {"dotprod", "nodotprod", "+dotprod", "-dotprod"}, +                              {"rcpc", "norcpc", "+rcpc", "-rcpc" }};    for (unsigned i = 0; i < array_lengthof(ArchExt); i++) {      EXPECT_EQ(StringRef(ArchExt[i][2]), diff --git a/unittests/Support/YAMLIOTest.cpp b/unittests/Support/YAMLIOTest.cpp index 120773a0c8dd..9caff85a5963 100644 --- a/unittests/Support/YAMLIOTest.cpp +++ b/unittests/Support/YAMLIOTest.cpp @@ -860,7 +860,7 @@ namespace yaml {            return "malformed by";        }      } -    static bool mustQuote(StringRef) { return true; } +    static QuotingType mustQuote(StringRef) { return QuotingType::Single; }    };  }  } @@ -1064,7 +1064,7 @@ namespace yaml {        return StringRef();      } -    static bool mustQuote(StringRef) { return false; } +    static QuotingType mustQuote(StringRef) { return QuotingType::None; }    };    template <> struct ScalarTraits<MyString> { @@ -1075,7 +1075,9 @@ namespace yaml {      static StringRef input(StringRef S, void *Ctx, MyString &V) {        return Impl::input(S, Ctx, V.value);      } -    static bool mustQuote(StringRef S) { return Impl::mustQuote(S); } +    static QuotingType mustQuote(StringRef S) { +      return Impl::mustQuote(S); +    }    };  }  } @@ -2232,7 +2234,7 @@ struct ScalarTraits<FlowSeq> {      return "";    } -  static bool mustQuote(StringRef S) { return false; } +  static QuotingType mustQuote(StringRef S) { return QuotingType::None; }  };  }  } @@ -2455,3 +2457,87 @@ TEST(YAMLIO, InvalidInput) {    yin >> Data;    EXPECT_TRUE((bool)yin.error());  } + +TEST(YAMLIO, TestEscapedSingleQuote) { +  std::string Id = "@abc@"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("'@abc@'", out); +} + +TEST(YAMLIO, TestEscapedNoQuote) { +  std::string Id = "abc/"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("abc/", out); +} + +TEST(YAMLIO, TestEscapedDoubleQuoteNonPrintable) { +  std::string Id = "\01@abc@"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("\"\\x01@abc@\"", out); +} + +TEST(YAMLIO, TestEscapedDoubleQuoteInsideSingleQuote) { +  std::string Id = "abc\"fdf"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("'abc\"fdf'", out); +} + +TEST(YAMLIO, TestEscapedDoubleQuoteInsideDoubleQuote) { +  std::string Id = "\01bc\"fdf"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("\"\\x01bc\\\"fdf\"", out); +} + +TEST(YAMLIO, TestEscapedSingleQuoteInsideSingleQuote) { +  std::string Id = "abc'fdf"; + +  std::string out; +  llvm::raw_string_ostream ostr(out); +  Output xout(ostr, nullptr, 0); + +  llvm::yaml::EmptyContext Ctx; +  yamlize(xout, Id, true, Ctx); + +  ostr.flush(); +  EXPECT_EQ("'abc''fdf'", out); +} diff --git a/unittests/Support/YAMLParserTest.cpp b/unittests/Support/YAMLParserTest.cpp index d411a286830b..7962f3ca1ad1 100644 --- a/unittests/Support/YAMLParserTest.cpp +++ b/unittests/Support/YAMLParserTest.cpp @@ -180,6 +180,7 @@ TEST(YAMLParser, HandlesEndOfFileGracefully) {  }  TEST(YAMLParser, HandlesNullValuesInKeyValueNodesGracefully) { +  ExpectParseError("KeyValueNode with null key", "? \"\n:");    ExpectParseError("KeyValueNode with null value", "test: '");  } | 
