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 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; } 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: 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/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/foo/foo.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/Users/foo/foo.h @@ -0,0 +1 @@ +#include 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/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 + +// 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