[llvm-branch-commits] [clang] release/22.x: [clang-scan-deps] Fixes an assertion in clang-scan-deps (#193619) (PR #194118)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Apr 24 23:27:01 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: llvmbot

<details>
<summary>Changes</summary>

Backport 1249cb6aea8893c3d2ba7221697b68b0ef4520e9

Requested by: @<!-- -->ChuanqiXu9

---
Full diff: https://github.com/llvm/llvm-project/pull/194118.diff


2 Files Affected:

- (added) clang/test/ClangScanDeps/p1689-mf-nested-dir.c (+34) 
- (modified) clang/tools/clang-scan-deps/ClangScanDeps.cpp (+30-7) 


``````````diff
diff --git a/clang/test/ClangScanDeps/p1689-mf-nested-dir.c b/clang/test/ClangScanDeps/p1689-mf-nested-dir.c
new file mode 100644
index 0000000000000..dca72727f4d6b
--- /dev/null
+++ b/clang/test/ClangScanDeps/p1689-mf-nested-dir.c
@@ -0,0 +1,34 @@
+// UNSUPPORTED: target={{.*}}-aix{{.*}}
+//
+// When using -format=p1689, clang-scan-deps writes make-style dependency output
+// to the path from -MF. The directory where the output file is written may not
+// exist yet. Ensure the tool creates missing directories instead of failing or
+// aborting.
+//
+// RUN: rm -rf %t
+// RUN: mkdir -p %t
+// RUN: split-file %s %t
+// RUN: sed "s|DIR|%/t|g" %t/cdb.json.in > %t/compile_commands.json
+// RUN: clang-scan-deps -compilation-database %t/compile_commands.json -format=p1689 \
+// RUN:   -o %t/scan.json
+// RUN: cat %t/obj/nested/hello.o.d | sed 's:\\\\\?:/:g' | FileCheck %s --check-prefix=CHECK-DEP
+// RUN: cat %t/scan.json | FileCheck %s -DPREFIX=%/t --check-prefix=CHECK-JSON
+
+//--- hello.c
+int main(void) { return 0; }
+
+//--- cdb.json.in
+[
+  {
+    "directory": "DIR",
+    "command": "clang -c DIR/hello.c -o DIR/obj/nested/hello.o -MMD -MF DIR/obj/nested/hello.o.d",
+    "file": "DIR/hello.c",
+    "output": "DIR/obj/nested/hello.o"
+  }
+]
+
+// CHECK-DEP-DAG: hello.o
+// CHECK-DEP-DAG: hello.c
+
+// CHECK-JSON-DAG: "primary-output": "[[PREFIX]]/obj/nested/hello.o"
+// CHECK-JSON-DAG: "version": 1
diff --git a/clang/tools/clang-scan-deps/ClangScanDeps.cpp b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
index 256a70568a3bf..a5f0db6976a43 100644
--- a/clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ b/clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -19,6 +19,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/JSON.h"
@@ -1031,6 +1032,7 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
 
         if (!MakeformatOutputPath.empty() && !MakeformatOutput.empty() &&
             !HadErrors) {
+          llvm::SmallString<256> FullDepPath;
           static std::mutex Lock;
           // With compilation database, we may open different files
           // concurrently or we may write the same file concurrently. So we
@@ -1039,16 +1041,37 @@ int clang_scan_deps_main(int argc, char **argv, const llvm::ToolContext &) {
           static llvm::StringMap<llvm::raw_fd_ostream> OSs;
           std::unique_lock<std::mutex> LockGuard(Lock);
 
-          auto OSIter = OSs.find(MakeformatOutputPath);
+          if (llvm::sys::path::is_absolute(MakeformatOutputPath))
+            FullDepPath = MakeformatOutputPath;
+          else
+            llvm::sys::path::append(FullDepPath, CWD, MakeformatOutputPath);
+
+          if (llvm::StringRef Parent =
+                  llvm::sys::path::parent_path(FullDepPath);
+              !Parent.empty()) {
+            if (std::error_code DirEC =
+                    llvm::sys::fs::create_directories(Parent)) {
+              llvm::errs() << "Failed to create directory \"" << Parent
+                           << "\" for P1689 make format output: "
+                           << DirEC.message() << "\n";
+              HadErrors = true;
+              continue;
+            }
+          }
+
+          auto OSIter = OSs.find(FullDepPath);
           if (OSIter == OSs.end()) {
             std::error_code EC;
-            OSIter = OSs.try_emplace(MakeformatOutputPath, MakeformatOutputPath,
-                                     EC, llvm::sys::fs::OF_Text)
-                         .first;
-            if (EC)
+            auto Emplaced = OSs.try_emplace(FullDepPath.str(), FullDepPath, EC,
+                                            llvm::sys::fs::OF_Text);
+            OSIter = Emplaced.first;
+            if (EC) {
+              OSs.erase(OSIter);
               llvm::errs() << "Failed to open P1689 make format output file \""
-                           << MakeformatOutputPath << "\" for " << EC.message()
-                           << "\n";
+                           << FullDepPath << "\" for " << EC.message() << "\n";
+              HadErrors = true;
+              continue;
+            }
           }
 
           SharedStream MakeformatOS(OSIter->second);

``````````

</details>


https://github.com/llvm/llvm-project/pull/194118


More information about the llvm-branch-commits mailing list