From: Francis Visoiu Mistrih <francisvm@yahoo.com> Date: Wed, 16 Oct 2019 15:40:59 +0000 (+0000) Subject: [Remarks] Add support for prepending a path to external files X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=381c09ac35354db8f183fd78dadab53940323c92;p=llvm [Remarks] Add support for prepending a path to external files This helps with testing and debugging for paths that are assumed absolute. It also uses a FileError to provide the file path it's trying to open. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375008 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Remarks/RemarkParser.h b/include/llvm/Remarks/RemarkParser.h index 551d20a8a0a..d6b1fddb06f 100644 --- a/include/llvm/Remarks/RemarkParser.h +++ b/include/llvm/Remarks/RemarkParser.h @@ -39,6 +39,8 @@ public: struct RemarkParser { /// The format of the parser. Format ParserFormat; + /// Path to prepend when opening an external remark file. + std::string ExternalFilePrependPath; RemarkParser(Format ParserFormat) : ParserFormat(ParserFormat) {} @@ -82,7 +84,8 @@ createRemarkParser(Format ParserFormat, StringRef Buf, Expected<std::unique_ptr<RemarkParser>> createRemarkParserFromMeta(Format ParserFormat, StringRef Buf, - Optional<ParsedStringTable> StrTab = None); + Optional<ParsedStringTable> StrTab = None, + Optional<StringRef> ExternalFilePrependPath = None); } // end namespace remarks } // end namespace llvm diff --git a/lib/Remarks/BitstreamRemarkParser.cpp b/lib/Remarks/BitstreamRemarkParser.cpp index f57d01fbee0..99a82e1ee3a 100644 --- a/lib/Remarks/BitstreamRemarkParser.cpp +++ b/lib/Remarks/BitstreamRemarkParser.cpp @@ -15,6 +15,7 @@ #include "BitstreamRemarkParser.h" #include "llvm/Remarks/BitstreamRemarkContainer.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::remarks; @@ -304,8 +305,9 @@ static Error advanceToMetaBlock(BitstreamParserHelper &Helper) { } Expected<std::unique_ptr<BitstreamRemarkParser>> -remarks::createBitstreamParserFromMeta(StringRef Buf, - Optional<ParsedStringTable> StrTab) { +remarks::createBitstreamParserFromMeta( + StringRef Buf, Optional<ParsedStringTable> StrTab, + Optional<StringRef> ExternalFilePrependPath) { BitstreamParserHelper Helper(Buf); Expected<std::array<char, 4>> Magic = Helper.parseMagic(); if (!Magic) @@ -314,9 +316,14 @@ remarks::createBitstreamParserFromMeta(StringRef Buf, if (Error E = validateMagicNumber(StringRef(Magic->data(), Magic->size()))) return std::move(E); - return StrTab - ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab)) + auto Parser = + StrTab ? std::make_unique<BitstreamRemarkParser>(Buf, std::move(*StrTab)) : std::make_unique<BitstreamRemarkParser>(Buf); + + if (ExternalFilePrependPath) + Parser->ExternalFilePrependPath = *ExternalFilePrependPath; + + return std::move(Parser); } Expected<std::unique_ptr<Remark>> BitstreamRemarkParser::next() { @@ -409,13 +416,16 @@ Error BitstreamRemarkParser::processExternalFilePath( std::make_error_code(std::errc::illegal_byte_sequence), "Error while parsing BLOCK_META: missing external file path."); + SmallString<80> FullPath(ExternalFilePrependPath); + sys::path::append(FullPath, *ExternalFilePath); + // External file: open the external file, parse it, check if its metadata // matches the one from the separate metadata, then replace the current parser // with the one parsing the remarks. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = - MemoryBuffer::getFile(*ExternalFilePath); + MemoryBuffer::getFile(FullPath); if (std::error_code EC = BufferOrErr.getError()) - return errorCodeToError(EC); + return createFileError(FullPath, EC); TmpRemarkBuffer = std::move(*BufferOrErr); // Create a separate parser used for parsing the separate file. diff --git a/lib/Remarks/BitstreamRemarkParser.h b/lib/Remarks/BitstreamRemarkParser.h index f1f28b4aeb7..7c9cc2f1e7d 100644 --- a/lib/Remarks/BitstreamRemarkParser.h +++ b/lib/Remarks/BitstreamRemarkParser.h @@ -73,9 +73,9 @@ private: Error processExternalFilePath(Optional<StringRef> ExternalFilePath); }; -Expected<std::unique_ptr<BitstreamRemarkParser>> -createBitstreamParserFromMeta(StringRef Buf, - Optional<ParsedStringTable> StrTab = None); +Expected<std::unique_ptr<BitstreamRemarkParser>> createBitstreamParserFromMeta( + StringRef Buf, Optional<ParsedStringTable> StrTab = None, + Optional<StringRef> ExternalFilePrependPath = None); } // end namespace remarks } // end namespace llvm diff --git a/lib/Remarks/RemarkParser.cpp b/lib/Remarks/RemarkParser.cpp index 600f415e9b5..c5c3d0badd3 100644 --- a/lib/Remarks/RemarkParser.cpp +++ b/lib/Remarks/RemarkParser.cpp @@ -86,16 +86,19 @@ llvm::remarks::createRemarkParser(Format ParserFormat, StringRef Buf, } Expected<std::unique_ptr<RemarkParser>> -llvm::remarks::createRemarkParserFromMeta(Format ParserFormat, StringRef Buf, - Optional<ParsedStringTable> StrTab) { +llvm::remarks::createRemarkParserFromMeta( + Format ParserFormat, StringRef Buf, Optional<ParsedStringTable> StrTab, + Optional<StringRef> ExternalFilePrependPath) { switch (ParserFormat) { // Depending on the metadata, the format can be either yaml or yaml-strtab, // regardless of the input argument. case Format::YAML: case Format::YAMLStrTab: - return createYAMLParserFromMeta(Buf, std::move(StrTab)); + return createYAMLParserFromMeta(Buf, std::move(StrTab), + std::move(ExternalFilePrependPath)); case Format::Bitstream: - return createBitstreamParserFromMeta(Buf, std::move(StrTab)); + return createBitstreamParserFromMeta(Buf, std::move(StrTab), + std::move(ExternalFilePrependPath)); case Format::Unknown: return createStringError(std::make_error_code(std::errc::invalid_argument), "Unknown remark parser format."); diff --git a/lib/Remarks/YAMLRemarkParser.cpp b/lib/Remarks/YAMLRemarkParser.cpp index 69e8a0dfd76..dd834d85676 100644 --- a/lib/Remarks/YAMLRemarkParser.cpp +++ b/lib/Remarks/YAMLRemarkParser.cpp @@ -15,6 +15,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Remarks/RemarkParser.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Path.h" using namespace llvm; using namespace llvm::remarks; @@ -109,7 +110,8 @@ static Expected<ParsedStringTable> parseStrTab(StringRef &Buf, Expected<std::unique_ptr<YAMLRemarkParser>> remarks::createYAMLParserFromMeta(StringRef Buf, - Optional<ParsedStringTable> StrTab) { + Optional<ParsedStringTable> StrTab, + Optional<StringRef> ExternalFilePrependPath) { // We now have a magic number. The metadata has to be correct. Expected<bool> isMeta = parseMagic(Buf); if (!isMeta) @@ -138,11 +140,17 @@ remarks::createYAMLParserFromMeta(StringRef Buf, // If it starts with "---", there is no external file. if (!Buf.startswith("---")) { // At this point, we expect Buf to contain the external file path. + StringRef ExternalFilePath = Buf; + SmallString<80> FullPath; + if (ExternalFilePrependPath) + FullPath = *ExternalFilePrependPath; + sys::path::append(FullPath, ExternalFilePath); + // Try to open the file and start parsing from there. ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = - MemoryBuffer::getFile(Buf); + MemoryBuffer::getFile(FullPath); if (std::error_code EC = BufferOrErr.getError()) - return errorCodeToError(EC); + return createFileError(FullPath, EC); // Keep the buffer alive. SeparateBuf = std::move(*BufferOrErr); diff --git a/lib/Remarks/YAMLRemarkParser.h b/lib/Remarks/YAMLRemarkParser.h index ff03abbb576..03707433bc0 100644 --- a/lib/Remarks/YAMLRemarkParser.h +++ b/lib/Remarks/YAMLRemarkParser.h @@ -111,7 +111,8 @@ protected: Expected<std::unique_ptr<YAMLRemarkParser>> createYAMLParserFromMeta(StringRef Buf, - Optional<ParsedStringTable> StrTab = None); + Optional<ParsedStringTable> StrTab = None, + Optional<StringRef> ExternalFilePrependPath = None); } // end namespace remarks } // end namespace llvm diff --git a/unittests/Remarks/YAMLRemarksParsingTest.cpp b/unittests/Remarks/YAMLRemarksParsingTest.cpp index aec2e97cda8..04ba8702f36 100644 --- a/unittests/Remarks/YAMLRemarksParsingTest.cpp +++ b/unittests/Remarks/YAMLRemarksParsingTest.cpp @@ -63,12 +63,15 @@ bool parseExpectError(const char (&Buf)[N], const char *Error) { return StringRef(Stream.str()).contains(Error); } -void parseExpectErrorMeta(StringRef Buf, const char *Error) { +void parseExpectErrorMeta(StringRef Buf, const char *Error, + Optional<StringRef> ExternalFilePrependPath = None) { std::string ErrorStr; raw_string_ostream Stream(ErrorStr); Expected<std::unique_ptr<remarks::RemarkParser>> MaybeParser = - remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf); + remarks::createRemarkParserFromMeta(remarks::Format::YAML, Buf, + /*StrTab=*/None, + std::move(ExternalFilePrependPath)); handleAllErrors(MaybeParser.takeError(), [&](const ErrorInfoBase &EIB) { EIB.log(Stream); }); @@ -705,6 +708,14 @@ TEST(YAMLRemarks, ParsingBadMeta) { "\0\0\0\0\0\0\0\0" "\0\0\0\0\0\0\0\0" "/path/", - 28), - "No such file or directory"); + 30), + "'/path/': No such file or directory"); + + parseExpectErrorMeta(StringRef("REMARKS\0" + "\0\0\0\0\0\0\0\0" + "\0\0\0\0\0\0\0\0" + "/path/", + 30), + "'/baddir/path/': No such file or directory", + StringRef("/baddir/")); }