From 7aff2bb3d23bb1f4f970d382dc1696392ce99827 Mon Sep 17 00:00:00 2001 From: Bruno Cardoso Lopes Date: Mon, 12 Dec 2016 19:28:25 +0000 Subject: [PATCH] [CrashReproducer] Collect PCH included via -include-pch Collect the necessary input PCH files. Do not try to validate the AST before copying it out because if the crash is in this path, we won't be able to collect it. Instead only check if it's a file containg an AST. rdar://problem/27913709 llvm-svn: 289460 --- clang/lib/Driver/Job.cpp | 5 ++-- clang/lib/Frontend/CompilerInstance.cpp | 33 +++++++++++++++++++++++ clang/test/Modules/crash-vfs-include-pch.m | 43 ++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 clang/test/Modules/crash-vfs-include-pch.m diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp index 68bb4ab..9fd8808 100644 --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -50,9 +50,8 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum, bool ShouldSkip = llvm::StringSwitch(Flag) .Cases("-MF", "-MT", "-MQ", "-serialize-diagnostic-file", true) .Cases("-o", "-coverage-file", "-dependency-file", true) - .Cases("-fdebug-compilation-dir", "-include-pch", true) + .Cases("-fdebug-compilation-dir", "-diagnostic-log-file", true) .Cases("-dwarf-debug-flags", "-ivfsoverlay", true) - .Case("-diagnostic-log-file", true) .Default(false); if (ShouldSkip) return true; @@ -64,7 +63,7 @@ static bool skipArgs(const char *Flag, bool HaveCrashVFS, int &SkipNum, .Cases("-internal-externc-isystem", "-iprefix", true) .Cases("-iwithprefixbefore", "-isystem", "-iquote", true) .Cases("-isysroot", "-I", "-F", "-resource-dir", true) - .Case("-iframework", true) + .Cases("-iframework", "-include-pch", true) .Default(false); if (IsInclude) return HaveCrashVFS ? false : true; diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index cd67166..5c78f81 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -149,6 +149,38 @@ static void collectHeaderMaps(const HeaderSearch &HS, MDC->addFile(Name); } +static void collectIncludePCH(CompilerInstance &CI, + std::shared_ptr MDC) { + const PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); + if (PPOpts.ImplicitPCHInclude.empty()) + return; + + StringRef PCHInclude = PPOpts.ImplicitPCHInclude; + FileManager &FileMgr = CI.getFileManager(); + const DirectoryEntry *PCHDir = FileMgr.getDirectory(PCHInclude); + if (!PCHDir) { + MDC->addFile(PCHInclude); + return; + } + + std::error_code EC; + SmallString<128> DirNative; + llvm::sys::path::native(PCHDir->getName(), DirNative); + vfs::FileSystem &FS = *FileMgr.getVirtualFileSystem(); + SimpleASTReaderListener Validator(CI.getPreprocessor()); + for (vfs::directory_iterator Dir = FS.dir_begin(DirNative, EC), DirEnd; + Dir != DirEnd && !EC; Dir.increment(EC)) { + // Check whether this is an AST file. ASTReader::isAcceptableASTFile is not + // used here since we're not interested in validating the PCH at this time, + // but only to check whether this is a file containing an AST. + if (!ASTReader::readASTFileControlBlock( + Dir->getName(), FileMgr, CI.getPCHContainerReader(), + /*FindModuleFileExtensions=*/false, Validator, + /*ValidateDiagnosticOptions=*/false)) + MDC->addFile(Dir->getName()); + } +} + // Diagnostics static void SetUpDiagnosticLog(DiagnosticOptions *DiagOpts, const CodeGenOptions *CodeGenOpts, @@ -379,6 +411,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { if (ModuleDepCollector) { addDependencyCollector(ModuleDepCollector); collectHeaderMaps(PP->getHeaderSearchInfo(), ModuleDepCollector); + collectIncludePCH(*this, ModuleDepCollector); } for (auto &Listener : DependencyCollectors) diff --git a/clang/test/Modules/crash-vfs-include-pch.m b/clang/test/Modules/crash-vfs-include-pch.m new file mode 100644 index 0000000..78a8e14 --- /dev/null +++ b/clang/test/Modules/crash-vfs-include-pch.m @@ -0,0 +1,43 @@ +// REQUIRES: crash-recovery, shell, system-darwin +// +// RUN: rm -rf %t +// RUN: mkdir -p %t/m %t/out + +// RUN: %clang_cc1 -x objective-c-header -emit-pch %S/Inputs/pch-used.h \ +// RUN: -o %t/out/pch-used.h.pch -fmodules -fimplicit-module-maps \ +// RUN: -fmodules-cache-path=%t/cache -O0 \ +// RUN: -isystem %S/Inputs/System/usr/include + +// RUN: not env FORCE_CLANG_DIAGNOSTICS_CRASH= TMPDIR=%t TEMP=%t TMP=%t \ +// RUN: %clang %s -E -include-pch %t/out/pch-used.h.pch -fmodules -nostdlibinc \ +// RUN: -fimplicit-module-maps -fmodules-cache-path=%t/cache -O0 \ +// RUN: -Xclang -fno-validate-pch -isystem %S/Inputs/System/usr/include \ +// RUN: -o %t/output.E 2>&1 | FileCheck %s + +// 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 + +void f() { SPXTrace(); } +void g() { double x = DBL_MAX; } + +// CHECK: Preprocessed source(s) and associated run script(s) are located at: +// CHECK-NEXT: note: diagnostic msg: {{.*}}.m +// CHECK-NEXT: note: diagnostic msg: {{.*}}.cache + +// CHECKSH: "-include-pch" "/[[INCPATH:.*]]/out/pch-used.h.pch" +// CHECKSH: "crash-vfs-{{[^ ]*}}.m" +// CHECKSH: "-ivfsoverlay" "crash-vfs-{{[^ ]*}}.cache/vfs/vfs.yaml" +// CHECKSH: "-fmodules-cache-path=crash-vfs-{{[^ ]*}}.cache/repro-modules" + +// CHECKYAML: 'case-sensitive': +// CHECKYAML-NEXT: 'use-external-names': 'false', +// CHECKYAML-NEXT: 'overlay-relative': 'true', +// CHECKYAML-NEXT: 'ignore-non-existent-contents': 'false' +// CHECKYAML: 'type': 'directory' +// CHECKYAML: 'name': "/[[PATH:.*]]/out", +// CHECKYAML-NEXT: 'contents': [ +// CHECKYAML-NEXT: { +// CHECKYAML-NEXT: 'type': 'file', +// CHECKYAML-NEXT: 'name': "pch-used.h.pch", +// CHECKYAML-NEXT: 'external-contents': "/[[PATH]]/out/pch-used.h.pch" -- 2.7.4