[clang-tools-extra] [clang-include-cleaner] Fix incorrect directory issue for writing files (PR #111375)

Byoungchan Lee via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 13 04:25:42 PDT 2024


================
@@ -305,8 +307,84 @@ int main(int argc, const char **argv) {
     }
   }
 
-  clang::tooling::ClangTool Tool(OptionsParser->getCompilations(),
-                                 OptionsParser->getSourcePathList());
+  auto VFS = llvm::vfs::getRealFileSystem();
+  auto &CDB = OptionsParser->getCompilations();
+  // CDBToAbsPaths is a map from the path in the compilation database to the
+  // writable absolute path of the file.
+  std::map<std::string, std::string> CDBToAbsPaths;
+  if (Edit) {
+    // if Edit is enabled, `Factory.editedFiles()` will contain the final code,
+    // along with the path given in the compilation database. That path can be
+    // absolute or relative, and if it is relative, it is relative to the
+    // "Directory" field in the compilation database. We need to make it
+    // absolute to write the final code to the correct path.
+    // There are several cases to consider:
+    // 1. The "Directory" field isn't same as the current working directory.
+    // 2. The file path resolved from the "Directory" field is not writable.
+    // For these cases, we need to find a writable path for the file.
+    // To effectively handle these cases, we only need to consider
+    // the files from `getSourcePathList()` that are present in the compilation
+    // database.
+    for (auto &Source : OptionsParser->getSourcePathList()) {
+      llvm::SmallString<256> AbsPath(Source);
+      if (auto Err = VFS->makeAbsolute(AbsPath)) {
+        llvm::errs() << "Failed to get absolute path for " << Source << " : "
+                     << Err.message() << '\n';
+        return 1;
+      }
+      std::vector<clang::tooling::CompileCommand> Cmds =
+          CDB.getCompileCommands(AbsPath);
+      if (Cmds.empty()) {
+        // Try with the original path.
+        Cmds = CDB.getCompileCommands(Source);
+        if (Cmds.empty()) {
+          continue;
+        }
+      }
+      // We only need the first command to get the directory.
+      auto Cmd = Cmds[0];
+      llvm::SmallString<256> CDBPath(Cmd.Filename);
+      std::string Directory(Cmd.Directory);
+
+      if (llvm::sys::path::is_absolute(CDBPath)) {
+        // If the path in the compilation database is already absolute, we don't
+        // need to do anything.
+        CDBToAbsPaths[static_cast<std::string>(CDBPath)] =
----------------
bc-lee wrote:

Done.

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


More information about the cfe-commits mailing list