--- /dev/null
+// If response file does not exist, '@file; directive remains unexpanded in
+// command line.
+//
+// RUN: %clang @%S/Inputs/inexistent.rsp -### 2>&1 | FileCheck --check-prefix=INEXISTENT %s
+// INEXISTENT: @{{.*}}Inputs/inexistent.rsp
+
+// As the above case but '@file' is in response file.
+//
+// RUN: %clang @%S/Inputs/inc-inexistent.rsp -### 2>&1 | FileCheck --check-prefix=INEXISTENT2 %s
+// INEXISTENT2: @{{.*}}inexistent.txt
+
+// If file in `@file` is a directory, it is an error.
+//
+// RUN: not %clang @%S/Inputs -### 2>&1 | FileCheck --check-prefix=DIRECTORY %s
+// DIRECTORY: cannot not open file '{{.*}}Inputs': {{[Ii]}}s a directory
assert(sys::path::is_absolute(FName));
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
FS->getBufferForFile(FName);
- if (!MemBufOrErr)
- return llvm::createStringError(
- MemBufOrErr.getError(), Twine("cannot not open file '") + FName + "'");
+ if (!MemBufOrErr) {
+ std::error_code EC = MemBufOrErr.getError();
+ return llvm::createStringError(EC, Twine("cannot not open file '") + FName +
+ "': " + EC.message());
+ }
MemoryBuffer &MemBuf = *MemBufOrErr.get();
StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
if (auto CWD = FS->getCurrentWorkingDirectory()) {
CurrDir = *CWD;
} else {
- return make_error<StringError>(
+ return createStringError(
CWD.getError(), Twine("cannot get absolute path for: ") + FName);
}
} else {
llvm::sys::path::append(CurrDir, FName);
FName = CurrDir.c_str();
}
+
+ ErrorOr<llvm::vfs::Status> Res = FS->status(FName);
+ if (!Res || !Res->exists()) {
+ std::error_code EC = Res.getError();
+ if (!InConfigFile) {
+ // If the specified file does not exist, leave '@file' unexpanded, as
+ // libiberty does.
+ if (!EC || EC == llvm::errc::no_such_file_or_directory) {
+ ++I;
+ continue;
+ }
+ }
+ if (!EC)
+ EC = llvm::errc::no_such_file_or_directory;
+ return createStringError(EC, Twine("cannot not open file '") + FName +
+ "': " + EC.message());
+ }
+ const llvm::vfs::Status &FileStatus = Res.get();
+
auto IsEquivalent =
- [FName, this](const ResponseFileRecord &RFile) -> ErrorOr<bool> {
- ErrorOr<llvm::vfs::Status> LHS = FS->status(FName);
- if (!LHS)
- return LHS.getError();
+ [FileStatus, this](const ResponseFileRecord &RFile) -> ErrorOr<bool> {
ErrorOr<llvm::vfs::Status> RHS = FS->status(RFile.File);
if (!RHS)
return RHS.getError();
- return LHS->equivalent(*RHS);
+ return FileStatus.equivalent(*RHS);
};
// Check for recursive response files.
for (const auto &F : drop_begin(FileStack)) {
if (ErrorOr<bool> R = IsEquivalent(F)) {
if (R.get())
- return make_error<StringError>(
- Twine("recursive expansion of: '") + F.File + "'", R.getError());
+ return createStringError(
+ R.getError(), Twine("recursive expansion of: '") + F.File + "'");
} else {
- return make_error<StringError>(Twine("cannot open file: ") + F.File,
- R.getError());
+ return createStringError(R.getError(),
+ Twine("cannot open file: ") + F.File);
}
}
// Replace this response file argument with the tokenization of its
// contents. Nested response files are expanded in subsequent iterations.
SmallVector<const char *, 0> ExpandedArgv;
- if (!InConfigFile) {
- // If the specified file does not exist, leave '@file' unexpanded, as
- // libiberty does.
- ErrorOr<llvm::vfs::Status> Res = FS->status(FName);
- if (!Res) {
- std::error_code EC = Res.getError();
- if (EC == llvm::errc::no_such_file_or_directory) {
- ++I;
- continue;
- }
- } else {
- if (!Res->exists()) {
- ++I;
- continue;
- }
- }
- }
if (Error Err = expandResponseFile(FName, ExpandedArgv))
return Err;