Skip to content

Commit 5a302e4

Browse files
authored
Merge pull request #8575 from apple/eng/blangmuir/finclude-tree-preserve-pch-path-6.0
[cas] Add cc1 option -finclude-tree-preserve-pch-path
2 parents c5ac128 + d189ec2 commit 5a302e4

File tree

10 files changed

+113
-24
lines changed

10 files changed

+113
-24
lines changed

clang/include/clang/CAS/IncludeTree.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -794,12 +794,12 @@ class IncludeTreeRoot : public IncludeTreeBase<IncludeTreeRoot> {
794794
return IncludeTree::FileList(std::move(*Node));
795795
}
796796

797-
Expected<std::optional<StringRef>> getPCHBuffer() {
797+
Expected<std::optional<IncludeTree::File>> getPCH() {
798798
if (std::optional<ObjectRef> Ref = getPCHRef()) {
799799
auto Node = getCAS().getProxy(*Ref);
800800
if (!Node)
801801
return Node.takeError();
802-
return Node->getData();
802+
return IncludeTree::File(std::move(*Node));
803803
}
804804
return std::nullopt;
805805
}

clang/include/clang/Driver/Options.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7119,6 +7119,11 @@ defm casid_output : BoolFOption<"casid-output",
71197119
" write a CASID for the output file.">,
71207120
NegFlag<SetFalse>>;
71217121

7122+
defm include_tree_preserve_pch_path : BoolFOption<"include-tree-preserve-pch-path",
7123+
FrontendOpts<"IncludeTreePreservePCHPath">, DefaultFalse,
7124+
PosFlag<SetTrue, [], "Keep the original PCH path in include-tree rather than canonicalizing">,
7125+
NegFlag<SetFalse>>;
7126+
71227127
/// BEGIN MCCAS
71237128
defm cas_backend : BoolFOption<"cas-backend",
71247129
CodeGenOpts<"UseCASBackend">, DefaultFalse,

clang/include/clang/Frontend/FrontendOptions.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,11 @@ class FrontendOptions {
372372
/// caching of compilation outputs. This is used for testing purposes.
373373
unsigned DisableCachedCompileJobReplay : 1;
374374

375+
/// Whether to preserve the original PCH path in the include-tree, or to
376+
/// canonicalize it to a fixed value. Setting this to \c true allows the use
377+
/// of gmodules with PCH and include tree.
378+
unsigned IncludeTreePreservePCHPath : 1;
379+
375380
/// Keep the diagnostic client open for receiving diagnostics after the source
376381
/// files have been processed.
377382
unsigned MayEmitDiagnosticsAfterProcessingSourceFiles : 1;
@@ -593,6 +598,7 @@ class FrontendOptions {
593598
BuildingImplicitModuleUsesLock(true), ModulesEmbedAllFiles(false),
594599
IncludeTimestamps(true), UseTemporary(true), CacheCompileJob(false),
595600
ForIncludeTreeScan(false), DisableCachedCompileJobReplay(false),
601+
IncludeTreePreservePCHPath(false),
596602
MayEmitDiagnosticsAfterProcessingSourceFiles(false),
597603
WriteOutputAsCASID(false), AllowPCMWithCompilerErrors(false),
598604
ModulesShareFileManager(true), EmitSymbolGraph(false),

clang/lib/CAS/IncludeTree.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -832,10 +832,13 @@ llvm::Error IncludeTree::APINotes::forEachAPINotes(
832832
}
833833

834834
llvm::Error IncludeTreeRoot::print(llvm::raw_ostream &OS, unsigned Indent) {
835-
if (std::optional<ObjectRef> PCHRef = getPCHRef()) {
835+
std::optional<IncludeTree::File> PCH;
836+
if (llvm::Error E = getPCH().moveInto(PCH))
837+
return E;
838+
if (PCH) {
836839
OS.indent(Indent) << "(PCH) ";
837-
getCAS().getID(*PCHRef).print(OS);
838-
OS << '\n';
840+
if (llvm::Error E = PCH->print(OS))
841+
return E;
839842
}
840843
std::optional<cas::IncludeTree> MainTree;
841844
if (llvm::Error E = getMainFileTree().moveInto(MainTree))

clang/lib/Frontend/FrontendAction.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -998,7 +998,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
998998
};
999999

10001000
std::optional<cas::IncludeTreeRoot> IncludeTreeRoot;
1001-
std::optional<StringRef> IncludeTreePCHBuffer;
1001+
std::optional<cas::IncludeTree::File> IncludeTreePCH;
10021002
if (Input.isIncludeTree()) {
10031003
if (llvm::Error E = cas::IncludeTreeRoot::get(CI.getOrCreateObjectStore(),
10041004
Input.getIncludeTree())
@@ -1012,8 +1012,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
10121012
CI.getPreprocessor().setPPCachedActions(std::move(*PPCachedAct));
10131013
CI.getFrontendOpts().IncludeTimestamps = false;
10141014

1015-
if (llvm::Error E =
1016-
IncludeTreeRoot->getPCHBuffer().moveInto(IncludeTreePCHBuffer))
1015+
if (llvm::Error E = IncludeTreeRoot->getPCH().moveInto(IncludeTreePCH))
10171016
return reportError(std::move(E));
10181017

10191018
auto ModMap = IncludeTreeRoot->getModuleMap();
@@ -1148,7 +1147,7 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
11481147
CI.getASTContext().setExternalSource(source);
11491148
} else if (CI.getLangOpts().Modules ||
11501149
!CI.getPreprocessorOpts().ImplicitPCHInclude.empty() ||
1151-
IncludeTreePCHBuffer) {
1150+
IncludeTreePCH) {
11521151
// Use PCM or PCH.
11531152
assert(hasPCHSupport() && "This action does not have PCH support!");
11541153
ASTDeserializationListener *DeserialListener =
@@ -1167,16 +1166,17 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
11671166
DeleteDeserialListener = true;
11681167
}
11691168
if (!CI.getPreprocessorOpts().ImplicitPCHInclude.empty() ||
1170-
IncludeTreePCHBuffer) {
1169+
IncludeTreePCH) {
11711170
StringRef PCHPath;
11721171
DisableValidationForModuleKind DisableValidation;
11731172
std::unique_ptr<llvm::MemoryBuffer> PCHBuffer;
1174-
if (IncludeTreePCHBuffer) {
1175-
PCHPath = "<PCH>";
1173+
if (IncludeTreePCH) {
11761174
// No need to do any validation.
11771175
DisableValidation = DisableValidationForModuleKind::All;
1178-
PCHBuffer =
1179-
llvm::MemoryBuffer::getMemBuffer(*IncludeTreePCHBuffer, PCHPath);
1176+
if (llvm::Error E =
1177+
IncludeTreePCH->getMemoryBuffer().moveInto(PCHBuffer))
1178+
return reportError(std::move(E));
1179+
PCHPath = PCHBuffer->getBufferIdentifier();
11801180
} else {
11811181
PCHPath = CI.getPreprocessorOpts().ImplicitPCHInclude;
11821182
DisableValidation =

clang/lib/Tooling/DependencyScanning/IncludeTreeActionController.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,9 +644,17 @@ IncludeTreeBuilder::finishIncludeTree(CompilerInstance &ScanInstance,
644644
FM.getObjectRefForFileContent(PPOpts.ImplicitPCHInclude);
645645
if (!CASContents)
646646
return llvm::errorCodeToError(CASContents.getError());
647-
PCHRef = **CASContents;
648647

649-
return Error::success();
648+
StringRef PCHFilename = "<PCH>";
649+
if (NewInvocation.getFrontendOpts().IncludeTreePreservePCHPath)
650+
PCHFilename = PPOpts.ImplicitPCHInclude;
651+
652+
auto PCHFile =
653+
cas::IncludeTree::File::create(DB, PCHFilename, **CASContents);
654+
if (!PCHFile)
655+
return PCHFile.takeError();
656+
PCHRef = PCHFile->getRef();
657+
return llvm::Error::success();
650658
};
651659

652660
if (Error E = FinishIncludeTree())

clang/lib/Tooling/DependencyScanning/ScanAndUpdateArgs.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ void tooling::dependencies::configureInvocationForCaching(
5858
HSOpts.ResourceDir = std::move(OriginalHSOpts.ResourceDir);
5959
// Preserve fmodule-file options.
6060
HSOpts.PrebuiltModuleFiles = std::move(OriginalHSOpts.PrebuiltModuleFiles);
61+
// Preserve -gmodules (see below for caveats).
62+
HSOpts.ModuleFormat = OriginalHSOpts.ModuleFormat;
63+
6164
auto &PPOpts = CI.getPreprocessorOpts();
6265
// We don't need this because we save the contents of the PCH file in the
6366
// include tree root.
@@ -72,12 +75,13 @@ void tooling::dependencies::configureInvocationForCaching(
7275
PPOpts.MacroIncludes.clear();
7376
PPOpts.Includes.clear();
7477
}
75-
// Disable `-gmodules` to avoid debug info referencing a non-existent PCH
76-
// filename.
77-
// NOTE: We'd have to preserve \p HeaderSearchOptions::ModuleFormat (code
78-
// above resets \p HeaderSearchOptions) when properly supporting
79-
// `-gmodules`.
80-
CI.getCodeGenOpts().DebugTypeExtRefs = false;
78+
if (!FrontendOpts.IncludeTreePreservePCHPath) {
79+
// Disable `-gmodules` to avoid debug info referencing a non-existent PCH
80+
// filename.
81+
// FIXME: we should also allow -gmodules if there is no PCH involved.
82+
CI.getCodeGenOpts().DebugTypeExtRefs = false;
83+
HSOpts.ModuleFormat = "raw";
84+
}
8185
// Clear APINotes options.
8286
CI.getAPINotesOpts().ModuleSearchPaths = {};
8387
} else {
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// RUN: split-file %s %t
2+
// RUN: sed -e "s|DIR|%/t|g" %t/cdb_pch.json.template > %t/cdb_pch.json
3+
// RUN: sed -e "s|DIR|%/t|g" %t/cdb.json.template > %t/cdb.json
4+
// RUN: sed -e "s|DIR|%/t|g" %t/cdb_no_preserve.json.template > %t/cdb_no_preserve.json
5+
6+
// RUN: clang-scan-deps -compilation-database %t/cdb_pch.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps_pch.json
7+
// RUN: FileCheck %s -input-file %t/deps_pch.json -DPREFIX=%/t
8+
9+
// CHECK: "-fmodule-format=obj"
10+
// CHECK: "-dwarf-ext-refs"
11+
12+
// RUN: %deps-to-rsp %t/deps_pch.json --tu-index 0 > %t/pch.rsp
13+
// RUN: %clang @%t/pch.rsp
14+
15+
// RUN: clang-scan-deps -compilation-database %t/cdb.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps_tu.json
16+
// RUN: FileCheck %s -input-file %t/deps_tu.json -DPREFIX=%/t
17+
18+
// RUN: %deps-to-rsp %t/deps_tu.json --tu-index 0 > %t/tu.rsp
19+
// RUN: %clang @%t/tu.rsp
20+
21+
// RUN: cat %t/tu.ll | FileCheck %s -check-prefix=LLVMIR -DPREFIX=%/t
22+
// LLVMIR: !DICompileUnit({{.*}}, splitDebugFilename: "prefix.pch"
23+
24+
// Extract include-tree casid
25+
// RUN: cat %t/tu.rsp | sed -E 's|.*"-fcas-include-tree" "(llvmcas://[[:xdigit:]]+)".*|\1|' > %t/tu.casid
26+
27+
// RUN: clang-cas-test -cas %t/cas -print-include-tree @%t/tu.casid | FileCheck %s -check-prefix=INCLUDE_TREE -DPREFIX=%/t
28+
// INCLUDE_TREE: (PCH) [[PREFIX]]/prefix.pch llvmcas://
29+
30+
// RUN: clang-scan-deps -compilation-database %t/cdb_no_preserve.json -format experimental-include-tree-full -cas-path %t/cas > %t/deps_no_preserve.json
31+
// RUN: FileCheck %s -input-file %t/deps_no_preserve.json -DPREFIX=%/t -check-prefix=NO_PRESERVE
32+
33+
// Note: "raw" is the default format, so it will not show up in the arguments.
34+
// NO_PRESERVE-NOT: "-fmodule-format=
35+
// NO_PRESERVE-NOT: "-dwarf-ext-refs"
36+
37+
38+
//--- cdb_pch.json.template
39+
[{
40+
"directory": "DIR",
41+
"command": "clang -x c-header DIR/prefix.h -target x86_64-apple-macos12 -o DIR/prefix.pch -gmodules -g -Xclang -finclude-tree-preserve-pch-path",
42+
"file": "DIR/prefix.h"
43+
}]
44+
45+
//--- cdb.json.template
46+
[{
47+
"directory": "DIR",
48+
"command": "clang -S -emit-llvm DIR/tu.c -o DIR/tu.ll -include-pch DIR/prefix.pch -target x86_64-apple-macos12 -gmodules -g -Xclang -finclude-tree-preserve-pch-path",
49+
"file": "DIR/tu.c"
50+
}]
51+
52+
//--- cdb_no_preserve.json.template
53+
[{
54+
"directory": "DIR",
55+
"command": "clang -S -emit-llvm DIR/tu.c -o DIR/tu.ll -include-pch DIR/prefix.pch -target x86_64-apple-macos12 -gmodules -g",
56+
"file": "DIR/tu.c"
57+
}]
58+
59+
//--- prefix.h
60+
struct S {};
61+
62+
//--- tu.c
63+
struct S s;

clang/test/ClangScanDeps/modules-include-tree-missing-submodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
// CHECK-NOT: Bar
4848

4949
// CHECK-LABEL: TRANSLATION UNIT
50-
// CHECK: (PCH) llvmcas://
50+
// CHECK: (PCH) <PCH> llvmcas://
5151
// CHECK: [[PREFIX]]/tu.c llvmcas://
5252
// CHECK: 1:1 <built-in> llvmcas://
5353
// CHECK: 2:1 (Spurious import) (Module) Foo.Bar [[PREFIX]]/Foo.framework/Headers/Bar.h llvmcas://

clang/test/ClangScanDeps/modules-include-tree-pch-with-private.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
// CHECK: 3:1 (Module) Mod_Private
5454

5555
// CHECK-LABEL: TRANSLATION UNIT
56-
// CHECK: (PCH) llvmcas://
56+
// CHECK: (PCH) <PCH> llvmcas://
5757
// CHECK: [[PREFIX]]/tu.m llvmcas://
5858
// CHECK: 1:1 <built-in> llvmcas://
5959
// CHECK: 2:1 (Module) Mod_Private

0 commit comments

Comments
 (0)