Skip to content

Commit b546492

Browse files
committed
Pass IsText from getFileRef to open files as binary for #embed and add testcase for zos
1 parent cdb3994 commit b546492

File tree

6 files changed

+146
-30
lines changed

6 files changed

+146
-30
lines changed

clang/include/clang/Basic/FileManager.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ class FileManager : public RefCountedBase<FileManager> {
124124
std::unique_ptr<FileSystemStatCache> StatCache;
125125

126126
std::error_code getStatValue(StringRef Path, llvm::vfs::Status &Status,
127-
bool isFile,
128-
std::unique_ptr<llvm::vfs::File> *F);
127+
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
128+
bool IsText = true);
129129

130130
/// Add all ancestors of the given path (pointing to either a file
131131
/// or a directory) as virtual directories.
@@ -230,7 +230,8 @@ class FileManager : public RefCountedBase<FileManager> {
230230
/// the failure to find this file.
231231
llvm::Expected<FileEntryRef> getFileRef(StringRef Filename,
232232
bool OpenFile = false,
233-
bool CacheFailure = true);
233+
bool CacheFailure = true,
234+
bool IsText = true);
234235

235236
/// Get the FileEntryRef for stdin, returning an error if stdin cannot be
236237
/// read.

clang/include/clang/Basic/FileSystemStatCache.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ class FileSystemStatCache {
4848
/// success for directories (not files). On a successful file lookup, the
4949
/// implementation can optionally fill in \p F with a valid \p File object and
5050
/// the client guarantees that it will close it.
51-
static std::error_code
52-
get(StringRef Path, llvm::vfs::Status &Status, bool isFile,
53-
std::unique_ptr<llvm::vfs::File> *F,
54-
FileSystemStatCache *Cache, llvm::vfs::FileSystem &FS);
51+
static std::error_code get(StringRef Path, llvm::vfs::Status &Status,
52+
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
53+
FileSystemStatCache *Cache,
54+
llvm::vfs::FileSystem &FS, bool IsText = true);
5555

5656
protected:
5757
// FIXME: The pointer here is a non-owning/optional reference to the

clang/lib/Basic/FileManager.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,10 @@ FileManager::getFile(StringRef Filename, bool openFile, bool CacheFailure) {
212212
return llvm::errorToErrorCode(Result.takeError());
213213
}
214214

215-
llvm::Expected<FileEntryRef>
216-
FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
215+
llvm::Expected<FileEntryRef> FileManager::getFileRef(StringRef Filename,
216+
bool openFile,
217+
bool CacheFailure,
218+
bool IsText) {
217219
++NumFileLookups;
218220

219221
// See if there is already an entry in the map.
@@ -259,7 +261,7 @@ FileManager::getFileRef(StringRef Filename, bool openFile, bool CacheFailure) {
259261
std::unique_ptr<llvm::vfs::File> F;
260262
llvm::vfs::Status Status;
261263
auto statError = getStatValue(InterndFileName, Status, true,
262-
openFile ? &F : nullptr);
264+
openFile ? &F : nullptr, IsText);
263265
if (statError) {
264266
// There's no real file at the given path.
265267
if (CacheFailure)
@@ -580,20 +582,22 @@ FileManager::getBufferForFileImpl(StringRef Filename, int64_t FileSize,
580582
/// if the path points to a virtual file or does not exist, or returns
581583
/// false if it's an existent real file. If FileDescriptor is NULL,
582584
/// do directory look-up instead of file look-up.
583-
std::error_code
584-
FileManager::getStatValue(StringRef Path, llvm::vfs::Status &Status,
585-
bool isFile, std::unique_ptr<llvm::vfs::File> *F) {
585+
std::error_code FileManager::getStatValue(StringRef Path,
586+
llvm::vfs::Status &Status,
587+
bool isFile,
588+
std::unique_ptr<llvm::vfs::File> *F,
589+
bool IsText) {
586590
// FIXME: FileSystemOpts shouldn't be passed in here, all paths should be
587591
// absolute!
588592
if (FileSystemOpts.WorkingDir.empty())
589-
return FileSystemStatCache::get(Path, Status, isFile, F,
590-
StatCache.get(), *FS);
593+
return FileSystemStatCache::get(Path, Status, isFile, F, StatCache.get(),
594+
*FS, IsText);
591595

592596
SmallString<128> FilePath(Path);
593597
FixupRelativePath(FilePath);
594598

595599
return FileSystemStatCache::get(FilePath.c_str(), Status, isFile, F,
596-
StatCache.get(), *FS);
600+
StatCache.get(), *FS, IsText);
597601
}
598602

599603
std::error_code

clang/lib/Basic/FileSystemStatCache.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ void FileSystemStatCache::anchor() {}
3030
/// success for directories (not files). On a successful file lookup, the
3131
/// implementation can optionally fill in FileDescriptor with a valid
3232
/// descriptor and the client guarantees that it will close it.
33-
std::error_code
34-
FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status,
35-
bool isFile, std::unique_ptr<llvm::vfs::File> *F,
36-
FileSystemStatCache *Cache,
37-
llvm::vfs::FileSystem &FS) {
33+
std::error_code FileSystemStatCache::get(StringRef Path,
34+
llvm::vfs::Status &Status, bool isFile,
35+
std::unique_ptr<llvm::vfs::File> *F,
36+
FileSystemStatCache *Cache,
37+
llvm::vfs::FileSystem &FS,
38+
bool IsText) {
3839
bool isForDir = !isFile;
3940
std::error_code RetCode;
4041

@@ -58,7 +59,8 @@ FileSystemStatCache::get(StringRef Path, llvm::vfs::Status &Status,
5859
//
5960
// Because of this, check to see if the file exists with 'open'. If the
6061
// open succeeds, use fstat to get the stat info.
61-
auto OwnedFile = FS.openFileForRead(Path);
62+
auto OwnedFile =
63+
IsText ? FS.openFileForRead(Path) : FS.openFileForReadBinary(Path);
6264

6365
if (!OwnedFile) {
6466
// If the open fails, our "stat" fails.

clang/lib/Lex/PPDirectives.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
10801080
FileManager &FM = this->getFileManager();
10811081
if (llvm::sys::path::is_absolute(Filename)) {
10821082
// lookup path or immediately fail
1083-
llvm::Expected<FileEntryRef> ShouldBeEntry =
1084-
FM.getFileRef(Filename, OpenFile);
1083+
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
1084+
Filename, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
10851085
return llvm::expectedToOptional(std::move(ShouldBeEntry));
10861086
}
10871087

@@ -1107,8 +1107,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
11071107
StringRef FullFileDir = LookupFromFile->tryGetRealPathName();
11081108
if (!FullFileDir.empty()) {
11091109
SeparateComponents(LookupPath, FullFileDir, Filename, true);
1110-
llvm::Expected<FileEntryRef> ShouldBeEntry =
1111-
FM.getFileRef(LookupPath, OpenFile);
1110+
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
1111+
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
11121112
if (ShouldBeEntry)
11131113
return llvm::expectedToOptional(std::move(ShouldBeEntry));
11141114
llvm::consumeError(ShouldBeEntry.takeError());
@@ -1123,8 +1123,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
11231123
StringRef WorkingDir = WorkingDirEntry.getName();
11241124
if (!WorkingDir.empty()) {
11251125
SeparateComponents(LookupPath, WorkingDir, Filename, false);
1126-
llvm::Expected<FileEntryRef> ShouldBeEntry =
1127-
FM.getFileRef(LookupPath, OpenFile);
1126+
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
1127+
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
11281128
if (ShouldBeEntry)
11291129
return llvm::expectedToOptional(std::move(ShouldBeEntry));
11301130
llvm::consumeError(ShouldBeEntry.takeError());
@@ -1135,8 +1135,8 @@ Preprocessor::LookupEmbedFile(StringRef Filename, bool isAngled, bool OpenFile,
11351135
for (const auto &Entry : PPOpts->EmbedEntries) {
11361136
LookupPath.clear();
11371137
SeparateComponents(LookupPath, Entry, Filename, false);
1138-
llvm::Expected<FileEntryRef> ShouldBeEntry =
1139-
FM.getFileRef(LookupPath, OpenFile);
1138+
llvm::Expected<FileEntryRef> ShouldBeEntry = FM.getFileRef(
1139+
LookupPath, OpenFile, /*CacheFailure=*/true, /*IsText=*/false);
11401140
if (ShouldBeEntry)
11411141
return llvm::expectedToOptional(std::move(ShouldBeEntry));
11421142
llvm::consumeError(ShouldBeEntry.takeError());

clang/test/Preprocessor/embed_zos.c

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t/media && cp %S/Inputs/media/art.txt %t/media/
3+
// RUN: chtag -r %t/media/art.txt
4+
// RUN: %clang_cc1 -std=c23 %s -fsyntax-only --embed-dir=%t -verify
5+
// expected-no-diagnostics
6+
7+
// REQUIRES: shell, system-zos
8+
9+
const char data[] = {
10+
#embed <media/art.txt>
11+
};
12+
const char data2[] = {
13+
#embed <media/art.txt>
14+
, 0
15+
};
16+
const char data3[] = {
17+
#embed <media/art.txt> suffix(, 0)
18+
};
19+
const char data4[] = {
20+
#embed <media/art.txt> suffix(,)
21+
0
22+
};
23+
static_assert(sizeof(data) == 274);
24+
static_assert(' ' == data[0]);
25+
static_assert('_' == data[11]);
26+
static_assert('\n' == data[273]);
27+
static_assert(sizeof(data2) == 275);
28+
static_assert(' ' == data2[0]);
29+
static_assert('_' == data2[11]);
30+
static_assert('\n' == data2[273]);
31+
static_assert('\0' == data2[274]);
32+
static_assert(sizeof(data3) == 275);
33+
static_assert(' ' == data3[0]);
34+
static_assert('_' == data3[11]);
35+
static_assert('\n' == data3[273]);
36+
static_assert('\0' == data3[274]);
37+
static_assert(sizeof(data4) == 275);
38+
static_assert(' ' == data4[0]);
39+
static_assert('_' == data4[11]);
40+
static_assert('\n' == data4[273]);
41+
static_assert('\0' == data4[274]);
42+
43+
const signed char data5[] = {
44+
#embed <media/art.txt>
45+
};
46+
const signed char data6[] = {
47+
#embed <media/art.txt>
48+
, 0
49+
};
50+
const signed char data7[] = {
51+
#embed <media/art.txt> suffix(, 0)
52+
};
53+
const signed char data8[] = {
54+
#embed <media/art.txt> suffix(,)
55+
0
56+
};
57+
static_assert(sizeof(data5) == 274);
58+
static_assert(' ' == data5[0]);
59+
static_assert('_' == data5[11]);
60+
static_assert('\n' == data5[273]);
61+
static_assert(sizeof(data6) == 275);
62+
static_assert(' ' == data6[0]);
63+
static_assert('_' == data6[11]);
64+
static_assert('\n' == data6[273]);
65+
static_assert('\0' == data6[274]);
66+
static_assert(sizeof(data7) == 275);
67+
static_assert(' ' == data7[0]);
68+
static_assert('_' == data7[11]);
69+
static_assert('\n' == data7[273]);
70+
static_assert('\0' == data7[274]);
71+
static_assert(sizeof(data8) == 275);
72+
static_assert(' ' == data8[0]);
73+
static_assert('_' == data8[11]);
74+
static_assert('\n' == data8[273]);
75+
static_assert('\0' == data8[274]);
76+
77+
const unsigned char data9[] = {
78+
#embed <media/art.txt>
79+
};
80+
const unsigned char data10[] = {
81+
0,
82+
#embed <media/art.txt>
83+
};
84+
const unsigned char data11[] = {
85+
#embed <media/art.txt> prefix(0,)
86+
};
87+
const unsigned char data12[] = {
88+
0
89+
#embed <media/art.txt> prefix(,)
90+
};
91+
static_assert(sizeof(data9) == 274);
92+
static_assert(' ' == data9[0]);
93+
static_assert('_' == data9[11]);
94+
static_assert('\n' == data9[273]);
95+
static_assert(sizeof(data10) == 275);
96+
static_assert(' ' == data10[1]);
97+
static_assert('_' == data10[12]);
98+
static_assert('\n' == data10[274]);
99+
static_assert('\0' == data10[0]);
100+
static_assert(sizeof(data11) == 275);
101+
static_assert(' ' == data11[1]);
102+
static_assert('_' == data11[12]);
103+
static_assert('\n' == data11[274]);
104+
static_assert('\0' == data11[0]);
105+
static_assert(sizeof(data12) == 275);
106+
static_assert(' ' == data12[1]);
107+
static_assert('_' == data12[12]);
108+
static_assert('\n' == data12[274]);
109+
static_assert('\0' == data12[0]);

0 commit comments

Comments
 (0)