forked from OSchip/llvm-project
[clang][modules] Track affecting modules
When compiling a module, its semantics and Clang's behavior are affected by other modules. These modules are typically the **imported** ones. However, during implicit build, some modules end up being compiled and read without being actually imported. This patch starts tracking such modules and serializing them into `.pcm` files. This enables the dependency scanner to construct explicit compilations that mimic implicit build. Reviewed By: benlangmuir Differential Revision: https://reviews.llvm.org/D132430
This commit is contained in:
parent
b20104f644
commit
002bfdd6b1
|
@ -345,6 +345,10 @@ public:
|
|||
/// module depends.
|
||||
llvm::SmallSetVector<Module *, 2> Imports;
|
||||
|
||||
/// The set of top-level modules that affected the compilation of this module,
|
||||
/// but were not imported.
|
||||
llvm::SmallSetVector<Module *, 2> AffectingModules;
|
||||
|
||||
/// Describes an exported module.
|
||||
///
|
||||
/// The pointer is the module being re-exported, while the bit will be true
|
||||
|
|
|
@ -51,6 +51,11 @@ public:
|
|||
ModuleLoadResult() = default;
|
||||
ModuleLoadResult(Module *M) : Storage(M, Normal) {}
|
||||
ModuleLoadResult(LoadResultKind Kind) : Storage(nullptr, Kind) {}
|
||||
ModuleLoadResult(Module *M, LoadResultKind Kind) : Storage(M, Kind) {}
|
||||
|
||||
operator bool() const {
|
||||
return Storage.getInt() == Normal && Storage.getPointer();
|
||||
}
|
||||
|
||||
operator Module *() const { return Storage.getPointer(); }
|
||||
|
||||
|
|
|
@ -860,6 +860,10 @@ private:
|
|||
/// The files that have been included.
|
||||
IncludedFilesSet IncludedFiles;
|
||||
|
||||
/// The set of top-level modules that affected preprocessing, but were not
|
||||
/// imported.
|
||||
llvm::SmallSetVector<Module *, 2> AffectingModules;
|
||||
|
||||
/// The set of known macros exported from modules.
|
||||
llvm::FoldingSet<ModuleMacro> ModuleMacros;
|
||||
|
||||
|
@ -1331,6 +1335,12 @@ public:
|
|||
|
||||
/// \}
|
||||
|
||||
/// Get the set of top-level modules that affected preprocessing, but were not
|
||||
/// imported.
|
||||
const llvm::SmallSetVector<Module *, 2> &getAffectingModules() const {
|
||||
return AffectingModules;
|
||||
}
|
||||
|
||||
/// Mark the file as included.
|
||||
/// Returns true if this is the first time the file was included.
|
||||
bool markIncluded(const FileEntry *File) {
|
||||
|
|
|
@ -829,6 +829,9 @@ enum SubmoduleRecordTypes {
|
|||
/// Specifies the name of the module that will eventually
|
||||
/// re-export the entities in this module.
|
||||
SUBMODULE_EXPORT_AS = 17,
|
||||
|
||||
/// Specifies affecting modules that were not imported.
|
||||
SUBMODULE_AFFECTING_MODULES = 18,
|
||||
};
|
||||
|
||||
/// Record types used within a comments block.
|
||||
|
|
|
@ -689,7 +689,7 @@ private:
|
|||
Module *Mod;
|
||||
|
||||
/// The kind of module reference.
|
||||
enum { Import, Export, Conflict } Kind;
|
||||
enum { Import, Export, Conflict, Affecting } Kind;
|
||||
|
||||
/// The local ID of the module that is being exported.
|
||||
unsigned ID;
|
||||
|
|
|
@ -176,6 +176,13 @@ private:
|
|||
llvm::DenseSet<const Module *> &AddedModules);
|
||||
void addModuleDep(const Module *M, ModuleDeps &MD,
|
||||
llvm::DenseSet<const Module *> &AddedModules);
|
||||
|
||||
/// Traverses the affecting modules and updates \c MD with references to the
|
||||
/// parent \c ModuleDepCollector info.
|
||||
void addAllAffectingModules(const Module *M, ModuleDeps &MD,
|
||||
llvm::DenseSet<const Module *> &AddedModules);
|
||||
void addAffectingModule(const Module *M, ModuleDeps &MD,
|
||||
llvm::DenseSet<const Module *> &AddedModules);
|
||||
};
|
||||
|
||||
/// Collects modular and non-modular dependencies of the main file by attaching
|
||||
|
|
|
@ -2099,7 +2099,7 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
|
|||
<< Module->getFullModuleName()
|
||||
<< SourceRange(Path.front().second, Path.back().second);
|
||||
|
||||
return ModuleLoadResult::MissingExpected;
|
||||
return ModuleLoadResult(Module, ModuleLoadResult::MissingExpected);
|
||||
}
|
||||
|
||||
// Check whether this module is available.
|
||||
|
|
|
@ -1563,6 +1563,8 @@ static bool suggestModule(HeaderSearch &HS, const FileEntry *File,
|
|||
*SuggestedModule = ModuleMap::KnownHeader();
|
||||
return true;
|
||||
}
|
||||
// TODO: Add this module (or just its module map file) into something like
|
||||
// `RequestingModule->AffectingModules`.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2281,6 +2281,13 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
|
|||
if (Imported) {
|
||||
Action = Import;
|
||||
} else if (Imported.isMissingExpected()) {
|
||||
Module *M = static_cast<Module *>(Imported)->getTopLevelModule();
|
||||
if (!BuildingSubmoduleStack.empty()) {
|
||||
if (Imported != BuildingSubmoduleStack.back().M)
|
||||
BuildingSubmoduleStack.back().M->AffectingModules.insert(M);
|
||||
} else {
|
||||
AffectingModules.insert(M);
|
||||
}
|
||||
// We failed to find a submodule that we assumed would exist (because it
|
||||
// was in the directory of an umbrella header, for instance), but no
|
||||
// actual module containing it exists (because the umbrella header is
|
||||
|
|
|
@ -4376,6 +4376,11 @@ ASTReader::ASTReadResult ASTReader::ReadAST(StringRef FileName,
|
|||
Unresolved.Mod->Imports.insert(ResolvedMod);
|
||||
continue;
|
||||
|
||||
case UnresolvedModuleRef::Affecting:
|
||||
if (ResolvedMod)
|
||||
Unresolved.Mod->AffectingModules.insert(ResolvedMod);
|
||||
continue;
|
||||
|
||||
case UnresolvedModuleRef::Export:
|
||||
if (ResolvedMod || Unresolved.IsWildcard)
|
||||
Unresolved.Mod->Exports.push_back(
|
||||
|
@ -5674,6 +5679,18 @@ llvm::Error ASTReader::ReadSubmoduleBlock(ModuleFile &F,
|
|||
}
|
||||
break;
|
||||
|
||||
case SUBMODULE_AFFECTING_MODULES:
|
||||
for (unsigned Idx = 0; Idx != Record.size(); ++Idx) {
|
||||
UnresolvedModuleRef Unresolved;
|
||||
Unresolved.File = &F;
|
||||
Unresolved.Mod = CurrentModule;
|
||||
Unresolved.ID = Record[Idx];
|
||||
Unresolved.Kind = UnresolvedModuleRef::Affecting;
|
||||
Unresolved.IsWildcard = false;
|
||||
UnresolvedModuleRefs.push_back(Unresolved);
|
||||
}
|
||||
break;
|
||||
|
||||
case SUBMODULE_EXPORTS:
|
||||
for (unsigned Idx = 0; Idx + 1 < Record.size(); Idx += 2) {
|
||||
UnresolvedModuleRef Unresolved;
|
||||
|
|
|
@ -883,6 +883,7 @@ void ASTWriter::WriteBlockInfoBlock() {
|
|||
RECORD(SUBMODULE_TOPHEADER);
|
||||
RECORD(SUBMODULE_UMBRELLA_DIR);
|
||||
RECORD(SUBMODULE_IMPORTS);
|
||||
RECORD(SUBMODULE_AFFECTING_MODULES);
|
||||
RECORD(SUBMODULE_EXPORTS);
|
||||
RECORD(SUBMODULE_REQUIRES);
|
||||
RECORD(SUBMODULE_EXCLUDED_HEADER);
|
||||
|
@ -2865,6 +2866,14 @@ void ASTWriter::WriteSubmodules(Module *WritingModule) {
|
|||
Stream.EmitRecord(SUBMODULE_IMPORTS, Record);
|
||||
}
|
||||
|
||||
// Emit the modules affecting compilation that were not imported.
|
||||
if (!Mod->AffectingModules.empty()) {
|
||||
RecordData Record;
|
||||
for (auto *I : Mod->AffectingModules)
|
||||
Record.push_back(getSubmoduleID(I));
|
||||
Stream.EmitRecord(SUBMODULE_AFFECTING_MODULES, Record);
|
||||
}
|
||||
|
||||
// Emit the exports.
|
||||
if (!Mod->Exports.empty()) {
|
||||
RecordData Record;
|
||||
|
|
|
@ -278,6 +278,11 @@ void ModuleDepCollectorPP::EndOfMainFile() {
|
|||
if (!MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude.empty())
|
||||
MDC.addFileDep(MDC.ScanInstance.getPreprocessorOpts().ImplicitPCHInclude);
|
||||
|
||||
for (const Module *M :
|
||||
MDC.ScanInstance.getPreprocessor().getAffectingModules())
|
||||
if (!MDC.isPrebuiltModule(M))
|
||||
DirectModularDeps.insert(M);
|
||||
|
||||
for (const Module *M : DirectModularDeps) {
|
||||
// A top-level module might not be actually imported as a module when
|
||||
// -fmodule-name is used to compile a translation unit that imports this
|
||||
|
@ -389,6 +394,8 @@ ModuleID ModuleDepCollectorPP::handleTopLevelModule(const Module *M) {
|
|||
addAllSubmodulePrebuiltDeps(M, MD, SeenModules);
|
||||
llvm::DenseSet<const Module *> AddedModules;
|
||||
addAllSubmoduleDeps(M, MD, AddedModules);
|
||||
llvm::DenseSet<const Module *> ProcessedModules;
|
||||
addAllAffectingModules(M, MD, ProcessedModules);
|
||||
|
||||
MD.BuildInvocation = MDC.makeInvocationForModuleBuildWithoutOutputs(
|
||||
MD, [&](CompilerInvocation &BuildInvocation) {
|
||||
|
@ -461,6 +468,30 @@ void ModuleDepCollectorPP::addModuleDep(
|
|||
}
|
||||
}
|
||||
|
||||
void ModuleDepCollectorPP::addAllAffectingModules(
|
||||
const Module *M, ModuleDeps &MD,
|
||||
llvm::DenseSet<const Module *> &AddedModules) {
|
||||
addAffectingModule(M, MD, AddedModules);
|
||||
|
||||
for (const Module *SubM : M->submodules())
|
||||
addAllAffectingModules(SubM, MD, AddedModules);
|
||||
}
|
||||
|
||||
void ModuleDepCollectorPP::addAffectingModule(
|
||||
const Module *M, ModuleDeps &MD,
|
||||
llvm::DenseSet<const Module *> &AddedModules) {
|
||||
for (const Module *Affecting : M->AffectingModules) {
|
||||
assert(Affecting == Affecting->getTopLevelModule() &&
|
||||
"Not quite import not top-level module");
|
||||
if (Affecting != M->getTopLevelModule() &&
|
||||
!MDC.isPrebuiltModule(Affecting)) {
|
||||
ModuleID ImportID = handleTopLevelModule(Affecting);
|
||||
if (AddedModules.insert(Affecting).second)
|
||||
MD.ClangModuleDeps.push_back(ImportID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModuleDepCollector::ModuleDepCollector(
|
||||
std::unique_ptr<DependencyOutputOptions> Opts,
|
||||
CompilerInstance &ScanInstance, DependencyConsumer &C,
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
// This test checks that modules loaded during compilation (but not imported)
|
||||
// are still reported as dependencies.
|
||||
|
||||
// RUN: rm -rf %t && mkdir %t
|
||||
// RUN: split-file %s %t
|
||||
|
||||
//--- frameworks/FW.framework/Modules/module.modulemap
|
||||
framework module FW {
|
||||
umbrella header "FW.h"
|
||||
module * { export * }
|
||||
}
|
||||
//--- frameworks/FW.framework/Headers/FW.h
|
||||
//--- frameworks/FW.framework/Modules/module.private.modulemap
|
||||
framework module FW_Private {
|
||||
umbrella header "FW_Private.h"
|
||||
module * { export * }
|
||||
}
|
||||
//--- frameworks/FW.framework/PrivateHeaders/FW_Private.h
|
||||
#include "One.h"
|
||||
//--- frameworks/FW.framework/PrivateHeaders/One.h
|
||||
//--- frameworks/FW.framework/PrivateHeaders/Two.h
|
||||
|
||||
// Let's check we report the non-imported modular dependencies for a translation unit.
|
||||
|
||||
//--- from_tu.cdb.json.template
|
||||
[{
|
||||
"file": "DIR/from_tu.m",
|
||||
"directory": "DIR",
|
||||
"command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_tu.m -o DIR/from_tu.o"
|
||||
}]
|
||||
//--- from_tu.m
|
||||
#include "FW/FW.h"
|
||||
#include "FW/Two.h"
|
||||
|
||||
// RUN: sed -e "s|DIR|%/t|g" %t/from_tu.cdb.json.template > %t/from_tu.cdb.json
|
||||
// RUN: clang-scan-deps -compilation-database %t/from_tu.cdb.json -format experimental-full > %t/from_tu_result.json
|
||||
// RUN: cat %t/from_tu_result.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK_TU
|
||||
// CHECK_TU: {
|
||||
// CHECK_TU-NEXT: "modules": [
|
||||
// CHECK_TU-NEXT: {
|
||||
// CHECK_TU-NEXT: "clang-module-deps": [],
|
||||
// CHECK_TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_TU-NEXT: "command-line": [
|
||||
// CHECK_TU: ],
|
||||
// CHECK_TU-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_TU-NEXT: "file-deps": [
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
|
||||
// CHECK_TU-NEXT: ],
|
||||
// CHECK_TU-NEXT: "name": "FW"
|
||||
// CHECK_TU-NEXT: },
|
||||
// CHECK_TU-NEXT: {
|
||||
// CHECK_TU-NEXT: "clang-module-deps": [],
|
||||
// CHECK_TU-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
|
||||
// CHECK_TU-NEXT: "command-line": [
|
||||
// CHECK_TU: ],
|
||||
// CHECK_TU-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_TU-NEXT: "file-deps": [
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
|
||||
// CHECK_TU-NEXT: ],
|
||||
// CHECK_TU-NEXT: "name": "FW_Private"
|
||||
// CHECK_TU-NEXT: }
|
||||
// CHECK_TU-NEXT: ],
|
||||
// CHECK_TU-NEXT: "translation-units": [
|
||||
// CHECK_TU-NEXT: {
|
||||
// CHECK_TU-NEXT: "clang-context-hash": "{{.*}}",
|
||||
// CHECK_TU-NEXT: "clang-module-deps": [
|
||||
// CHECK_TU-NEXT: {
|
||||
// CHECK_TU-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_TU-NEXT: "module-name": "FW"
|
||||
// CHECK_TU-NEXT: },
|
||||
// CHECK_TU-NEXT: {
|
||||
// CHECK_TU-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_TU-NEXT: "module-name": "FW_Private"
|
||||
// CHECK_TU-NEXT: }
|
||||
// CHECK_TU-NEXT: ],
|
||||
// CHECK_TU-NEXT: "command-line": [
|
||||
// CHECK_TU: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
|
||||
// CHECK_TU: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
|
||||
// CHECK_TU: ],
|
||||
// CHECK_TU-NEXT: "file-deps": [
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/from_tu.m",
|
||||
// CHECK_TU-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h"
|
||||
// CHECK_TU-NEXT: ],
|
||||
// CHECK_TU-NEXT: "input-file": "[[PREFIX]]/from_tu.m"
|
||||
// CHECK_TU-NEXT: }
|
||||
// CHECK_TU-NEXT: ]
|
||||
// CHECK_TU-NEXT: }
|
||||
|
||||
// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW > %t/FW.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t/from_tu_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t/from_tu_result.json --tu-index=0 > %t/tu.rsp
|
||||
// RUN: %clang @%t/FW.cc1.rsp
|
||||
// RUN: %clang @%t/FW_Private.cc1.rsp
|
||||
// RUN: %clang @%t/tu.rsp
|
||||
|
||||
// Now let's check we report the dependencies for modules as well.
|
||||
|
||||
//--- from_module.cdb.json.template
|
||||
[{
|
||||
"file": "DIR/from_module.m",
|
||||
"directory": "DIR",
|
||||
"command": "clang -fmodules -fmodules-cache-path=DIR/cache -iframework DIR/frameworks -c DIR/from_module.m -o DIR/from_module.o"
|
||||
}]
|
||||
//--- module.modulemap
|
||||
module Mod { header "Mod.h" }
|
||||
//--- Mod.h
|
||||
#include "FW/FW.h"
|
||||
#include "FW/Two.h"
|
||||
//--- from_module.m
|
||||
#include "Mod.h"
|
||||
|
||||
// RUN: sed -e "s|DIR|%/t|g" %t/from_module.cdb.json.template > %t/from_module.cdb.json
|
||||
// RUN: clang-scan-deps -compilation-database %t/from_module.cdb.json -format experimental-full > %t/from_module_result.json
|
||||
// RUN: cat %t/from_module_result.json | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t --check-prefixes=CHECK_MODULE
|
||||
// CHECK_MODULE: {
|
||||
// CHECK_MODULE-NEXT: "modules": [
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "clang-module-deps": [],
|
||||
// CHECK_MODULE-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_MODULE-NEXT: "command-line": [
|
||||
// CHECK_MODULE: ],
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "file-deps": [
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Headers/FW.h",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap"
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "name": "FW"
|
||||
// CHECK_MODULE-NEXT: },
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "clang-module-deps": [],
|
||||
// CHECK_MODULE-NEXT: "clang-modulemap-file": "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
|
||||
// CHECK_MODULE-NEXT: "command-line": [
|
||||
// CHECK_MODULE: ],
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "file-deps": [
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/FW_Private.h",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/One.h"
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "name": "FW_Private"
|
||||
// CHECK_MODULE-NEXT: },
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "clang-module-deps": [
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "module-name": "FW"
|
||||
// CHECK_MODULE-NEXT: },
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "module-name": "FW_Private"
|
||||
// CHECK_MODULE-NEXT: }
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "clang-modulemap-file": "[[PREFIX]]/module.modulemap",
|
||||
// CHECK_MODULE-NEXT: "command-line": [
|
||||
// CHECK_MODULE: "-fmodule-file={{.*}}/FW-{{.*}}.pcm"
|
||||
// CHECK_MODULE: "-fmodule-file={{.*}}/FW_Private-{{.*}}.pcm"
|
||||
// CHECK_MODULE: ],
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "file-deps": [
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/Mod.h"
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.modulemap",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/Modules/module.private.modulemap",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/frameworks/FW.framework/PrivateHeaders/Two.h",
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/module.modulemap"
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "name": "Mod"
|
||||
// CHECK_MODULE-NEXT: }
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "translation-units": [
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "clang-context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "clang-module-deps": [
|
||||
// CHECK_MODULE-NEXT: {
|
||||
// CHECK_MODULE-NEXT: "context-hash": "{{.*}}",
|
||||
// CHECK_MODULE-NEXT: "module-name": "Mod"
|
||||
// CHECK_MODULE-NEXT: }
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "command-line": [
|
||||
// CHECK_MODULE: ],
|
||||
// CHECK_MODULE-NEXT: "file-deps": [
|
||||
// CHECK_MODULE-NEXT: "[[PREFIX]]/from_module.m"
|
||||
// CHECK_MODULE-NEXT: ],
|
||||
// CHECK_MODULE-NEXT: "input-file": "[[PREFIX]]/from_module.m"
|
||||
// CHECK_MODULE-NEXT: }
|
||||
// CHECK_MODULE-NEXT: ]
|
||||
// CHECK_MODULE-NEXT: }
|
||||
|
||||
// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW > %t/FW.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t/from_module_result.json --module-name=FW_Private > %t/FW_Private.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t/from_module_result.json --module-name=Mod > %t/Mod.cc1.rsp
|
||||
// RUN: %deps-to-rsp %t/from_module_result.json --tu-index=0 > %t/tu.rsp
|
||||
// RUN: %clang @%t/FW.cc1.rsp
|
||||
// RUN: %clang @%t/FW_Private.cc1.rsp
|
||||
// RUN: %clang @%t/Mod.cc1.rsp
|
||||
// RUN: %clang @%t/tu.rsp
|
Loading…
Reference in New Issue