Skip to content

Commit 052e2e7

Browse files
committed
[clang][ScanDeps] Disable header search and VFS opt when using include tree
The FullIncludeTree output format completely subsumes header search and VFS optimizations due to how it works. Disable these optimizations so we're not doing unneeded work. Also test that FullIncludeTree handles VFSs correctly when emitting diagnostics.
1 parent 0a3a556 commit 052e2e7

File tree

3 files changed

+219
-2
lines changed

3 files changed

+219
-2
lines changed

clang/include/clang/Tooling/DependencyScanning/DependencyScanningService.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ enum class ScanningOptimizations {
8080
Macros = 8,
8181

8282
DSS_LAST_BITMASK_ENUM(Macros),
83-
Default = All
83+
Default = All,
84+
FullIncludeTreeIrrelevant = HeaderSearch | VFS,
8485
};
8586

8687
#undef DSS_LAST_BITMASK_ENUM

clang/lib/Tooling/DependencyScanning/DependencyScanningWorker.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,13 @@ class DependencyScanningAction : public tooling::ToolAction {
384384
CASOpts(CASOpts),
385385
EmitDependencyFile(EmitDependencyFile),
386386
DiagGenerationAsCompilation(DiagGenerationAsCompilation),
387-
ModuleName(ModuleName), VerboseOS(VerboseOS) {}
387+
ModuleName(ModuleName), VerboseOS(VerboseOS) {
388+
// The FullIncludeTree output format completely subsumes header search and
389+
// VFS optimizations due to how it works. Disable these optimizations so
390+
// we're not doing unneeded work.
391+
if (Format == ScanningOutputFormat::FullIncludeTree)
392+
this->OptimizeArgs &= ~ScanningOptimizations::FullIncludeTreeIrrelevant;
393+
}
388394

389395
bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation,
390396
FileManager *FileMgr,
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
// Check that tracking of VFSs works with PCH. include-tree disables the VFS
2+
// optimization, but here we check that the same situations work and variants
3+
// are still removed.
4+
// REQUIRES: ondisk_cas
5+
6+
// RUN: rm -rf %t
7+
// RUN: split-file %s %t
8+
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-pch.json.in > %t/build/compile-commands-pch.json
9+
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu.json.in > %t/build/compile-commands-tu.json
10+
// RUN: sed -e "s|DIR|%/t|g" %t/build/compile-commands-tu1.json.in > %t/build/compile-commands-tu1.json
11+
// RUN: sed -e "s|DIR|%/t|g" %t/build/pch-overlay.yaml.in > %t/build/pch-overlay.yaml
12+
13+
// RUN: clang-scan-deps -compilation-database %t/build/compile-commands-pch.json \
14+
// RUN: -format experimental-include-tree-full -cas-path %t/cas \
15+
// RUN: --optimize-args=vfs,header-search > %t/pch-deps.db
16+
// RUN: %deps-to-rsp %t/pch-deps.db --module-name=A > %t/A.rsp
17+
// RUN: %deps-to-rsp %t/pch-deps.db --module-name=B > %t/B.rsp
18+
// RUN: %deps-to-rsp %t/pch-deps.db --tu-index=0 > %t/pch.rsp
19+
// RUN: %clang @%t/A.rsp
20+
// RUN: %clang @%t/B.rsp
21+
// RUN: %clang @%t/pch.rsp
22+
23+
// RUN: clang-scan-deps -compilation-database %t/build/compile-commands-tu.json \
24+
// RUN: -format experimental-include-tree-full -cas-path %t/cas \
25+
// RUN: --optimize-args=vfs,header-search > %t/tu-deps.db
26+
// RUN: %deps-to-rsp %t/tu-deps.db --module-name=C > %t/C.rsp
27+
// RUN: %deps-to-rsp %t/tu-deps.db --tu-index=0 > %t/tu.rsp
28+
// RUN: %clang @%t/C.rsp
29+
// RUN: %clang @%t/tu.rsp
30+
31+
// Next test is to verify that include-tree correctly handles diagnostics
32+
// involving paths that have been VFS remapped.
33+
34+
// RUN: clang-scan-deps -compilation-database %t/build/compile-commands-tu1.json \
35+
// RUN: -format experimental-include-tree-full -cas-path %t/cas \
36+
// RUN: --optimize-args=vfs,header-search > %t/tu1-deps.db
37+
// RUN: %deps-to-rsp %t/tu1-deps.db --tu-index=0 > %t/tu1.rsp
38+
// Reuse existing B
39+
// RUN: %deps-to-rsp %t/tu1-deps.db --module-name=E > %t/E.rsp
40+
// RUN: %deps-to-rsp %t/tu1-deps.db --module-name=D > %t/D.rsp
41+
// The build of D depends on B which depend on the prebuilt A. D will only build
42+
// if it has A's VFS, as it needs to emit a diagnostic showing the content of A.
43+
// RUN: %clang @%t/E.rsp
44+
// RUN: %clang @%t/D.rsp -verify
45+
// RUN: %clang @%t/tu1.rsp
46+
// RUN: cat %t/tu1-deps.db | sed 's:\\\\\?:/:g' | FileCheck %s -DPREFIX=%/t
47+
48+
// Check that D has the overlay, but E doesn't.
49+
// CHECK: {
50+
// CHECK-NEXT: "modules": [
51+
// CHECK-NEXT: {
52+
// CHECK-NEXT: "cache-key"
53+
// CHECK-NEXT: "cas-include-tree-id"
54+
// CHECK-NEXT: "clang-module-deps": [
55+
// CHECK-NEXT: {
56+
// CHECK-NEXT: "context-hash": "{{.*}}",
57+
// CHECK-NEXT: "module-name": "E"
58+
// CHECK-NEXT: }
59+
// CHECK-NEXT: ],
60+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/modules/D/module.modulemap",
61+
// CHECK-NEXT: "command-line": [
62+
// CHECK-NOT: "-ivfsoverlay"
63+
// CHECK: ],
64+
// CHECK-NEXT: "context-hash": "{{.*}}",
65+
// CHECK-NEXT: "file-deps": [
66+
// CHECK: ],
67+
// CHECK: "name": "D"
68+
// CHECK-NEXT: },
69+
// CHECK-NEXT: {
70+
// CHECK-NEXT: "cache-key"
71+
// CHECK-NEXT: "cas-include-tree-id"
72+
// CHECK-NEXT: "clang-module-deps": [],
73+
// CHECK-NEXT: "clang-modulemap-file": "[[PREFIX]]/modules/E/module.modulemap",
74+
// CHECK-NEXT: "command-line": [
75+
// CHECK-NOT: "-ivfsoverlay"
76+
// CHECK: ],
77+
// CHECK-NEXT: "context-hash": "{{.*}}",
78+
// CHECK-NEXT: "file-deps": [
79+
// CHECK: ],
80+
// CHECK: "name": "E"
81+
// CHECK-NEXT: }
82+
83+
//--- build/compile-commands-pch.json.in
84+
85+
[
86+
{
87+
"directory": "DIR",
88+
"command": "clang -x objective-c-header DIR/pch.h -I DIR/modules/A -I DIR/modules/B -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -o DIR/pch.h.pch -ivfsoverlay DIR/build/pch-overlay.yaml",
89+
"file": "DIR/pch.h"
90+
}
91+
]
92+
93+
//--- build/compile-commands-tu.json.in
94+
95+
[
96+
{
97+
"directory": "DIR",
98+
"command": "clang -fsyntax-only DIR/tu.m -I DIR/modules/A -I DIR/modules/B -I DIR/modules/C -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu.o -ivfsoverlay DIR/build/pch-overlay.yaml",
99+
"file": "DIR/tu.m"
100+
}
101+
]
102+
103+
//--- build/compile-commands-tu1.json.in
104+
105+
[
106+
{
107+
"directory": "DIR",
108+
"command": "clang -fsyntax-only DIR/tu1.m -I DIR/modules/B -I DIR/modules/D -I DIR/modules/E -fmodules -fimplicit-module-maps -fmodules-cache-path=DIR/cache -include DIR/pch.h -o DIR/tu1.o -ivfsoverlay DIR/build/pch-overlay.yaml",
109+
"file": "DIR/tu1.m"
110+
}
111+
]
112+
113+
//--- build/pch-overlay.yaml.in
114+
115+
{
116+
"version":0,
117+
"case-sensitive":"false",
118+
"roots":[
119+
{
120+
"contents":[
121+
{
122+
"external-contents":"DIR/build/module.modulemap",
123+
"name":"module.modulemap",
124+
"type":"file"
125+
},
126+
{
127+
"external-contents":"DIR/build/A.h",
128+
"name":"A.h",
129+
"type":"file"
130+
}
131+
],
132+
"name":"DIR/modules/A",
133+
"type":"directory"
134+
}
135+
]
136+
}
137+
138+
//--- pch.h
139+
#include <B.h>
140+
141+
//--- build/module.modulemap
142+
143+
module A {
144+
umbrella header "A.h"
145+
}
146+
147+
//--- build/A.h
148+
149+
typedef int A_t __attribute__((deprecated("yep, it's depr")));
150+
151+
//--- modules/B/module.modulemap
152+
153+
module B {
154+
umbrella header "B.h"
155+
export *
156+
}
157+
158+
//--- modules/B/B.h
159+
#include <A.h>
160+
161+
typedef int B_t;
162+
163+
//--- modules/C/module.modulemap
164+
165+
module C {
166+
umbrella header "C.h"
167+
}
168+
169+
//--- modules/C/C.h
170+
#include <B.h>
171+
172+
typedef int C_t;
173+
174+
//--- tu.m
175+
176+
#include <C.h>
177+
178+
A_t a = 0;
179+
B_t b = 0;
180+
C_t c = 0;
181+
182+
//--- modules/D/module.modulemap
183+
184+
module D {
185+
umbrella header "D.h"
186+
export *
187+
}
188+
189+
//--- modules/D/D.h
190+
#include <B.h>
191+
#include <E.h>
192+
193+
typedef A_t D_t; // expected-warning{{'A_t' is deprecated}}
194+
// expected-note@*:* {{marked deprecated here}}
195+
196+
//--- modules/E/module.modulemap
197+
198+
module E {
199+
umbrella header "E.h"
200+
}
201+
202+
//--- modules/E/E.h
203+
typedef int E_t;
204+
205+
//--- tu1.m
206+
207+
#include <D.h>
208+
209+
D_t d = 0;
210+
E_t e = 0;

0 commit comments

Comments
 (0)