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
512private import OverlayXml
@@ -12,111 +19,64 @@ private import OverlayXml
1219overlay [ local]
1320predicate 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 */
7729overlay [ 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 */
10246overlay [ 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 */
11459overlay [ discard_entity]
11560private 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