https://github.com/abhina-sree updated https://github.com/llvm/llvm-project/pull/111723
>From c1676e48a587e10ba54c28e99192fd5e6a36f72e Mon Sep 17 00:00:00 2001 From: Abhina Sreeskantharajan <abhina.sreeskanthara...@ibm.com> Date: Wed, 9 Oct 2024 13:23:41 -0400 Subject: [PATCH 1/3] [SystemZ][z/OS] Add new openFileForReadBinary function, and pass IsText parameter to getBufferForFile --- clang/include/clang/Basic/FileManager.h | 8 ++--- clang/lib/Basic/FileManager.cpp | 12 +++---- clang/lib/Lex/HeaderMap.cpp | 4 ++- clang/lib/Serialization/ASTReader.cpp | 3 +- llvm/include/llvm/Support/VirtualFileSystem.h | 13 ++++++-- llvm/lib/Support/VirtualFileSystem.cpp | 31 +++++++++++++------ 6 files changed, 48 insertions(+), 23 deletions(-) diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index ce4e8c1fbe16eb..d987fb05a94a37 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -292,21 +292,21 @@ class FileManager : public RefCountedBase<FileManager> { /// MemoryBuffer if successful, otherwise returning null. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(FileEntryRef Entry, bool isVolatile = false, - bool RequiresNullTerminator = true, + bool RequiresNullTerminator = true, bool IsText = true, std::optional<int64_t> MaybeLimit = std::nullopt); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(StringRef Filename, bool isVolatile = false, - bool RequiresNullTerminator = true, + bool RequiresNullTerminator = true, bool IsText = true, std::optional<int64_t> MaybeLimit = std::nullopt) const { return getBufferForFileImpl(Filename, /*FileSize=*/MaybeLimit.value_or(-1), - isVolatile, RequiresNullTerminator); + isVolatile, RequiresNullTerminator, IsText); } private: llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFileImpl(StringRef Filename, int64_t FileSize, bool isVolatile, - bool RequiresNullTerminator) const; + bool RequiresNullTerminator, bool IsText) const; DirectoryEntry *&getRealDirEntry(const llvm::vfs::Status &Status); diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index 6097b85a03064b..27075cefafdc2f 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -530,7 +530,7 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile, - bool RequiresNullTerminator, + bool RequiresNullTerminator, bool IsText, std::optional<int64_t> MaybeLimit) { const FileEntry *Entry = &FE.getFileEntry(); // If the content is living on the file entry, return a reference to it. @@ -558,21 +558,21 @@ FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile, // Otherwise, open the file. return getBufferForFileImpl(Filename, FileSize, isVolatile, - RequiresNullTerminator); + RequiresNullTerminator, IsText); } llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize, - bool isVolatile, - bool RequiresNullTerminator) const { + bool isVolatile, bool RequiresNullTerminator, + bool IsText) const { if (FileSystemOpts.WorkingDir.empty()) return FS->getBufferForFile(Filename, FileSize, RequiresNullTerminator, - isVolatile); + isVolatile, IsText); SmallString<128> FilePath(Filename); FixupRelativePath(FilePath); return FS->getBufferForFile(FilePath, FileSize, RequiresNullTerminator, - isVolatile); + isVolatile, IsText); } /// getStatValue - Get the 'stat' information for the specified path, diff --git a/clang/lib/Lex/HeaderMap.cpp b/clang/lib/Lex/HeaderMap.cpp index 00bf880726ee3e..35c68b304a4523 100644 --- a/clang/lib/Lex/HeaderMap.cpp +++ b/clang/lib/Lex/HeaderMap.cpp @@ -54,7 +54,9 @@ std::unique_ptr<HeaderMap> HeaderMap::Create(FileEntryRef FE, FileManager &FM) { unsigned FileSize = FE.getSize(); if (FileSize <= sizeof(HMapHeader)) return nullptr; - auto FileBuffer = FM.getBufferForFile(FE); + auto FileBuffer = + FM.getBufferForFile(FE, /*IsVolatile=*/false, + /*RequiresNullTerminator=*/true, /*IsText=*/false); if (!FileBuffer || !*FileBuffer) return nullptr; bool NeedsByteSwap; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 5c4f8d0e9c46cd..769b85dc318072 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5333,7 +5333,8 @@ std::string ASTReader::getOriginalSourceFile( const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags) { // Open the AST file. auto Buffer = FileMgr.getBufferForFile(ASTFileName, /*IsVolatile=*/false, - /*RequiresNullTerminator=*/false); + /*RequiresNullTerminator=*/false, + /*IsText=*/false); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) << ASTFileName << Buffer.getError().message(); diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index 2531c075f262d7..a94e285a806f2c 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -271,15 +271,24 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem>, /// Get the status of the entry at \p Path, if one exists. virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0; - /// Get a \p File object for the file at \p Path, if one exists. + /// Get a \p File object for the text file at \p Path, if one exists. virtual llvm::ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) = 0; + /// Get a \p File objct for the binary file at \p Path, if one exists. + /// This function should be called instead of openFileForRead if the file + /// should be opened as a binary file. + virtual llvm::ErrorOr<std::unique_ptr<File>> + openFileForReadBinary(const Twine &Path) { + return openFileForRead(Path); + } + /// This is a convenience method that opens a file, gets its content and then /// closes the file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(const Twine &Name, int64_t FileSize = -1, - bool RequiresNullTerminator = true, bool IsVolatile = false); + bool RequiresNullTerminator = true, bool IsVolatile = false, + bool IsText = true); /// Get a directory_iterator for \p Dir. /// \note The 'end' iterator is directory_iterator(). diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index 928c0b5a24ed65..ca2e1ab2c7de55 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -117,8 +117,9 @@ FileSystem::~FileSystem() = default; ErrorOr<std::unique_ptr<MemoryBuffer>> FileSystem::getBufferForFile(const llvm::Twine &Name, int64_t FileSize, - bool RequiresNullTerminator, bool IsVolatile) { - auto F = openFileForRead(Name); + bool RequiresNullTerminator, bool IsVolatile, + bool IsText) { + auto F = IsText ? openFileForRead(Name) : openFileForReadBinary(Name); if (!F) return F.getError(); @@ -279,6 +280,8 @@ class RealFileSystem : public FileSystem { ErrorOr<Status> status(const Twine &Path) override; ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; + ErrorOr<std::unique_ptr<File>> + openFileForReadBinary(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override; @@ -302,6 +305,17 @@ class RealFileSystem : public FileSystem { return Storage; } + ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Name, + sys::fs::OpenFlags Flags) { + SmallString<256> RealName, Storage; + Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead( + adjustPath(Name, Storage), Flags, &RealName); + if (!FDOrErr) + return errorToErrorCode(FDOrErr.takeError()); + return std::unique_ptr<File>( + new RealFile(*FDOrErr, Name.str(), RealName.str())); + } + struct WorkingDirectory { // The current working directory, without symlinks resolved. (echo $PWD). SmallString<128> Specified; @@ -324,13 +338,12 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) { ErrorOr<std::unique_ptr<File>> RealFileSystem::openFileForRead(const Twine &Name) { - SmallString<256> RealName, Storage; - Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead( - adjustPath(Name, Storage), sys::fs::OF_None, &RealName); - if (!FDOrErr) - return errorToErrorCode(FDOrErr.takeError()); - return std::unique_ptr<File>( - new RealFile(*FDOrErr, Name.str(), RealName.str())); + return openFileForRead(Name, sys::fs::OF_Text); +} + +ErrorOr<std::unique_ptr<File>> +RealFileSystem::openFileForReadBinary(const Twine &Name) { + return openFileForRead(Name, sys::fs::OF_None); } llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const { >From cdb399463920b24a1fa48f785597ffcaae0f14f0 Mon Sep 17 00:00:00 2001 From: Abhina Sreeskantharajan <abhina.sreeskanthara...@ibm.com> Date: Thu, 10 Oct 2024 16:29:09 -0400 Subject: [PATCH 2/3] address comments --- clang/include/clang/Basic/FileManager.h | 13 +++++++++---- clang/lib/Basic/FileManager.cpp | 4 ++-- clang/lib/Lex/HeaderMap.cpp | 3 ++- clang/lib/Serialization/ASTReader.cpp | 1 + llvm/include/llvm/Support/VirtualFileSystem.h | 10 +++++++--- llvm/lib/Support/VirtualFileSystem.cpp | 8 ++++---- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index d987fb05a94a37..7a26c65379ac67 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -290,14 +290,19 @@ class FileManager : public RefCountedBase<FileManager> { /// Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. + /// The IsText parameter controls whether the file should be opened as a text + /// or binary file, and should be set to false if the file contents should be + /// treated as binary. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(FileEntryRef Entry, bool isVolatile = false, - bool RequiresNullTerminator = true, bool IsText = true, - std::optional<int64_t> MaybeLimit = std::nullopt); + bool RequiresNullTerminator = true, + std::optional<int64_t> MaybeLimit = std::nullopt, + bool IsText = true); llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(StringRef Filename, bool isVolatile = false, - bool RequiresNullTerminator = true, bool IsText = true, - std::optional<int64_t> MaybeLimit = std::nullopt) const { + bool RequiresNullTerminator = true, + std::optional<int64_t> MaybeLimit = std::nullopt, + bool IsText = true) const { return getBufferForFileImpl(Filename, /*FileSize=*/MaybeLimit.value_or(-1), isVolatile, RequiresNullTerminator, IsText); diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index 27075cefafdc2f..eb91ec042e1d06 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -530,8 +530,8 @@ void FileManager::fillRealPathName(FileEntry *UFE, llvm::StringRef FileName) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileManager::getBufferForFile(FileEntryRef FE, bool isVolatile, - bool RequiresNullTerminator, bool IsText, - std::optional<int64_t> MaybeLimit) { + bool RequiresNullTerminator, + std::optional<int64_t> MaybeLimit, bool IsText) { const FileEntry *Entry = &FE.getFileEntry(); // If the content is living on the file entry, return a reference to it. if (Entry->Content) diff --git a/clang/lib/Lex/HeaderMap.cpp b/clang/lib/Lex/HeaderMap.cpp index 35c68b304a4523..b04f67a4b2ed3c 100644 --- a/clang/lib/Lex/HeaderMap.cpp +++ b/clang/lib/Lex/HeaderMap.cpp @@ -56,7 +56,8 @@ std::unique_ptr<HeaderMap> HeaderMap::Create(FileEntryRef FE, FileManager &FM) { auto FileBuffer = FM.getBufferForFile(FE, /*IsVolatile=*/false, - /*RequiresNullTerminator=*/true, /*IsText=*/false); + /*RequiresNullTerminator=*/true, + /*MaybeList=*/std::nullopt, /*IsText=*/false); if (!FileBuffer || !*FileBuffer) return nullptr; bool NeedsByteSwap; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 769b85dc318072..954bdf207d1725 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -5334,6 +5334,7 @@ std::string ASTReader::getOriginalSourceFile( // Open the AST file. auto Buffer = FileMgr.getBufferForFile(ASTFileName, /*IsVolatile=*/false, /*RequiresNullTerminator=*/false, + /*MaybeLimit=*/std::nullopt, /*IsText=*/false); if (!Buffer) { Diags.Report(diag::err_fe_unable_to_read_pch_file) diff --git a/llvm/include/llvm/Support/VirtualFileSystem.h b/llvm/include/llvm/Support/VirtualFileSystem.h index a94e285a806f2c..1358e880942a1c 100644 --- a/llvm/include/llvm/Support/VirtualFileSystem.h +++ b/llvm/include/llvm/Support/VirtualFileSystem.h @@ -275,9 +275,11 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem>, virtual llvm::ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) = 0; - /// Get a \p File objct for the binary file at \p Path, if one exists. - /// This function should be called instead of openFileForRead if the file - /// should be opened as a binary file. + /// Get a \p File object for the binary file at \p Path, if one exists. + /// Some non-ascii based file systems perform encoding conversions + /// when reading as a text file, and this function should be used if + /// a file's bytes should be read as-is. On most filesystems, this + /// is the same behaviour as openFileForRead. virtual llvm::ErrorOr<std::unique_ptr<File>> openFileForReadBinary(const Twine &Path) { return openFileForRead(Path); @@ -285,6 +287,8 @@ class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem>, /// This is a convenience method that opens a file, gets its content and then /// closes the file. + /// The IsText parameter is used to distinguish whether the file should be + /// opened as a binary or text file. llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> getBufferForFile(const Twine &Name, int64_t FileSize = -1, bool RequiresNullTerminator = true, bool IsVolatile = false, diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp index ca2e1ab2c7de55..4feb41554fc3c7 100644 --- a/llvm/lib/Support/VirtualFileSystem.cpp +++ b/llvm/lib/Support/VirtualFileSystem.cpp @@ -305,8 +305,8 @@ class RealFileSystem : public FileSystem { return Storage; } - ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Name, - sys::fs::OpenFlags Flags) { + ErrorOr<std::unique_ptr<File>> + openFileForReadWithFlags(const Twine &Name, sys::fs::OpenFlags Flags) { SmallString<256> RealName, Storage; Expected<file_t> FDOrErr = sys::fs::openNativeFileForRead( adjustPath(Name, Storage), Flags, &RealName); @@ -338,12 +338,12 @@ ErrorOr<Status> RealFileSystem::status(const Twine &Path) { ErrorOr<std::unique_ptr<File>> RealFileSystem::openFileForRead(const Twine &Name) { - return openFileForRead(Name, sys::fs::OF_Text); + return openFileForReadWithFlags(Name, sys::fs::OF_Text); } ErrorOr<std::unique_ptr<File>> RealFileSystem::openFileForReadBinary(const Twine &Name) { - return openFileForRead(Name, sys::fs::OF_None); + return openFileForReadWithFlags(Name, sys::fs::OF_None); } llvm::ErrorOr<std::string> RealFileSystem::getCurrentWorkingDirectory() const { >From ba038a6cb316c8325b101bc9c355b3af8f0d3a00 Mon Sep 17 00:00:00 2001 From: Abhina Sreeskantharajan <abhina.sreeskanthara...@ibm.com> Date: Fri, 11 Oct 2024 11:52:40 -0400 Subject: [PATCH 3/3] Pass IsText from getFileRef to open files as binary for #embed and add testcase for zos --- clang/include/clang/Basic/FileManager.h | 6 +- .../include/clang/Basic/FileSystemStatCache.h | 8 +- clang/lib/Basic/FileManager.cpp | 22 ++-- clang/lib/Basic/FileSystemStatCache.cpp | 14 ++- clang/lib/Lex/PPDirectives.cpp | 16 +-- clang/test/Preprocessor/embed_zos.c | 108 ++++++++++++++++++ 6 files changed, 145 insertions(+), 29 deletions(-) create mode 100644 clang/test/Preprocessor/embed_zos.c diff --git a/clang/include/clang/Basic/FileManager.h b/clang/include/clang/Basic/FileManager.h index 7a26c65379ac67..785b2acb6000e2 100644 --- a/clang/include/clang/Basic/FileManager.h +++ b/clang/include/clang/Basic/FileManager.h @@ -125,7 +125,8 @@ class FileManager : public RefCountedBase<FileManager> { std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status, bool isFile, - std::unique_ptr<llvm::vfs::File> *F); + bool isFile, std::unique_ptr<llvm::vfs::File> *F, + bool IsText = true); /// Add all ancestors of the given path (pointing to either a file /// or a directory) as virtual directories. @@ -230,7 +231,8 @@ class FileManager : public RefCountedBase<FileManager> { /// the failure to find this file. llvm::Expected<FileEntryRef> getFileRef(StringRef Filename, bool OpenFile = false, - bool CacheFailure = true); + bool CacheFailure = true, + bool IsText = true); /// Get the FileEntryRef for stdin, returning an error if stdin cannot be /// read. diff --git a/clang/include/clang/Basic/FileSystemStatCache.h b/clang/include/clang/Basic/FileSystemStatCache.h index 5a003a748178d3..73c256a0169712 100644 --- a/clang/include/clang/Basic/FileSystemStatCache.h +++ b/clang/include/clang/Basic/FileSystemStatCache.h @@ -48,10 +48,10 @@ class FileSystemStatCache { /// success for directories (not files). On a successful file lookup, the /// implementation can optionally fill in \p F with a valid \p File object and /// the client guarantees that it will close it. - static std::error_code - get(StringRef Path, llvm::vfs::Status &Status, bool isFile, - std::unique_ptr<llvm::vfs::File> *F, - FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS); + static std::error_code get(StringRef Path, llvm::vfs::Status &Status, + bool isFile, std::unique_ptr<llvm::vfs::File> *F, + FileSystemStatCache *Cache, + llvm::vfs::FileSystem &FS, bool IsText = true); protected: // FIXME: The pointer here is a non-owning/optional reference to the diff --git a/clang/lib/Basic/FileManager.cpp b/clang/lib/Basic/FileManager.cpp index eb91ec042e1d06..2876c290a26b13 100644 --- a/clang/lib/Basic/FileManager.cpp +++ b/clang/lib/Basic/FileManager.cpp @@ -212,8 +212,10 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) { return llvm::errorToErrorCode(Result.takeError()); } -llvm::Expected<FileEntryRef> -FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { +llvm::Expected<FileEntryRef> FileManager::getFileRef(StringRef Filename, + bool openFile, + bool CacheFailure, + bool IsText) { ++NumFileLookups; // See if there is already an entry in the map. @@ -259,7 +261,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) { std::unique_ptr<llvm::vfs::File> F; llvm::vfs::Status Status; auto statError = getStatValue(InterndFileName, Status, true, - openFile ? &F : nullptr); + openFile ? &F : nullptr, IsText); if (statError) { // There's no real file at the given path. if (CacheFailure) @@ -580,20 +582,22 @@ FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize, /// if the path points to a virtual file or does not exist, or returns /// false if it's an existent real file. If FileDescriptor is NULL, /// do directory look-up instead of file look-up. -std::error_code -FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status, - bool isFile, std::unique_ptr<llvm::vfs::File> *F) { +std::error_code FileManager::getStatValue(StringRef Path, + llvm::vfs::Status &Status, + bool isFile, + std::unique_ptr<llvm::vfs::File> *F, + bool IsText) { // FIXME: FileSystemOpts shouldn't be passed in here, all paths should be // absolute! if (FileSystemOpts.WorkingDir.empty()) - return FileSystemStatCache::get(Path, Status, isFile, F, - StatCache.get(), *FS); + return FileSystemStatCache::get(Path, Status, isFile, F, StatCache.get(), + *FS, IsText); SmallString<128> FilePath(Path); FixupRelativePath(FilePath); return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F, - StatCache.get(), *FS); + StatCache.get(), *FS, IsText); } std::error_code diff --git a/clang/lib/Basic/FileSystemStatCache.cpp b/clang/lib/Basic/FileSystemStatCache.cpp index 415a4e2025df84..183eea09866377 100644 --- a/clang/lib/Basic/FileSystemStatCache.cpp +++ b/clang/lib/Basic/FileSystemStatCache.cpp @@ -30,11 +30,12 @@ void FileSystemStatCache::anchor() {} /// success for directories (not files). On a successful file lookup, the /// implementation can optionally fill in FileDescriptor with a valid /// descriptor and the client guarantees that it will close it. -std::error_code -FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status, - bool isFile, std::unique_ptr<llvm::vfs::File> *F, - FileSystemStatCache *Cache, - llvm::vfs::FileSystem &FS) { +std::error_code FileSystemStatCache::get(StringRef Path, + llvm::vfs::Status &Status, bool isFile, + std::unique_ptr<llvm::vfs::File> *F, + FileSystemStatCache *Cache, + llvm::vfs::FileSystem &FS, + bool IsText) { bool isForDir = !isFile; std::error_code RetCode; @@ -58,7 +59,8 @@ FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status, // // Because of this, check to see if the file exists with 'open'. If the // open succeeds, use fstat to get the stat info. - auto OwnedFile = FS.openFileForRead(Path); + auto OwnedFile = + IsText ? FS.openFileForRead(Path) : FS.openFileForReadBinary(Path); if (!OwnedFile) { // If the open fails, our "stat" fails. diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 4e77df9ec444c7..8e7d80aa8911c8 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1080,8 +1080,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, FileManager &FM = this->getFileManager(); if (llvm::sys::path::is_absolute(Filename)) { // lookup path or immediately fail - llvm::Expected<FileEntryRef> ShouldBeEntry = - FM.getFileRef(Filename, OpenFile); + llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef( + Filename, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); return llvm::expectedToOptional(std::move(ShouldBeEntry)); } @@ -1107,8 +1107,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, StringRef FullFileDir = LookupFromFile->tryGetRealPathName(); if (!FullFileDir.empty()) { SeparateComponents(LookupPath, FullFileDir, Filename, true); - llvm::Expected<FileEntryRef> ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); @@ -1123,8 +1123,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, StringRef WorkingDir = WorkingDirEntry.getName(); if (!WorkingDir.empty()) { SeparateComponents(LookupPath, WorkingDir, Filename, false); - llvm::Expected<FileEntryRef> ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); @@ -1135,8 +1135,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile, for (const auto &Entry : PPOpts->EmbedEntries) { LookupPath.clear(); SeparateComponents(LookupPath, Entry, Filename, false); - llvm::Expected<FileEntryRef> ShouldBeEntry = - FM.getFileRef(LookupPath, OpenFile); + llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef( + LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false); if (ShouldBeEntry) return llvm::expectedToOptional(std::move(ShouldBeEntry)); llvm::consumeError(ShouldBeEntry.takeError()); diff --git a/clang/test/Preprocessor/embed_zos.c b/clang/test/Preprocessor/embed_zos.c new file mode 100644 index 00000000000000..8dfeb3cd6e2432 --- /dev/null +++ b/clang/test/Preprocessor/embed_zos.c @@ -0,0 +1,108 @@ +// RUN: rm -rf %t +// RUN: mkdir -p %t/media && cp %S/Inputs/media/art.txt %t/media/ +// RUN: chtag -r %t/media/art.txt +// RUN: %clang_cc1 -std=c23 %s -fsyntax-only --embed-dir=%t -verify +// expected-no-diagnostics + +// REQUIRES: system-zos +const char data[] = { +#embed <media/art.txt> +}; +const char data2[] = { +#embed <media/art.txt> +, 0 +}; +const char data3[] = { +#embed <media/art.txt> suffix(, 0) +}; +const char data4[] = { +#embed <media/art.txt> suffix(,) +0 +}; +static_assert(sizeof(data) == 274); +static_assert(' ' == data[0]); +static_assert('_' == data[11]); +static_assert('\n' == data[273]); +static_assert(sizeof(data2) == 275); +static_assert(' ' == data2[0]); +static_assert('_' == data2[11]); +static_assert('\n' == data2[273]); +static_assert('\0' == data2[274]); +static_assert(sizeof(data3) == 275); +static_assert(' ' == data3[0]); +static_assert('_' == data3[11]); +static_assert('\n' == data3[273]); +static_assert('\0' == data3[274]); +static_assert(sizeof(data4) == 275); +static_assert(' ' == data4[0]); +static_assert('_' == data4[11]); +static_assert('\n' == data4[273]); +static_assert('\0' == data4[274]); + +const signed char data5[] = { +#embed <media/art.txt> +}; +const signed char data6[] = { +#embed <media/art.txt> +, 0 +}; +const signed char data7[] = { +#embed <media/art.txt> suffix(, 0) +}; +const signed char data8[] = { +#embed <media/art.txt> suffix(,) +0 +}; +static_assert(sizeof(data5) == 274); +static_assert(' ' == data5[0]); +static_assert('_' == data5[11]); +static_assert('\n' == data5[273]); +static_assert(sizeof(data6) == 275); +static_assert(' ' == data6[0]); +static_assert('_' == data6[11]); +static_assert('\n' == data6[273]); +static_assert('\0' == data6[274]); +static_assert(sizeof(data7) == 275); +static_assert(' ' == data7[0]); +static_assert('_' == data7[11]); +static_assert('\n' == data7[273]); +static_assert('\0' == data7[274]); +static_assert(sizeof(data8) == 275); +static_assert(' ' == data8[0]); +static_assert('_' == data8[11]); +static_assert('\n' == data8[273]); +static_assert('\0' == data8[274]); + +const unsigned char data9[] = { +#embed <media/art.txt> +}; +const unsigned char data10[] = { +0, +#embed <media/art.txt> +}; +const unsigned char data11[] = { +#embed <media/art.txt> prefix(0,) +}; +const unsigned char data12[] = { +0 +#embed <media/art.txt> prefix(,) +}; +static_assert(sizeof(data9) == 274); +static_assert(' ' == data9[0]); +static_assert('_' == data9[11]); +static_assert('\n' == data9[273]); +static_assert(sizeof(data10) == 275); +static_assert(' ' == data10[1]); +static_assert('_' == data10[12]); +static_assert('\n' == data10[274]); +static_assert('\0' == data10[0]); +static_assert(sizeof(data11) == 275); +static_assert(' ' == data11[1]); +static_assert('_' == data11[12]); +static_assert('\n' == data11[274]); +static_assert('\0' == data11[0]); +static_assert(sizeof(data12) == 275); +static_assert(' ' == data12[1]); +static_assert('_' == data12[12]); +static_assert('\n' == data12[274]); +static_assert('\0' == data12[0]); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits