ehntoo created this revision.
ehntoo added reviewers: kadircet, nridge.
ehntoo added a project: clang-tools-extra.
Herald added a subscriber: arphaman.
Herald added a project: All.
ehntoo requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Rework the cache key construction to consider all the arguments used when 
invoking the query driver.
https://github.com/clangd/clangd/issues/1403

This also reworks handling for -isysroot
https://github.com/clangd/clangd/issues/1404

And adds support for passing through -specs flags to the query driver
https://github.com/clangd/clangd/issues/1410


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D139277

Files:
  clang-tools-extra/clangd/SystemIncludeExtractor.cpp
  clang-tools-extra/clangd/test/system-include-extractor.test

Index: clang-tools-extra/clangd/test/system-include-extractor.test
===================================================================
--- clang-tools-extra/clangd/test/system-include-extractor.test
+++ clang-tools-extra/clangd/test/system-include-extractor.test
@@ -14,13 +14,17 @@
 # Check that clangd preserves certain flags like `-nostdinc` from
 # original invocation in compile_commands.json.
 # RUN: echo '[ -z "${args##*"-nostdinc"*}" ] || exit' >> %t.dir/bin/my_driver.sh
-# RUN: echo '[ -z "${args##*"-isysroot=/isysroot"*}" ] || exit' >> %t.dir/bin/my_driver.sh
-# RUN: echo '[ -z "${args##*"--sysroot /my/sysroot/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh
+# RUN: echo '[ -z "${args##*"-isysroot/isysroot1"*}" ] || exit' >> %t.dir/bin/my_driver.sh
+# RUN: echo '[ -z "${args##*"-isysroot /isysroot2"*}" ] || exit' >> %t.dir/bin/my_driver.sh
+# RUN: echo '[ -z "${args##*"--sysroot /my/sysroot1/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh
+# RUN: echo '[ -z "${args##*"--sysroot=/my/sysroot2/path"*}" ] || exit' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo line to ignore >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'printf "Target: arm-linux-gnueabihf\r\n" >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'printf "#include <...> search starts here:\r\n" >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'echo %t.dir/my/dir2/ >&2' >> %t.dir/bin/my_driver.sh
+# Append an alternate includes path iff we were given a specs file
+# RUN: echo '[ -z "${args##*"-specs=nano.specs"*}" ] && echo %t.dir/my/dir3/ >&2' >> %t.dir/bin/my_driver.sh
 # RUN: echo 'printf "End of search list.\r\n" >&2' >> %t.dir/bin/my_driver.sh
 # RUN: chmod +x %t.dir/bin/my_driver.sh
 
@@ -29,10 +33,12 @@
 # RUN: touch %t.dir/my/dir/a.h
 # RUN: mkdir -p %t.dir/my/dir2
 # RUN: touch %t.dir/my/dir2/b.h
+# RUN: mkdir -p %t.dir/my/dir3
+# RUN: touch %t.dir/my/dir3/c.h
 
 # Generate a compile_commands.json that will query the mock driver we've
 # created. Which should add a.h and b.h into include search path.
-# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
+# RUN: echo '[{"directory": "%/t.dir", "command": "my_driver.sh the-file.cpp -nostdinc --sysroot /my/sysroot1/path --sysroot=/my/sysroot2/path -isysroot/isysroot1 -isysroot /isysroot2 -specs=nano.specs", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
 
 # RUN: sed -e "s|INPUT_DIR|%/t.dir|g" %s > %t.test.1
 # On Windows, we need the URI in didOpen to look like "uri":"file:///C:/..."
@@ -53,7 +59,7 @@
       "uri": "file://INPUT_DIR/the-file.cpp",
       "languageId":"cpp",
       "version":1,
-      "text":"#include <a.h>\n#include <b.h>\n#if !defined(__ARM_ARCH) || !defined(__gnu_linux__)\n#error \"Invalid target\"\n#endif"
+      "text":"#include <a.h>\n#include <b.h>\n#include <c.h>\n#if !defined(__ARM_ARCH) || !defined(__gnu_linux__)\n#error \"Invalid target\"\n#endif"
     }
   }
 }
@@ -70,7 +76,7 @@
 {"jsonrpc":"2.0","method":"exit"}
 
 # Generate a different compile_commands.json which does not point to the mock driver
-# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp -nostdinc --sysroot /my/sysroot/path -isysroot=/isysroot", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
+# RUN: echo '[{"directory": "%/t.dir", "command": "gcc the-file.cpp -nostdinc --sysroot /my/sysroot1/path --sysroot=/my/sysroot2/path -isysroot/isysroot1 -isysroot /isysroot2 -specs=nano.specs", "file": "the-file.cpp"}]' > %t.dir/compile_commands.json
 
 # Generate a clangd config file which points to the mock driver instead
 # RUN: echo 'CompileFlags:' > %t.dir/.clangd
Index: clang-tools-extra/clangd/SystemIncludeExtractor.cpp
===================================================================
--- clang-tools-extra/clangd/SystemIncludeExtractor.cpp
+++ clang-tools-extra/clangd/SystemIncludeExtractor.cpp
@@ -135,11 +135,10 @@
   return std::move(Info);
 }
 
-llvm::Optional<DriverInfo>
-extractSystemIncludesAndTarget(llvm::SmallString<128> Driver,
-                               llvm::StringRef Lang,
-                               llvm::ArrayRef<std::string> CommandLine,
-                               const llvm::Regex &QueryDriverRegex) {
+llvm::Optional<DriverInfo> extractSystemIncludesAndTarget(
+    llvm::SmallString<128> Driver, llvm::StringRef Lang,
+    llvm::ArrayRef<llvm::StringRef> AdditionalDriverArgs,
+    const llvm::Regex &QueryDriverRegex) {
   trace::Span Tracer("Extract system includes and target");
 
   if (!llvm::sys::path::is_absolute(Driver)) {
@@ -180,33 +179,7 @@
   llvm::SmallVector<llvm::StringRef> Args = {Driver, "-E", "-x",
                                              Lang,   "-",  "-v"};
 
-  // These flags will be preserved
-  const llvm::StringRef FlagsToPreserve[] = {
-      "-nostdinc", "--no-standard-includes", "-nostdinc++", "-nobuiltininc"};
-  // Preserves these flags and their values, either as separate args or with an
-  // equalsbetween them
-  const llvm::StringRef ArgsToPreserve[] = {"--sysroot", "-isysroot"};
-
-  for (size_t I = 0, E = CommandLine.size(); I < E; ++I) {
-    llvm::StringRef Arg = CommandLine[I];
-    if (llvm::is_contained(FlagsToPreserve, Arg)) {
-      Args.push_back(Arg);
-    } else {
-      const auto *Found =
-          llvm::find_if(ArgsToPreserve, [&Arg](llvm::StringRef S) {
-            return Arg.startswith(S);
-          });
-      if (Found == std::end(ArgsToPreserve))
-        continue;
-      Arg = Arg.drop_front(Found->size());
-      if (Arg.empty() && I + 1 < E) {
-        Args.push_back(CommandLine[I]);
-        Args.push_back(CommandLine[++I]);
-      } else if (Arg.startswith("=")) {
-        Args.push_back(CommandLine[I]);
-      }
-    }
-  }
+  llvm::append_range(Args, AdditionalDriverArgs);
 
   std::string ErrMsg;
   if (int RC = llvm::sys::ExecuteAndWait(Driver, Args, /*Env=*/llvm::None,
@@ -325,12 +298,34 @@
       return;
 
     llvm::StringRef Lang;
+    llvm::SmallVector<llvm::StringRef> AdditionalDriverArgs;
+
+    // These flags will be preserved
+    const llvm::StringRef FlagsToPreserve[] = {
+        "-nostdinc", "--no-standard-includes", "-nostdinc++", "-nobuiltininc"};
+    // Preserve these flags and their values when provided as separate args
+    const llvm::StringRef TwoPartArgsToPreserve[] = {"--sysroot", "-isysroot"};
+    // Preserve these flags and their values when provided as a single arg
+    const llvm::StringRef ArgPrefixesToPreserve[] = {
+        "-isysroot", "--sysroot=", "-specs=", "--specs="};
+
     for (size_t I = 0, E = Cmd.CommandLine.size(); I < E; ++I) {
       llvm::StringRef Arg = Cmd.CommandLine[I];
-      if (Arg == "-x" && I + 1 < E)
-        Lang = Cmd.CommandLine[I + 1];
-      else if (Arg.startswith("-x"))
+      if (Arg == "-x" && I + 1 < E) {
+        Lang = Cmd.CommandLine[++I];
+      } else if (Arg.startswith("-x")) {
         Lang = Arg.drop_front(2).trim();
+      } else if (llvm::is_contained(FlagsToPreserve, Arg)) {
+        AdditionalDriverArgs.push_back(Arg);
+      } else if (llvm::is_contained(TwoPartArgsToPreserve, Arg) && I + 1 < E) {
+        AdditionalDriverArgs.push_back(Arg);
+        AdditionalDriverArgs.push_back(Cmd.CommandLine[++I]);
+      } else if (llvm::any_of(ArgPrefixesToPreserve,
+                              [&Arg](const llvm::StringRef Prefix) {
+                                return Arg.starts_with(Prefix);
+                              })) {
+        AdditionalDriverArgs.push_back(Arg);
+      }
     }
     if (Lang.empty()) {
       llvm::StringRef Ext = llvm::sys::path::extension(File).trim('.');
@@ -349,11 +344,14 @@
       // relative or absolute).
       llvm::sys::fs::make_absolute(Cmd.Directory, Driver);
 
-    if (auto Info =
-            QueriedDrivers.get(/*Key=*/(Driver + ":" + Lang).str(), [&] {
-              return extractSystemIncludesAndTarget(
-                  Driver, Lang, Cmd.CommandLine, QueryDriverRegex);
-            })) {
+    std::string CacheKey = (Driver + ":" + Lang).str();
+    if (!AdditionalDriverArgs.empty())
+      CacheKey += ":" + llvm::join(AdditionalDriverArgs, ":");
+
+    if (auto Info = QueriedDrivers.get(/*Key=*/CacheKey, [&] {
+          return extractSystemIncludesAndTarget(
+              Driver, Lang, AdditionalDriverArgs, QueryDriverRegex);
+        })) {
       setTarget(addSystemIncludes(Cmd, Info->SystemIncludes), Info->Target);
     }
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D139277: [clangd] ... Mitch Johnson via Phabricator via cfe-commits

Reply via email to