Skip to content

Commit 9d21f74

Browse files
committed
[llvm][clang] Pass VFS to llvm::cl command line handling (llvm#159174)
This PR passes the VFS down to `llvm::cl` functions so that they don't assume the real file system.
1 parent 5a4f55c commit 9d21f74

File tree

12 files changed

+54
-39
lines changed

12 files changed

+54
-39
lines changed

clang-tools-extra/clangd/tool/ClangdMain.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -775,8 +775,8 @@ It should be used via an editor plugin rather than invoked directly. For more in
775775
clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable.
776776
)";
777777
llvm::cl::HideUnrelatedOptions(ClangdCategories);
778-
llvm::cl::ParseCommandLineOptions(argc, argv, Overview,
779-
/*Errs=*/nullptr, FlagsEnvVar);
778+
llvm::cl::ParseCommandLineOptions(argc, argv, Overview, /*Errs=*/nullptr,
779+
/*VFS=*/nullptr, FlagsEnvVar);
780780
if (Test) {
781781
if (!Sync.getNumOccurrences())
782782
Sync = true;

clang/lib/CodeGen/BackendUtil.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ getInstrProfOptions(const CodeGenOptions &CodeGenOpts,
579579
return Options;
580580
}
581581

582-
static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
582+
static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts,
583+
vfs::FileSystem &VFS) {
583584
SmallVector<const char *, 16> BackendArgs;
584585
BackendArgs.push_back("clang"); // Fake program name.
585586
if (!CodeGenOpts.DebugPass.empty()) {
@@ -599,8 +600,9 @@ static void setCommandLineOpts(const CodeGenOptions &CodeGenOpts) {
599600
// FIXME: The command line parser below is not thread-safe and shares a global
600601
// state, so this call might crash or overwrite the options of another Clang
601602
// instance in the same process.
602-
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1,
603-
BackendArgs.data());
603+
llvm::cl::ParseCommandLineOptions(BackendArgs.size() - 1, BackendArgs.data(),
604+
/*Overview=*/"", /*Errs=*/nullptr,
605+
/*VFS=*/&VFS);
604606
}
605607

606608
void EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
@@ -1294,7 +1296,7 @@ void EmitAssemblyHelper::emitAssembly(BackendAction Action,
12941296
std::unique_ptr<raw_pwrite_stream> OS,
12951297
std::unique_ptr<raw_pwrite_stream> CasIDOS,
12961298
BackendConsumer *BC) {
1297-
setCommandLineOpts(CodeGenOpts);
1299+
setCommandLineOpts(CodeGenOpts, CI.getVirtualFileSystem());
12981300

12991301
bool RequiresCodeGen = actionRequiresCodeGen(Action);
13001302
CreateTargetMachine(RequiresCodeGen);
@@ -1331,7 +1333,7 @@ runThinLTOBackend(CompilerInstance &CI, ModuleSummaryIndex *CombinedIndex,
13311333
ModuleToDefinedGVSummaries;
13321334
CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries);
13331335

1334-
setCommandLineOpts(CGOpts);
1336+
setCommandLineOpts(CGOpts, CI.getVirtualFileSystem());
13351337

13361338
// We can simply import the values mentioned in the combined index, since
13371339
// we should only invoke this using the individual indexes written out

clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,9 @@ bool ExecuteCompilerInvocation(CompilerInstance *Clang) {
260260
for (unsigned i = 0; i != NumArgs; ++i)
261261
Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
262262
Args[NumArgs + 1] = nullptr;
263-
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
263+
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"",
264+
/*Errs=*/nullptr,
265+
/*VFS=*/&Clang->getVirtualFileSystem());
264266
}
265267

266268
#if CLANG_ENABLE_STATIC_ANALYZER

clang/tools/driver/cc1as_main.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,8 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
685685
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
686686
DiagnosticsEngine Diags(DiagID, DiagOpts, DiagClient);
687687

688+
auto VFS = vfs::getRealFileSystem();
689+
688690
// Set an error handler, so that any LLVM backend diagnostics go through our
689691
// error handler.
690692
ScopedFatalErrorHandler FatalErrorHandler
@@ -723,7 +725,8 @@ int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
723725
for (unsigned i = 0; i != NumArgs; ++i)
724726
Args[i + 1] = Asm.LLVMArgs[i].c_str();
725727
Args[NumArgs + 1] = nullptr;
726-
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get());
728+
llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get(), /*Overview=*/"",
729+
/*Errs=*/nullptr, /*VFS=*/VFS.get());
727730
}
728731

729732
// Execute the invocation, unless there were parsing errors.

clang/tools/driver/driver.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,17 @@ static void FixupDiagPrefixExeName(TextDiagnosticPrinter *DiagClient,
217217
}
218218

219219
static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV,
220-
const llvm::ToolContext &ToolContext) {
220+
const llvm::ToolContext &ToolContext,
221+
IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) {
221222
// If we call the cc1 tool from the clangDriver library (through
222223
// Driver::CC1Main), we need to clean up the options usage count. The options
223224
// are currently global, and they might have been used previously by the
224225
// driver.
225226
llvm::cl::ResetAllOptionOccurrences();
226227

227228
llvm::BumpPtrAllocator A;
228-
llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine);
229+
llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine,
230+
VFS.get());
229231
if (llvm::Error Err = ECtx.expandResponseFiles(ArgV)) {
230232
llvm::errs() << toString(std::move(Err)) << '\n';
231233
return 1;
@@ -293,14 +295,16 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
293295

294296
bool ClangCLMode = IsClangCL(DriverMode);
295297

296-
if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A)) {
298+
auto VFS = llvm::vfs::getRealFileSystem();
299+
300+
if (llvm::Error Err = expandResponseFiles(Args, ClangCLMode, A, VFS.get())) {
297301
llvm::errs() << toString(std::move(Err)) << '\n';
298302
return 1;
299303
}
300304

301305
// Handle -cc1 integrated tools.
302306
if (Args.size() >= 2 && StringRef(Args[1]).starts_with("-cc1"))
303-
return ExecuteCC1Tool(Args, ToolContext);
307+
return ExecuteCC1Tool(Args, ToolContext, VFS);
304308

305309
// Handle options that need handling before the real command line parsing in
306310
// Driver::BuildCompilation()
@@ -382,7 +386,6 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
382386
Diags.takeClient(), std::move(SerializedConsumer)));
383387
}
384388

385-
auto VFS = llvm::vfs::getRealFileSystem();
386389
ProcessWarningOptions(Diags, *DiagOpts, *VFS, /*ReportDiags=*/false);
387390

388391
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags,
@@ -402,10 +405,10 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
402405
if (!SetBackdoorDriverOutputsFromEnvVars(TheDriver))
403406
return 1;
404407

405-
auto ExecuteCC1WithContext =
406-
[&ToolContext](SmallVectorImpl<const char *> &ArgV) {
407-
return ExecuteCC1Tool(ArgV, ToolContext);
408-
};
408+
auto ExecuteCC1WithContext = [&ToolContext,
409+
&VFS](SmallVectorImpl<const char *> &ArgV) {
410+
return ExecuteCC1Tool(ArgV, ToolContext, VFS);
411+
};
409412
if (!UseNewCC1Process) {
410413
TheDriver.CC1Main = ExecuteCC1WithContext;
411414
// Ensure the CC1Command actually catches cc1 crashes

llvm/include/llvm/Support/CommandLine.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ namespace cl {
6969
LLVM_ABI bool ParseCommandLineOptions(int argc, const char *const *argv,
7070
StringRef Overview = "",
7171
raw_ostream *Errs = nullptr,
72+
vfs::FileSystem *VFS = nullptr,
7273
const char *EnvVar = nullptr,
7374
bool LongOptionsUseDoubleDash = false);
7475

@@ -2192,7 +2193,8 @@ class ExpansionContext {
21922193
SmallVectorImpl<const char *> &NewArgv);
21932194

21942195
public:
2195-
LLVM_ABI ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T);
2196+
LLVM_ABI ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T,
2197+
vfs::FileSystem *FS = nullptr);
21962198

21972199
ExpansionContext &setMarkEOLs(bool X) {
21982200
MarkEOLs = X;

llvm/lib/Support/CommandLine.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ class CommandLineParser {
188188

189189
bool ParseCommandLineOptions(int argc, const char *const *argv,
190190
StringRef Overview, raw_ostream *Errs = nullptr,
191+
vfs::FileSystem *VFS = nullptr,
191192
bool LongOptionsUseDoubleDash = false);
192193

193194
void forEachSubCommand(Option &Opt, function_ref<void(SubCommand &)> Action) {
@@ -1401,8 +1402,9 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
14011402
return true;
14021403
}
14031404

1404-
ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T)
1405-
: Saver(A), Tokenizer(T), FS(vfs::getRealFileSystem().get()) {}
1405+
ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T,
1406+
vfs::FileSystem *FS)
1407+
: Saver(A), Tokenizer(T), FS(FS ? FS : vfs::getRealFileSystem().get()) {}
14061408

14071409
bool ExpansionContext::findConfigFile(StringRef FileName,
14081410
SmallVectorImpl<char> &FilePath) {
@@ -1461,7 +1463,7 @@ Error ExpansionContext::readConfigFile(StringRef CfgFile,
14611463
static void initCommonOptions();
14621464
bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
14631465
StringRef Overview, raw_ostream *Errs,
1464-
const char *EnvVar,
1466+
vfs::FileSystem *VFS, const char *EnvVar,
14651467
bool LongOptionsUseDoubleDash) {
14661468
initCommonOptions();
14671469
SmallVector<const char *, 20> NewArgv;
@@ -1482,8 +1484,8 @@ bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
14821484
int NewArgc = static_cast<int>(NewArgv.size());
14831485

14841486
// Parse all options.
1485-
return GlobalParser->ParseCommandLineOptions(NewArgc, &NewArgv[0], Overview,
1486-
Errs, LongOptionsUseDoubleDash);
1487+
return GlobalParser->ParseCommandLineOptions(
1488+
NewArgc, &NewArgv[0], Overview, Errs, VFS, LongOptionsUseDoubleDash);
14871489
}
14881490

14891491
/// Reset all options at least once, so that we can parse different options.
@@ -1503,17 +1505,17 @@ void CommandLineParser::ResetAllOptionOccurrences() {
15031505
}
15041506
}
15051507

1506-
bool CommandLineParser::ParseCommandLineOptions(int argc,
1507-
const char *const *argv,
1508-
StringRef Overview,
1509-
raw_ostream *Errs,
1510-
bool LongOptionsUseDoubleDash) {
1508+
bool CommandLineParser::ParseCommandLineOptions(
1509+
int argc, const char *const *argv, StringRef Overview, raw_ostream *Errs,
1510+
vfs::FileSystem *VFS, bool LongOptionsUseDoubleDash) {
15111511
assert(hasOptions() && "No options specified!");
15121512

15131513
ProgramOverview = Overview;
15141514
bool IgnoreErrors = Errs;
15151515
if (!Errs)
15161516
Errs = &errs();
1517+
if (!VFS)
1518+
VFS = vfs::getRealFileSystem().get();
15171519
bool ErrorParsing = false;
15181520

15191521
// Expand response files.
@@ -1524,7 +1526,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
15241526
#else
15251527
auto Tokenize = cl::TokenizeGNUCommandLine;
15261528
#endif
1527-
ExpansionContext ECtx(A, Tokenize);
1529+
ExpansionContext ECtx(A, Tokenize, VFS);
15281530
if (Error Err = ECtx.expandResponseFiles(newArgv)) {
15291531
*Errs << toString(std::move(Err)) << '\n';
15301532
return false;

llvm/tools/obj2yaml/obj2yaml.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ int main(int argc, char *argv[]) {
104104
cl::HideUnrelatedOptions(Cat);
105105
cl::ParseCommandLineOptions(
106106
argc, argv, "Dump a YAML description from an object file", nullptr,
107-
nullptr, /*LongOptionsUseDoubleDash=*/true);
107+
nullptr, nullptr, /*LongOptionsUseDoubleDash=*/true);
108108

109109
std::error_code EC;
110110
std::unique_ptr<ToolOutputFile> Out(

llvm/tools/yaml2obj/yaml2obj.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ int main(int argc, char **argv) {
115115
cl::HideUnrelatedOptions(Cat);
116116
cl::ParseCommandLineOptions(
117117
argc, argv, "Create an object file from a YAML description", nullptr,
118-
nullptr, /*LongOptionsUseDoubleDash=*/true);
118+
nullptr, nullptr, /*LongOptionsUseDoubleDash=*/true);
119119

120120
constexpr StringRef ProgName = "yaml2obj";
121121
auto ErrHandler = [&](const Twine &Msg) {

llvm/unittests/Support/CommandLineTest.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1901,20 +1901,20 @@ TEST(CommandLineTest, LongOptions) {
19011901

19021902
// Fails because `-ab` is treated as `-a -b`, so `-a` is seen twice, and
19031903
// `val1` is unexpected.
1904-
EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(),
1905-
&OS, nullptr, true));
1904+
EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(), &OS, nullptr,
1905+
nullptr, true));
19061906
EXPECT_FALSE(Errs.empty()); Errs.clear();
19071907
cl::ResetAllOptionOccurrences();
19081908

19091909
// Works because `-a` is treated differently than `--ab`.
1910-
EXPECT_TRUE(cl::ParseCommandLineOptions(4, args2, StringRef(),
1911-
&OS, nullptr, true));
1910+
EXPECT_TRUE(cl::ParseCommandLineOptions(4, args2, StringRef(), &OS, nullptr,
1911+
nullptr, true));
19121912
EXPECT_TRUE(Errs.empty()); Errs.clear();
19131913
cl::ResetAllOptionOccurrences();
19141914

19151915
// Works because `-ab` is treated as `-a -b`, and `--ab` is a long option.
1916-
EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(),
1917-
&OS, nullptr, true));
1916+
EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(), &OS, nullptr,
1917+
nullptr, true));
19181918
EXPECT_TRUE(OptA);
19191919
EXPECT_TRUE(OptBLong);
19201920
EXPECT_STREQ("val1", OptAB.c_str());

0 commit comments

Comments
 (0)