[PATCH] D122385: [clang][deps] Fix clang-cl output argument parsing

Jan Svoboda via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 24 05:12:38 PDT 2022


jansvoboda11 created this revision.
jansvoboda11 added reviewers: Bigcheese, dexonsmith, saudi.
Herald added a project: All.
jansvoboda11 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

One goal of the ad-hoc command line argument parsing in `clang-scan-deps` is to get the last output path value.

Currently, the algorithm walks the arguments in reverse and identifies potention output path arguments.

Interestingly, in `clang-cl` mode, the output path can be specified in multiple ways. For example `/o /opt/build` and `/o/opt/build` are equivalent. The parser currently fails to correctly parse the former. It considers the value (`/opt/build/`) to be a shorthand for `/o pt/build`. It doesn't look at the preceding `/o`.

This patch simplifies the algorithm by doing forward iteration and fixes the bug by correctly handling separate `/o` argument.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122385

Files:
  clang/test/ClangScanDeps/cl-output.c
  clang/tools/clang-scan-deps/ClangScanDeps.cpp


Index: clang/tools/clang-scan-deps/ClangScanDeps.cpp
===================================================================
--- clang/tools/clang-scan-deps/ClangScanDeps.cpp
+++ clang/tools/clang-scan-deps/ClangScanDeps.cpp
@@ -470,27 +470,29 @@
               llvm::sys::path::stem(Args[0]).contains_insensitive("clang-cl") ||
               llvm::is_contained(Args, "--driver-mode=cl");
 
-          // Reverse scan, starting at the end or at the element before "--".
-          auto R = std::make_reverse_iterator(FlagsEnd);
-          for (auto I = R, E = Args.rend(); I != E; ++I) {
+          for (auto I = Args.begin(); I != FlagsEnd; ++I) {
             StringRef Arg = *I;
             if (ClangCLMode) {
               // Ignore arguments that are preceded by "-Xclang".
-              if ((I + 1) != E && I[1] == "-Xclang")
-                continue;
-              if (LastO.empty()) {
-                // With clang-cl, the output obj file can be specified with
-                // "/opath", "/o path", "/Fopath", and the dash counterparts.
-                // Also, clang-cl adds ".obj" extension if none is found.
-                if ((Arg == "-o" || Arg == "/o") && I != R)
-                  LastO = I[-1]; // Next argument (reverse iterator)
-                else if (Arg.startswith("/Fo") || Arg.startswith("-Fo"))
-                  LastO = Arg.drop_front(3).str();
-                else if (Arg.startswith("/o") || Arg.startswith("-o"))
-                  LastO = Arg.drop_front(2).str();
-
-                if (!LastO.empty() && !llvm::sys::path::has_extension(LastO))
-                  LastO.append(".obj");
+              if (Arg == "-Xclang")
+                ++I;
+
+              // With clang-cl, the output obj file can be specified with
+              // "/opath", "/o path", "/Fopath", and the dash counterparts.
+              // Also, clang-cl adds ".obj" extension if none is found.
+              llvm::StringRef CurrentO;
+              if ((Arg == "/o" || Arg == "-o") && I != FlagsEnd)
+                CurrentO = *++I;
+              else if (Arg.startswith("/Fo") || Arg.startswith("-Fo"))
+                CurrentO = Arg.drop_front(3);
+              else if (Arg.startswith("/o") || Arg.startswith("-o"))
+                CurrentO = Arg.drop_front(2);
+
+              if (!CurrentO.empty()) {
+                if (!llvm::sys::path::has_extension(CurrentO))
+                  LastO = (CurrentO + ".obj").str();
+                else
+                  LastO = CurrentO.str();
               }
             }
             if (Arg == "-resource-dir")
Index: clang/test/ClangScanDeps/cl-output.c
===================================================================
--- clang/test/ClangScanDeps/cl-output.c
+++ clang/test/ClangScanDeps/cl-output.c
@@ -46,6 +46,10 @@
   "file": "DIR/test.c",
   "directory": "DIR",
   "command": "clang-cl /c -o DIR/test.o -o DIR/last.o -- DIR/test.c"
+},{
+  "file": "DIR/test.c",
+  "directory": "DIR",
+  "command": "clang-cl /c /o /opt/test.o -- DIR/test.c"
 }]
 
 //--- test.c
@@ -81,7 +85,9 @@
 // Check that the last argument specifying the output path wins.
 //
 // RUN: sed -e "s|DIR|%/t|g" %t/last-arg-cdb.json.template > %t/last-arg-cdb.json
-// RUN: clang-scan-deps -compilation-database %t/last-arg-cdb.json > %t/last-arg-result.d
+// RUN: clang-scan-deps -compilation-database %t/last-arg-cdb.json -j 1 > %t/last-arg-result.d
 // RUN: cat %t/last-arg-result.d | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefix=CHECK-LAST
 // CHECK-LAST:      [[PREFIX]]/last.o:
 // CHECK-LAST-NEXT:   [[PREFIX]]/test.c
+// CHECK-LAST-NEXT: /opt/test.o:
+// CHECK-LAST-NEXT:   [[PREFIX]]/test.c


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D122385.417888.patch
Type: text/x-patch
Size: 3674 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220324/944760a8/attachment.bin>


More information about the cfe-commits mailing list