Index: include/clang/Frontend/Utils.h =================================================================== --- include/clang/Frontend/Utils.h +++ include/clang/Frontend/Utils.h @@ -77,7 +77,7 @@ /// interface. class DependencyCollector { public: - void attachToPreprocessor(Preprocessor &PP); + virtual void attachToPreprocessor(Preprocessor &PP); virtual void attachToASTReader(ASTReader &R); llvm::ArrayRef getDependencies() const { return Dependencies; } @@ -136,6 +136,7 @@ VFSWriter.addFileMapping(VPath, RPath); } + void attachToPreprocessor(Preprocessor &PP) override; void attachToASTReader(ASTReader &R) override; void writeFileMap(); Index: include/clang/Lex/ModuleMap.h =================================================================== --- include/clang/Lex/ModuleMap.h +++ include/clang/Lex/ModuleMap.h @@ -50,6 +50,11 @@ /// \param IsSystem Whether this is a module map from a system include path. virtual void moduleMapFileRead(SourceLocation FileStart, const FileEntry &File, bool IsSystem) {} + + /// \brief Called when a header is added during module map parsing. + /// + /// \param File The header file itself. + virtual void moduleMapAddHeader(const FileEntry &File) {} }; class ModuleMap { Index: lib/Frontend/ModuleDependencyCollector.cpp =================================================================== --- lib/Frontend/ModuleDependencyCollector.cpp +++ lib/Frontend/ModuleDependencyCollector.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Frontend/Utils.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/iterator_range.h" @@ -22,7 +23,7 @@ using namespace clang; namespace { -/// Private implementation for ModuleDependencyCollector +/// Private implementations for ModuleDependencyCollector class ModuleDependencyListener : public ASTReaderListener { ModuleDependencyCollector &Collector; public: @@ -36,12 +37,30 @@ return true; } }; + +struct ModuleDependencyMMCallbacks : public ModuleMapCallbacks { + ModuleDependencyCollector &Collector; + ModuleDependencyMMCallbacks(ModuleDependencyCollector &Collector) + : Collector(Collector) {} + + void moduleMapAddHeader(const FileEntry &File) override { + StringRef HeaderPath = File.getName(); + if (llvm::sys::path::is_absolute(HeaderPath)) + Collector.addFile(HeaderPath); + } +}; + } void ModuleDependencyCollector::attachToASTReader(ASTReader &R) { R.addListener(llvm::make_unique(*this)); } +void ModuleDependencyCollector::attachToPreprocessor(Preprocessor &PP) { + PP.getHeaderSearchInfo().getModuleMap().addModuleMapCallbacks( + llvm::make_unique(*this)); +} + void ModuleDependencyCollector::writeFileMap() { if (Seen.empty()) return; Index: lib/Lex/ModuleMap.cpp =================================================================== --- lib/Lex/ModuleMap.cpp +++ lib/Lex/ModuleMap.cpp @@ -812,6 +812,10 @@ HeaderInfo.MarkFileModuleHeader(Header.Entry, Role, isCompilingModuleHeader); } + + // Notify callbacks that we just added a new header. + for (const auto &Cb : Callbacks) + Cb->moduleMapAddHeader(*Header.Entry); } void ModuleMap::excludeHeader(Module *Mod, Module::Header Header) { Index: test/Modules/Inputs/crash-recovery/usr/include/module.map =================================================================== --- test/Modules/Inputs/crash-recovery/usr/include/module.map +++ test/Modules/Inputs/crash-recovery/usr/include/module.map @@ -3,4 +3,14 @@ module stdio { header "stdio.h" } + + module pthread { + header "pthread.h" + export * + + module impl { + header "pthread_impl.h" + export * + } + } } Index: test/Modules/Inputs/crash-recovery/usr/include/pthread.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/usr/include/pthread.h @@ -0,0 +1 @@ +#include "pthread/pthread_impl.h" Index: test/Modules/Inputs/crash-recovery/usr/include/pthread/pthread_impl.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/usr/include/pthread/pthread_impl.h @@ -0,0 +1 @@ +#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 Index: test/Modules/Inputs/crash-recovery/usr/include/pthread_impl.h =================================================================== --- /dev/null +++ test/Modules/Inputs/crash-recovery/usr/include/pthread_impl.h @@ -0,0 +1 @@ +#define _PTHREAD_MUTEX_SIG_init 0x32AAABA7 Index: test/Modules/crash-vfs-path-symlink-topheader.m =================================================================== --- /dev/null +++ test/Modules/crash-vfs-path-symlink-topheader.m @@ -0,0 +1,50 @@ +// REQUIRES: crash-recovery, shell + +// FIXME: This XFAIL is cargo-culted from crash-report.c. Do we need it? +// XFAIL: mingw32 + +// Test clang can collect symbolic link headers used in modules. +// crash reproducer if there's a symbolic link header file used in a module. + +// RUN: rm -rf %t +// RUN: mkdir -p %t/i %t/m %t %t/sysroot +// RUN: cp -a %S/Inputs/crash-recovery/usr %t/i/ +// RUN: rm -f %t/i/usr/include/pthread_impl.h +// RUN: ln -s pthread/pthread_impl.h %t/i/usr/include/pthread_impl.h + +// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: %clang -fsyntax-only %s -I %/t/i -isysroot %/t/sysroot/ \ +// 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 +// RUN: FileCheck --check-prefix=CHECKYAML %s -input-file \ +// RUN: %t/crash-vfs-*.cache/vfs/vfs.yaml +// RUN: find %t/crash-vfs-*.cache/vfs | \ +// RUN: grep "usr/include/pthread_impl.h" | count 1 + +#include "usr/include/stdio.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 cstd.stdio; + +// CHECKSH: # Crash reproducer +// CHECKSH-NEXT: # Driver args: "-fsyntax-only" +// CHECKSH-NEXT: # Original command: {{.*$}} +// CHECKSH-NEXT: "-cc1" +// CHECKSH: "-isysroot" "{{[^"]*}}/sysroot/" +// CHECKSH-NOT: "-fmodules-cache-path=" +// CHECKSH: "crash-vfs-{{[^ ]*}}.m" +// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml" + +// CHECKYAML: 'type': 'directory', +// CHECKYAML: 'name': "", +// CHECKYAML-NEXT: 'contents': [ +// CHECKYAML-NEXT: { +// CHECKYAML-NEXT: 'type': 'file', +// CHECKYAML-NEXT: 'name': "pthread_impl.h", +// CHECKYAML-NEXT: 'external-contents': "/{{.*}}/i/usr/include/pthread_impl.h" +// CHECKYAML-NEXT: },