summaryrefslogtreecommitdiff
path: root/clang/lib/Tooling/Tooling.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /clang/lib/Tooling/Tooling.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'clang/lib/Tooling/Tooling.cpp')
-rw-r--r--clang/lib/Tooling/Tooling.cpp68
1 files changed, 46 insertions, 22 deletions
diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp
index 79851ac723da..5242134097da 100644
--- a/clang/lib/Tooling/Tooling.cpp
+++ b/clang/lib/Tooling/Tooling.cpp
@@ -83,16 +83,20 @@ newDriver(DiagnosticsEngine *Diagnostics, const char *BinaryName,
return CompilerDriver;
}
-/// Retrieves the clang CC1 specific flags out of the compilation's jobs.
-///
-/// Returns nullptr on error.
-static const llvm::opt::ArgStringList *getCC1Arguments(
- DiagnosticsEngine *Diagnostics, driver::Compilation *Compilation) {
- // We expect to get back exactly one Command job, if we didn't something
- // failed. Extract that job from the Compilation.
+/// Decide whether extra compiler frontend commands can be ignored.
+static bool ignoreExtraCC1Commands(const driver::Compilation *Compilation) {
const driver::JobList &Jobs = Compilation->getJobs();
const driver::ActionList &Actions = Compilation->getActions();
+
bool OffloadCompilation = false;
+
+ // Jobs and Actions look very different depending on whether the Clang tool
+ // injected -fsyntax-only or not. Try to handle both cases here.
+
+ for (const auto &Job : Jobs)
+ if (StringRef(Job.getExecutable()) == "clang-offload-bundler")
+ OffloadCompilation = true;
+
if (Jobs.size() > 1) {
for (auto A : Actions){
// On MacOSX real actions may end up being wrapped in BindArchAction
@@ -117,8 +121,33 @@ static const llvm::opt::ArgStringList *getCC1Arguments(
}
}
}
- if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) ||
- (Jobs.size() > 1 && !OffloadCompilation)) {
+
+ return OffloadCompilation;
+}
+
+namespace clang {
+namespace tooling {
+
+const llvm::opt::ArgStringList *
+getCC1Arguments(DiagnosticsEngine *Diagnostics,
+ driver::Compilation *Compilation) {
+ const driver::JobList &Jobs = Compilation->getJobs();
+
+ auto IsCC1Command = [](const driver::Command &Cmd) {
+ return StringRef(Cmd.getCreator().getName()) == "clang";
+ };
+
+ auto IsSrcFile = [](const driver::InputInfo &II) {
+ return isSrcFile(II.getType());
+ };
+
+ llvm::SmallVector<const driver::Command *, 1> CC1Jobs;
+ for (const driver::Command &Job : Jobs)
+ if (IsCC1Command(Job) && llvm::all_of(Job.getInputInfos(), IsSrcFile))
+ CC1Jobs.push_back(&Job);
+
+ if (CC1Jobs.empty() ||
+ (CC1Jobs.size() > 1 && !ignoreExtraCC1Commands(Compilation))) {
SmallString<256> error_msg;
llvm::raw_svector_ostream error_stream(error_msg);
Jobs.Print(error_stream, "; ", true);
@@ -127,19 +156,9 @@ static const llvm::opt::ArgStringList *getCC1Arguments(
return nullptr;
}
- // The one job we find should be to invoke clang again.
- const auto &Cmd = cast<driver::Command>(*Jobs.begin());
- if (StringRef(Cmd.getCreator().getName()) != "clang") {
- Diagnostics->Report(diag::err_fe_expected_clang_command);
- return nullptr;
- }
-
- return &Cmd.getArguments();
+ return &CC1Jobs[0]->getArguments();
}
-namespace clang {
-namespace tooling {
-
/// Returns a clang build invocation initialized from the CC1 flags.
CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics,
const llvm::opt::ArgStringList &CC1Args,
@@ -334,6 +353,10 @@ bool ToolInvocation::run() {
DiagnosticsEngine Diagnostics(
IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs()), &*DiagOpts,
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
+ // Although `Diagnostics` are used only for command-line parsing, the custom
+ // `DiagConsumer` might expect a `SourceManager` to be present.
+ SourceManager SrcMgr(Diagnostics, *Files);
+ Diagnostics.setSourceManager(&SrcMgr);
const std::unique_ptr<driver::Driver> Driver(
newDriver(&Diagnostics, BinaryName, &Files->getVirtualFileSystem()));
@@ -440,8 +463,9 @@ static void injectResourceDir(CommandLineArguments &Args, const char *Argv0,
return;
// If there's no override in place add our resource dir.
- Args.push_back("-resource-dir=" +
- CompilerInvocation::GetResourcesPath(Argv0, MainAddr));
+ Args = getInsertArgumentAdjuster(
+ ("-resource-dir=" + CompilerInvocation::GetResourcesPath(Argv0, MainAddr))
+ .c_str())(Args, "");
}
int ClangTool::run(ToolAction *Action) {