jfb updated this revision to Diff 214448.
jfb marked an inline comment as done.
jfb added a comment.

- Rename option.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D65986/new/

https://reviews.llvm.org/D65986

Files:
  clang/include/clang/Driver/Driver.h
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/Driver.cpp
  clang/test/Driver/workdir.py

Index: clang/test/Driver/workdir.py
===================================================================
--- /dev/null
+++ clang/test/Driver/workdir.py
@@ -0,0 +1,49 @@
+# Check that we can change the working directory mode between 'os' and
+# 'virtual', which affects the maximum path length that clang can deal with.
+
+# UNSUPPORTED: system-windows
+
+# RUN: rm -rf xxx*
+# RUN: python %s > %t
+# RUN: cat %t | xargs not %clang                    2>&1 | FileCheck %s --check-prefix=VIRTUAL
+# RUN: cat %t | xargs not %clang -iworkdir=virtual  2>&1 | FileCheck %s --check-prefix=VIRTUAL
+# RUN: cat %t | xargs     %clang -iworkdir=os
+
+# VIRTUAL: error: no such file or directory:
+
+import os
+import subprocess
+
+current = os.path.realpath(os.curdir)
+name_max = int(subprocess.check_output("getconf NAME_MAX %s" % current, shell=True))
+path_max = int(subprocess.check_output("getconf PATH_MAX %s" % current, shell=True))
+assert name_max > 0, 'we want to test NAME_MAX properties, knowing its value is required'
+assert path_max > 0, 'we want to test PATH_MAX properties, knowing its value is required'
+
+filename = 'o.c'
+code = 'int main() { return 0; }\n'
+
+relative = ''
+absolute = current
+
+# Create directories which almost, but not quite, exhaust PATH_MAX.
+target_len = path_max - 1
+while len(absolute) < target_len:
+    new_name_len = min(target_len - len(absolute) - 1, name_max)
+    absolute = os.path.join(absolute, 'x' * new_name_len)
+    relative = os.path.join(relative, 'x' * new_name_len)
+    os.mkdir(relative)
+    assert os.path.exists(absolute), 'creating a directory must succeed'
+    assert os.path.exists(relative), 'creating a directory must succeed'
+
+# Create a file whose relative path doesn't exceed PATH_MAX, but whose absolute
+# path does.
+file_relative_path = os.path.join(relative, filename)
+with open(file_relative_path, 'w') as f:
+    f.write(code)
+
+assert os.path.exists(file_relative_path), 'the relative path should work because it is still smaller than PATH_MAX'
+assert not os.path.exists(os.path.join(absolute, filename)), 'the absolute path should exceed PATH_MAX'
+
+# Print out the relative path so lit can pass it to clang.
+print file_relative_path
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -131,10 +131,6 @@
       CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true),
       GenReproducer(false), SuppressMissingInputWarning(false) {
 
-  // Provide a sane fallback if no VFS is specified.
-  if (!this->VFS)
-    this->VFS = llvm::vfs::createPhysicalFileSystem().release();
-
   Name = llvm::sys::path::filename(ClangExecutable);
   Dir = llvm::sys::path::parent_path(ClangExecutable);
   InstalledDir = Dir; // Provide a sensible default installed dir.
@@ -150,6 +146,42 @@
   ResourceDir = GetResourcesPath(ClangExecutable, CLANG_RESOURCE_DIR);
 }
 
+void Driver::ParseVFSMode(ArrayRef<const char *> Args) {
+  const std::string OptionPrefix =
+      getOpts().getOption(options::OPT_iworkdir).getPrefixedName();
+  enum class Workdir { Unknown, OS, Virtual } Mode = Workdir::Unknown;
+  for (const char *ArgPtr : Args) {
+    if (!ArgPtr)
+      continue;
+    const StringRef Arg = ArgPtr;
+    if (!Arg.startswith(OptionPrefix))
+      continue;
+    const StringRef Value = Arg.drop_front(OptionPrefix.size());
+    Workdir M = llvm::StringSwitch<Workdir>(Value)
+                    .Case("os", Workdir::OS)
+                    .Case("virtual", Workdir::Virtual)
+                    .Default(Workdir::Unknown);
+    if (M == Workdir::Unknown) {
+      Diag(diag::err_drv_unsupported_option_argument) << OptionPrefix << Value;
+      break;
+    }
+    Mode = M;
+  }
+
+  switch (Mode) {
+  case Workdir::Unknown:
+    if (!this->VFS)
+      this->VFS = llvm::vfs::createPhysicalFileSystem().release();
+    break;
+  case Workdir::Virtual:
+    this->VFS = llvm::vfs::createPhysicalFileSystem().release();
+    break;
+  case Workdir::OS:
+    this->VFS = llvm::vfs::getRealFileSystem().get();
+    break;
+  }
+}
+
 void Driver::ParseDriverMode(StringRef ProgramName,
                              ArrayRef<const char *> Args) {
   if (ClangNameParts.isEmpty())
@@ -946,6 +978,10 @@
     }
   }
 
+  // We might try accessing the VFS fairly early, so make sure we have the
+  // right one.
+  ParseVFSMode(ArgList.slice(1));
+
   // We look for the driver mode option early, because the mode can affect
   // how other options are parsed.
   ParseDriverMode(ClangExecutable, ArgList.slice(1));
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2007,6 +2007,9 @@
   Flags<[CC1Option]>;
 def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>,
   HelpText<"Overlay the virtual filesystem described by file over the real file system">;
+def iworkdir : Joined<["-"], "iworkdir=">, Group<clang_i_Group>, Flags<[CC1Option, HelpHidden]>,
+  HelpText<"When looking up file, use the working directory provided by the operating system, or by the virtual file system.">,
+  Values<"os,virtual">;
 def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>;
 def keep__private__externs : Flag<["-"], "keep_private_externs">;
 def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>,
Index: clang/include/clang/Driver/Driver.h
===================================================================
--- clang/include/clang/Driver/Driver.h
+++ clang/include/clang/Driver/Driver.h
@@ -355,11 +355,13 @@
   /// @name Driver Steps
   /// @{
 
-  /// ParseDriverMode - Look for and handle the driver mode option in Args.
+  /// Look for and handle the VFS mode option in Args.
+  void ParseVFSMode(ArrayRef<const char *> Args);
+
+  /// Look for and handle the driver mode option in Args.
   void ParseDriverMode(StringRef ProgramName, ArrayRef<const char *> Args);
 
-  /// ParseArgStrings - Parse the given list of strings into an
-  /// ArgList.
+  /// Parse the given list of strings into an ArgList.
   llvm::opt::InputArgList ParseArgStrings(ArrayRef<const char *> Args,
                                           bool IsClCompatMode,
                                           bool &ContainsError);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to