bruno created this revision. bruno added reviewers: rsmith, benlangmuir, klimek. bruno added subscribers: aprantl, dexonsmith, cfe-commits.
The reproducer script (generated by the crash reproducer) invokes clang and tries to rebuild modules using the headers in the .cache/vfs directory. Depending on the order that modules are constructed it is possible that there's a mismatch between the directory that a module was constructed and the path that it was found: fatal error: module '_Builtin_stddef_max_align_t' was built in directory '/Users/bruno/Dev/install/clang/bin/../lib/clang/<ver>/include' but now resides in directory '/<path_to>.cache/vfs/Users/bruno/Dev/install/clang/lib/clang/<ver>/include' This happens because getFile() can leak the original path depending on the way it's accessed. This seems to be known issue and one that demands a lot of work to get rid of, according to: [cfe-dev] Module maps, __FILE__ and lazy stat'ing of header http://lists.llvm.org/pipermail/cfe-dev/2014-July/038273.html I tried a couple of fixes to the issue but this is the less invasive I could come up with. This fixes the issue by first looking into modules by using virtual dir paths instead of the real ones. Let me know if there's a better solution or whether I'm missing something. With this change on Darwin we are able to simulate a crash for a simple application using "Foundation/Foundation.h" (which relies on a bunch of different frameworks and headers) and successfully rebuild all the modules by relying solely at the VFS overlay. http://reviews.llvm.org/D18849 Files: lib/Lex/HeaderSearch.cpp test/Modules/Inputs/crash-recovery/Users/bar/a.h test/Modules/Inputs/crash-recovery/Users/bar/bar.h test/Modules/Inputs/crash-recovery/Users/bar/module.modulemap test/Modules/Inputs/crash-recovery/Users/foo/foo.h test/Modules/Inputs/crash-recovery/Users/foo/module.modulemap test/Modules/crash-vfs-module-redefinition.m
Index: test/Modules/crash-vfs-module-redefinition.m =================================================================== --- /dev/null +++ test/Modules/crash-vfs-module-redefinition.m @@ -0,0 +1,38 @@ +// REQUIRES: crash-recovery, system-darwin, shell + +// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? +// XFAIL: mingw32 + +// RUN: rm -rf %t +// RUN: mkdir -p %t/i %t/m %t + +// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: %clang -fsyntax-only -nostdinc %s \ +// RUN: -I %S/Inputs/crash-recovery/Users/bar \ +// RUN: -I %S/Inputs/crash-recovery/Users -isysroot %/t/i/ \ +// RUN: -fmodules -fmodules-cache-path=%t/m/ 2>&1 | FileCheck %s + +// RUN: FileCheck --check-prefix=CHECKSRC %s -input-file %t/crash-vfs-*.m +// RUN: FileCheck --check-prefix=CHECKSH %s -input-file %t/crash-vfs-*.sh + +#include <foo/foo.h> + +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK-NEXT: note: diagnostic msg: {{.*}}.m +// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache + +// CHECKSRC: @import foo; + +// CHECKSH: # Crash reproducer +// CHECKSH-NEXT: # Driver args: "-fsyntax-only" +// CHECKSH-NEXT: # Original command: {{.*$}} +// CHECKSH-NEXT: "-cc1" +// CHECKSH: "-resource-dir" +// CHECKSH: "-isysroot" "{{[^"]*}}/i/" +// CHECKSH: "crash-vfs-{{[^ ]*}}.m" +// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml" +// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/modules" + +// RUN: cd %t +// RUN: chmod 755 crash-vfs-*.sh +// RUN: ./crash-vfs-*.sh Index: test/Modules/Inputs/crash-recovery/Users/foo/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/foo/module.modulemap @@ -0,0 +1,3 @@ +module foo [system] [extern_c] { + header "foo.h" +} Index: test/Modules/Inputs/crash-recovery/Users/foo/foo.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/foo/foo.h @@ -0,0 +1 @@ +#include <a.h> Index: test/Modules/Inputs/crash-recovery/Users/bar/module.modulemap =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/bar/module.modulemap @@ -0,0 +1,3 @@ +module bar [system] [extern_c] { + header "bar.h" +} Index: test/Modules/Inputs/crash-recovery/Users/bar/bar.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/bar/bar.h @@ -0,0 +1,6 @@ +#ifndef __CLANG_MAX_ALIGN_T_DEFINED +#define __CLANG_MAX_ALIGN_T_DEFINED + +typedef long double max_align_t; + +#endif Index: test/Modules/Inputs/crash-recovery/Users/bar/a.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/bar/a.h @@ -0,0 +1,6 @@ +#ifndef _BAR_H +#define _BAR_H + +#include "bar.h" + +#endif Index: lib/Lex/HeaderSearch.cpp =================================================================== --- lib/Lex/HeaderSearch.cpp +++ lib/Lex/HeaderSearch.cpp @@ -1147,10 +1147,36 @@ bool HeaderSearch::findUsableModuleForHeader( const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { + using namespace llvm::sys; if (File && SuggestedModule) { + // FIXME: This is a workaround on a limitation: the file manager leaks + // original paths for virtual file requests. This leads to modules being + // inconsistently built with virtual and searched through real paths, or + // vice-versa, which ends up in module relocation errors. Fix that by + // trying to find the module map through the virtual one first. Since + // real paths that go through the VFS are canonicalized to do not contain + // path traversal components, take that into account. + SmallVector<std::string, 2> FilePaths; + + StringRef FileName = File->getName(); + SmallString<256> RootName = StringRef(Root->getName()); + path::remove_dots(RootName, true/*remove_dot_dot*/); + auto Pos = FileName.find(RootName); + if (path::is_absolute(FileName) && Pos != StringRef::npos && Pos > 0) { + StringRef Suffix = FileName.drop_front(Pos + RootName.str().size()); + SmallString<256> NewFileName = StringRef(Root->getName()); + path::append(NewFileName, Suffix); + FilePaths.push_back(NewFileName.str()); + } + FilePaths.push_back(FileName.str()); + // If there is a module that corresponds to this header, suggest it. - hasModuleMap(File->getName(), Root, IsSystemHeaderDir); - *SuggestedModule = findModuleForHeader(File); + for (auto &F : FilePaths) { + hasModuleMap(F, Root, IsSystemHeaderDir); + *SuggestedModule = findModuleForHeader(File); + if (SuggestedModule) + break; + } } return true; }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits