瀏覽代碼

[CrashReproducer] Always use realpath for destination

When running reproducer scripts we need that original symlinks from the
source filesystem are reproduced in the VFS so that different virtual
paths can map to the same file, allowing the FileManager to share the
same UID between these virtual entries. This avoids all sorts of module
redefinition errors when using frameworks.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@268825 91177308-0d34-0410-b5e6-96231b3b80d8
Bruno Cardoso Lopes 9 年之前
父節點
當前提交
dfc5d12bfb
共有 2 個文件被更改,包括 14 次插入29 次删除
  1. 13 20
      lib/Frontend/ModuleDependencyCollector.cpp
  2. 1 9
      test/Modules/crash-vfs-path-symlink-component.m

+ 13 - 20
lib/Frontend/ModuleDependencyCollector.cpp

@@ -153,47 +153,40 @@ bool ModuleDependencyCollector::getRealPath(StringRef SrcPath,
 std::error_code ModuleDependencyCollector::copyToRoot(StringRef Src) {
   using namespace llvm::sys;
 
-  // We need an absolute path to append to the root.
+  // We need an absolute src path to append to the root.
   SmallString<256> AbsoluteSrc = Src;
   fs::make_absolute(AbsoluteSrc);
-  // Canonicalize to a native path to avoid mixed separator styles.
+  // Canonicalize src to a native path to avoid mixed separator styles.
   path::native(AbsoluteSrc);
   // Remove redundant leading "./" pieces and consecutive separators.
   AbsoluteSrc = path::remove_leading_dotslash(AbsoluteSrc);
 
-  // Canonicalize path by removing "..", "." components.
+  // Canonicalize the source path by removing "..", "." components.
   SmallString<256> CanonicalPath = AbsoluteSrc;
   path::remove_dots(CanonicalPath, /*remove_dot_dot=*/true);
 
   // If a ".." component is present after a symlink component, remove_dots may
   // lead to the wrong real destination path. Let the source be canonicalized
-  // like that but make sure the destination uses the real path.
-  bool HasDotDotInPath =
-      std::count(path::begin(AbsoluteSrc), path::end(AbsoluteSrc), "..") > 0;
+  // like that but make sure we always use the real path for the destination.
   SmallString<256> RealPath;
-  bool HasRemovedSymlinkComponent = HasDotDotInPath &&
-                             getRealPath(AbsoluteSrc, RealPath) &&
-                             !StringRef(CanonicalPath).equals(RealPath);
-
-  // Build the destination path.
+  if (!getRealPath(AbsoluteSrc, RealPath))
+    RealPath = CanonicalPath;
   SmallString<256> Dest = getDest();
-  path::append(Dest, path::relative_path(HasRemovedSymlinkComponent ? RealPath
-                                                             : CanonicalPath));
+  path::append(Dest, path::relative_path(RealPath));
 
   // Copy the file into place.
   if (std::error_code EC = fs::create_directories(path::parent_path(Dest),
                                                    /*IgnoreExisting=*/true))
     return EC;
-  if (std::error_code EC = fs::copy_file(
-          HasRemovedSymlinkComponent ? RealPath : CanonicalPath, Dest))
+  if (std::error_code EC = fs::copy_file(RealPath, Dest))
     return EC;
 
-  // Use the canonical path under the root for the file mapping. Also create
-  // an additional entry for the real path.
+  // Always map a canonical src path to its real path into the YAML, by doing
+  // this we map different virtual src paths to the same entry in the VFS
+  // overlay, which is a way to emulate symlink inside the VFS; this is also
+  // needed for correctness, not doing that can lead to module redifinition
+  // errors.
   addFileMapping(CanonicalPath, Dest);
-  if (HasRemovedSymlinkComponent)
-    addFileMapping(RealPath, Dest);
-
   return std::error_code();
 }
 

+ 1 - 9
test/Modules/crash-vfs-path-symlink-component.m

@@ -43,17 +43,9 @@
 // CHECKYAML: 'case-sensitive':
 // CHECKYAML-NEXT: 'use-external-names': 'false',
 // CHECKYAML-NEXT: 'overlay-relative': 'true',
-// CHECKYAML: 'type': 'directory'
-// CHECKYAML: 'name': "/[[PATH:.*]]/i/usr/include",
-// CHECKYAML-NEXT: 'contents': [
-// CHECKYAML-NEXT:   {
-// CHECKYAML-NEXT:     'type': 'file',
-// CHECKYAML-NEXT:     'name': "module.map",
-// CHECKYAML-NEXT:     'external-contents': "/[[PATH]]/i/usr/include/module.map"
-// CHECKYAML-NEXT:   },
 
 // CHECKYAML: 'type': 'directory'
-// CHECKYAML: 'name': "/[[PATH]]/i/usr",
+// CHECKYAML: 'name': "/[[PATH:.*]]/i/usr",
 // CHECKYAML-NEXT: 'contents': [
 // CHECKYAML-NEXT:   {
 // CHECKYAML-NEXT:     'type': 'file',