[clang] 3ce78cb - [clang][deps] Fix handling of -MT in module command-line
Ben Langmuir via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 13 13:36:25 PDT 2022
Author: Ben Langmuir
Date: 2022-07-13T13:36:15-07:00
New Revision: 3ce78cbd2392d7c98f97d1d424cd7ff582fc28f8
URL: https://github.com/llvm/llvm-project/commit/3ce78cbd2392d7c98f97d1d424cd7ff582fc28f8
DIFF: https://github.com/llvm/llvm-project/commit/3ce78cbd2392d7c98f97d1d424cd7ff582fc28f8.diff
LOG: [clang][deps] Fix handling of -MT in module command-line
Follow-up to 6626f6fec3d3, this fixes the handling of -MT
* If no targets are provided, we need to invent one since cc1 expects
the driver to have handled it. The default is to use -o, quoting as
necessary for a make target.
* Fix the splitting for empty string, which was incorrectly treated as
{""} instead of {}.
* Add a way to test this behaviour in clang-scan-deps.
Differential Revision: https://reviews.llvm.org/D129607
Added:
clang/include/clang/Basic/MakeSupport.h
clang/lib/Basic/MakeSupport.cpp
Modified:
clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
clang/lib/Basic/CMakeLists.txt
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
clang/test/ClangScanDeps/generate-modules-path-args.c
clang/tools/clang-scan-deps/ClangScanDeps.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/MakeSupport.h b/clang/include/clang/Basic/MakeSupport.h
new file mode 100644
index 0000000000000..c663014ba7bcf
--- /dev/null
+++ b/clang/include/clang/Basic/MakeSupport.h
@@ -0,0 +1,23 @@
+//===- MakeSupport.h - Make Utilities ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_BASIC_MAKESUPPORT_H
+#define LLVM_CLANG_BASIC_MAKESUPPORT_H
+
+#include "clang/Basic/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang {
+
+/// Quote target names for inclusion in GNU Make dependency files.
+/// Only the characters '$', '#', ' ', '\t' are quoted.
+void quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res);
+
+} // namespace clang
+
+#endif // LLVM_CLANG_BASIC_MAKESUPPORT_H
diff --git a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
index cb68df8314da1..05c9f56b4cf63 100644
--- a/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
+++ b/clang/include/clang/Tooling/DependencyScanning/ModuleDepCollector.h
@@ -72,7 +72,7 @@ enum class ModuleOutputKind {
/// The path of the dependency file (.d), if any.
DependencyFile,
/// The null-separated list of names to use as the targets in the dependency
- /// file, if any.
+ /// file, if any. Defaults to the value of \c ModuleFile, as in the driver.
DependencyTargets,
/// The path of the serialized diagnostic file (.dia), if any.
DiagnosticSerializationFile,
diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt
index c815b571bc9c0..89dd33260b29c 100644
--- a/clang/lib/Basic/CMakeLists.txt
+++ b/clang/lib/Basic/CMakeLists.txt
@@ -54,6 +54,7 @@ add_clang_library(clangBasic
IdentifierTable.cpp
LangOptions.cpp
LangStandards.cpp
+ MakeSupport.cpp
Module.cpp
ObjCRuntime.cpp
OpenCLOptions.cpp
diff --git a/clang/lib/Basic/MakeSupport.cpp b/clang/lib/Basic/MakeSupport.cpp
new file mode 100644
index 0000000000000..37838f7bbc7bc
--- /dev/null
+++ b/clang/lib/Basic/MakeSupport.cpp
@@ -0,0 +1,35 @@
+//===-- MakeSuport.cpp --------------------------------------------------*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/MakeSupport.h"
+
+void clang::quoteMakeTarget(StringRef Target, SmallVectorImpl<char> &Res) {
+ for (unsigned i = 0, e = Target.size(); i != e; ++i) {
+ switch (Target[i]) {
+ case ' ':
+ case '\t':
+ // Escape the preceding backslashes
+ for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
+ Res.push_back('\\');
+
+ // Escape the space/tab
+ Res.push_back('\\');
+ break;
+ case '$':
+ Res.push_back('$');
+ break;
+ case '#':
+ Res.push_back('\\');
+ break;
+ default:
+ break;
+ }
+
+ Res.push_back(Target[i]);
+ }
+}
\ No newline at end of file
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 0081426e698ec..e16f017dd5229 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -27,6 +27,7 @@
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/MakeSupport.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -97,34 +98,6 @@ static void EscapeSpacesAndBackslashes(const char *Arg,
}
}
-// Quote target names for inclusion in GNU Make dependency files.
-// Only the characters '$', '#', ' ', '\t' are quoted.
-static void QuoteTarget(StringRef Target, SmallVectorImpl<char> &Res) {
- for (unsigned i = 0, e = Target.size(); i != e; ++i) {
- switch (Target[i]) {
- case ' ':
- case '\t':
- // Escape the preceding backslashes
- for (int j = i - 1; j >= 0 && Target[j] == '\\'; --j)
- Res.push_back('\\');
-
- // Escape the space/tab
- Res.push_back('\\');
- break;
- case '$':
- Res.push_back('$');
- break;
- case '#':
- Res.push_back('\\');
- break;
- default:
- break;
- }
-
- Res.push_back(Target[i]);
- }
-}
-
/// Apply \a Work on the current tool chain \a RegularToolChain and any other
/// offloading tool chain that is associated with the current action \a JA.
static void
@@ -1249,7 +1222,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
} else {
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
- QuoteTarget(A->getValue(), Quoted);
+ quoteMakeTarget(A->getValue(), Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
}
@@ -1274,7 +1247,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-MT");
SmallString<128> Quoted;
- QuoteTarget(DepTarget, Quoted);
+ quoteMakeTarget(DepTarget, Quoted);
CmdArgs.push_back(Args.MakeArgString(Quoted));
}
diff --git a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
index 2d4af501343b2..725bb2c318ac2 100644
--- a/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
+++ b/clang/lib/Tooling/DependencyScanning/ModuleDepCollector.cpp
@@ -8,6 +8,7 @@
#include "clang/Tooling/DependencyScanning/ModuleDepCollector.h"
+#include "clang/Basic/MakeSupport.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Tooling/DependencyScanning/DependencyScanningWorker.h"
@@ -112,7 +113,7 @@ serializeCompilerInvocation(const CompilerInvocation &CI) {
static std::vector<std::string> splitString(std::string S, char Separator) {
SmallVector<StringRef> Segments;
- StringRef(S).split(Segments, Separator);
+ StringRef(S).split(Segments, Separator, /*MaxSplit=*/-1, /*KeepEmpty=*/false);
std::vector<std::string> Result;
Result.reserve(Segments.size());
for (StringRef Segment : Segments)
@@ -135,10 +136,17 @@ std::vector<std::string> ModuleDeps::getCanonicalCommandLine(
CI.getDiagnosticOpts().DiagnosticSerializationFile =
LookupModuleOutput(ID, ModuleOutputKind::DiagnosticSerializationFile);
if (HadDependencyFile) {
- CI.getDependencyOutputOpts().OutputFile =
+ DependencyOutputOptions &DepOpts = CI.getDependencyOutputOpts();
+ DepOpts.OutputFile =
LookupModuleOutput(ID, ModuleOutputKind::DependencyFile);
- CI.getDependencyOutputOpts().Targets = splitString(
+ DepOpts.Targets = splitString(
LookupModuleOutput(ID, ModuleOutputKind::DependencyTargets), '\0');
+ if (!DepOpts.OutputFile.empty() && DepOpts.Targets.empty()) {
+ // Fallback to -o as dependency target, as in the driver.
+ SmallString<128> Target;
+ quoteMakeTarget(FrontendOpts.OutputFile, Target);
+ DepOpts.Targets.push_back(std::string(Target));
+ }
}
for (ModuleID MID : ClangModuleDeps)
diff --git a/clang/test/ClangScanDeps/generate-modules-path-args.c b/clang/test/ClangScanDeps/generate-modules-path-args.c
index 79f94ba82e189..31fb3e897c641 100644
--- a/clang/test/ClangScanDeps/generate-modules-path-args.c
+++ b/clang/test/ClangScanDeps/generate-modules-path-args.c
@@ -5,6 +5,12 @@
// RUN: clang-scan-deps -compilation-database %t/cdb.json \
// RUN: -format experimental-full -generate-modules-path-args > %t/deps.json
// RUN: cat %t/deps.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s
+// RUN: clang-scan-deps -compilation-database %t/cdb.json \
+// RUN: -format experimental-full -generate-modules-path-args -dependency-target foo > %t/deps_mt1.json
+// RUN: cat %t/deps_mt1.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s -check-prefix=DEPS_MT1
+// RUN: clang-scan-deps -compilation-database %t/cdb.json \
+// RUN: -format experimental-full -generate-modules-path-args -dependency-target foo -dependency-target bar > %t/deps_mt2.json
+// RUN: cat %t/deps_mt2.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t %s -check-prefix=DEPS_MT2
// RUN: clang-scan-deps -compilation-database %t/cdb_without.json \
// RUN: -format experimental-full -generate-modules-path-args > %t/deps_without.json
// RUN: cat %t/deps_without.json | sed 's:\\\\\?:/:g' | FileCheck -DPREFIX=%/t -check-prefix=WITHOUT %s
@@ -16,10 +22,20 @@
// CHECK-NEXT: "-cc1"
// CHECK: "-serialize-diagnostic-file"
// CHECK-NEXT: "[[PREFIX]]{{.*}}Mod{{.*}}.diag"
+// CHECK: "-MT"
+// CHECK-NEXT: "[[PREFIX]]{{.*}}Mod{{.*}}.pcm"
// CHECK: "-dependency-file"
// CHECK-NEXT: "[[PREFIX]]{{.*}}Mod{{.*}}.d"
// CHECK: ],
+// DEPS_MT1: "-MT"
+// DEPS_MT1-NEXT: "foo"
+
+// DEPS_MT2: "-MT"
+// DEPS_MT2-NEXT: "foo"
+// DEPS_MT2-NEXT: "-MT"
+// DEPS_MT2-NEXT: "bar"
+
// WITHOUT: {
// WITHOUT-NEXT: "modules": [
// WITHOUT-NEXT: {
@@ -27,6 +43,7 @@
// WITHOUT-NEXT: "-cc1"
// WITHOUT-NOT: "-serialize-diagnostic-file"
// WITHOUT-NOT: "-dependency-file"
+// WITHOUT-NOT: "-MT"
// WITHOUT: ],
//--- cdb.json.template
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 467d7d5c3644b..46166d8903a75 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -196,6 +196,12 @@ llvm::cl::opt<std::string> ModuleName(
llvm::cl::desc("the module of which the dependencies are to be computed"),
llvm::cl::cat(DependencyScannerCategory));
+llvm::cl::list<std::string> ModuleDepTargets(
+ "dependency-target",
+ llvm::cl::desc("With '-generate-modules-path-args', the names of "
+ "dependency targets for the dependency file"),
+ llvm::cl::cat(DependencyScannerCategory));
+
enum ResourceDirRecipeKind {
RDRK_ModifyCompilerPath,
RDRK_InvokeCompiler,
@@ -367,7 +373,8 @@ class FullDeps {
case ModuleOutputKind::DependencyFile:
return PCMPath.first->second + ".d";
case ModuleOutputKind::DependencyTargets:
- return ""; // Will get the default target name.
+ // Null-separate the list of targets.
+ return join(ModuleDepTargets, StringRef("\0", 1));
case ModuleOutputKind::DiagnosticSerializationFile:
return PCMPath.first->second + ".diag";
}
More information about the cfe-commits
mailing list