Skip to content

Commit 44de113

Browse files
committed
C/C++ overlay: use TRAP/tag-based entity discard strategy
1 parent bd0d69f commit 44de113

File tree

1 file changed

+50
-90
lines changed

1 file changed

+50
-90
lines changed
Lines changed: 50 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
/**
22
* Defines entity discard predicates for C++ overlay analysis.
3+
*
4+
* The discard strategy is based on TRAP file and tag tracking rather than
5+
* source locations. The extractor records which TRAP file or tag each element
6+
* is defined in (`in_trap_or_tag`), which source files use which TRAP files
7+
* (`source_file_uses_trap`), and which TRAP files use which tags
8+
* (`trap_uses_tag`). These relations allow us to precisely determine whether
9+
* a base element should be discarded or retained in the combined database.
310
*/
411

512
private import OverlayXml
@@ -12,111 +19,64 @@ private import OverlayXml
1219
overlay[local]
1320
predicate isOverlay() { databaseMetadata("isOverlay", "true") }
1421

15-
overlay[local]
16-
private string getLocationFilePath(@location_default loc) {
17-
exists(@file file | locations_default(loc, file, _, _, _, _) | files(file, result))
18-
}
19-
20-
/**
21-
* Gets the file path for an element with a single location.
22-
*/
23-
overlay[local]
24-
private string getSingleLocationFilePath(@element e) {
25-
exists(@location_default loc |
26-
var_decls(e, _, _, _, loc)
27-
or
28-
fun_decls(e, _, _, _, loc)
29-
or
30-
type_decls(e, _, loc)
31-
or
32-
namespace_decls(e, _, loc, _)
33-
or
34-
macroinvocations(e, _, loc, _)
35-
or
36-
preprocdirects(e, _, loc)
37-
or
38-
diagnostics(e, _, _, _, _, loc)
39-
or
40-
usings(e, _, loc, _)
41-
or
42-
static_asserts(e, _, _, loc, _)
43-
or
44-
derivations(e, _, _, _, loc)
45-
or
46-
frienddecls(e, _, _, loc)
47-
or
48-
comments(e, _, loc)
49-
or
50-
exprs(e, _, loc)
51-
or
52-
stmts(e, _, loc)
53-
or
54-
initialisers(e, _, _, loc)
55-
or
56-
attributes(e, _, _, _, loc)
57-
or
58-
attribute_args(e, _, _, _, loc)
59-
or
60-
namequalifiers(e, _, _, loc)
61-
or
62-
enumconstants(e, _, _, _, _, loc)
63-
or
64-
type_mentions(e, _, loc, _)
65-
or
66-
lambda_capture(e, _, _, _, _, _, loc)
67-
or
68-
concept_templates(e, _, loc)
69-
|
70-
result = getLocationFilePath(loc)
71-
)
72-
}
73-
7422
/**
75-
* Gets the file path for an element with potentially multiple locations.
23+
* Holds if TRAP file or tag `t` is reachable from a source file named
24+
* `source_file` in the given variant (base or overlay).
25+
*
26+
* A TRAP file is directly reachable from its source file. A tag is reachable
27+
* if the TRAP file that uses it is reachable.
7628
*/
7729
overlay[local]
78-
private string getMultiLocationFilePath(@element e) {
79-
exists(@location_default loc |
80-
var_decls(_, e, _, _, loc)
81-
or
82-
fun_decls(_, e, _, _, loc)
83-
or
84-
type_decls(_, e, loc)
85-
or
86-
namespace_decls(_, e, loc, _)
87-
|
88-
result = getLocationFilePath(loc)
30+
private predicate locallyReachableTrapOrTag(
31+
boolean isOverlayVariant, string source_file, @trap_or_tag t
32+
) {
33+
exists(@source_file sf, string source_file_raw, @trap trap |
34+
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
35+
source_file_uses_trap(sf, trap) and
36+
source_file_name(sf, source_file_raw) and
37+
source_file = source_file_raw.replaceAll("\\", "/") and
38+
(t = trap or trap_uses_tag(trap, t))
8939
)
9040
}
9141

9242
/**
93-
* A local helper predicate that holds in the base variant and never in the
94-
* overlay variant.
95-
*/
96-
overlay[local]
97-
private predicate isBase() { not isOverlay() }
98-
99-
/**
100-
* Holds if `path` was extracted in the overlay database.
43+
* Holds if element `e` is defined in TRAP file or tag `t` in the given
44+
* variant (base or overlay).
10145
*/
10246
overlay[local]
103-
private predicate overlayHasFile(string path) {
104-
isOverlay() and
105-
files(_, path) and
106-
path != ""
47+
private predicate locallyInTrapOrTag(boolean isOverlayVariant, @element e, @trap_or_tag t) {
48+
(if isOverlay() then isOverlayVariant = true else isOverlayVariant = false) and
49+
in_trap_or_tag(e, t)
10750
}
10851

10952
/**
11053
* Discards an element from the base variant if:
111-
* - It has a single location in a file extracted in the overlay, or
112-
* - All of its locations are in files extracted in the overlay.
54+
* - It is known to be in a base TRAP file or tag, and
55+
* - It is not reachable from any overlay source file, and
56+
* - Every base source file that reaches it has either changed or had its TRAP
57+
* file redefined by the overlay.
11358
*/
11459
overlay[discard_entity]
11560
private predicate discardElement(@element e) {
116-
isBase() and
117-
(
118-
overlayHasFile(getSingleLocationFilePath(e))
119-
or
120-
forex(string path | path = getMultiLocationFilePath(e) | overlayHasFile(path))
61+
// If we don't have any knowledge about what TRAP file something
62+
// is in, then we don't want to discard it, so we only consider
63+
// entities that are known to be in a base TRAP file.
64+
locallyInTrapOrTag(false, e, _) and
65+
// Anything that is reachable from an overlay source file should
66+
// not be discarded.
67+
not exists(@trap_or_tag t | locallyInTrapOrTag(true, e, t) |
68+
locallyReachableTrapOrTag(true, _, t)
69+
) and
70+
// Finally, we have to make sure that base shouldn't retain it.
71+
// If it is reachable from a base source file, then that is
72+
// sufficient unless either the base source file has changed (in
73+
// particular, been deleted) or the overlay has redefined the TRAP
74+
// file it is in.
75+
forall(@trap_or_tag t, string source_file |
76+
locallyInTrapOrTag(false, e, t) and
77+
locallyReachableTrapOrTag(false, source_file, t)
78+
|
79+
overlayChangedFiles(source_file) or
80+
locallyReachableTrapOrTag(true, _, t)
12181
)
12282
}

0 commit comments

Comments
 (0)