Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 34 additions & 2 deletions cpp/ql/lib/semmle/code/cpp/internal/Overlay.qll
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ private string getLocationFilePath(@location_default loc) {
* Gets the file path for an element with a single location.
*/
overlay[local]
private string getSingleLocationFilePath(@element e) {
string getSingleLocationFilePath(@element e) {
exists(@location_default loc |
var_decls(e, _, _, _, loc)
or
Expand All @@ -34,6 +34,38 @@ private string getSingleLocationFilePath(@element e) {
macroinvocations(e, _, loc, _)
or
preprocdirects(e, _, loc)
or
diagnostics(e, _, _, _, _, loc)
or
usings(e, _, loc, _)
or
static_asserts(e, _, _, loc, _)
or
derivations(e, _, _, _, loc)
or
frienddecls(e, _, _, loc)
or
comments(e, _, loc)
or
exprs(e, _, loc)
or
stmts(e, _, loc)
or
initialisers(e, _, _, loc)
or
attributes(e, _, _, _, loc)
or
attribute_args(e, _, _, _, loc)
or
namequalifiers(e, _, _, loc)
or
enumconstants(e, _, _, _, _, loc)
or
type_mentions(e, _, loc, _)
or
lambda_capture(e, _, _, _, _, _, loc)
or
concept_templates(e, _, loc)
|
result = getLocationFilePath(loc)
)
Expand All @@ -43,7 +75,7 @@ private string getSingleLocationFilePath(@element e) {
* Gets the file path for an element with potentially multiple locations.
*/
overlay[local]
private string getMultiLocationFilePath(@element e) {
string getMultiLocationFilePath(@element e) {
exists(@location_default loc |
exists(@var_decl vd | var_decls(vd, e, _, _, loc))
or
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/**
* Provides consistency queries for checking that every database entity
* that can be discarded (i.e. everything but `@compilation` and some external
* entities) in an overlay database is indeed discarded.
*
* This validates that Overlay.qll's `getSingleLocationFilePath` and
* `getMultiLocationFilePath` predicates cover all entity types.
*/

import cpp
private import Overlay

/**
* Holds if `element` is not covered by the discard predicates in Overlay.qll.
*
* This query is intended to flag cases where new entity types are added
* to the dbscheme but the corresponding discard predicate is not updated.
*
* An element is considered covered if it has a path via either
* `getSingleLocationFilePath` or `getMultiLocationFilePath`.
*/
query predicate consistencyTest(Element element, string message) {
(
// Check that every @element has a path via the discard predicates
not exists(getSingleLocationFilePath(element)) and
not exists(getMultiLocationFilePath(element)) and
// Exclude global/synthetic entities that don't need to be discarded
not element instanceof @specifier and
not element instanceof @builtintype and
not element instanceof @derivedtype and
not element instanceof @routinetype and
not element instanceof @ptrtomember and
not element instanceof @decltype and
not element instanceof @type_operator and
not element instanceof @specialnamequalifyingelement and
// Exclude files/folders (handled separately by overlay infrastructure)
not element instanceof @file and
not element instanceof @folder and
// Exclude XML entities (not C++ code)
not element instanceof @xmllocatable and
// Exclude compiler diagnostics (metadata, not source entities)
not element instanceof @diagnostic and
// Exclude usertypes without declarations (compiler built-ins like 'auto', '__va_list')
not (element instanceof @usertype and not exists(@type_decl td | type_decls(td, element, _))) and
// Exclude namespaces without declarations (global namespace)
not (
element instanceof @namespace and
not exists(@namespace_decl nd | namespace_decls(nd, element, _, _))
) and
// Exclude functions without declarations (compiler-generated like implicit operator=)
not (
element instanceof @function and not exists(@fun_decl fd | fun_decls(fd, element, _, _, _))
) and
// Exclude variables without declarations (parameters of compiler-generated functions)
not (
element instanceof @variable and not exists(@var_decl vd | var_decls(vd, element, _, _, _))
) and
exists(Location loc | loc = element.getLocation() |
message =
element.getPrimaryQlClasses() + " at " + loc.getFile().getRelativePath() + ":" +
loc.getStartLine().toString() + " not covered by discard predicates"
)
)
}