Skip to content
Merged
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
13 changes: 13 additions & 0 deletions ql/ql/src/codeql_ql/ast/Ast.qll
Original file line number Diff line number Diff line change
Expand Up @@ -2554,6 +2554,10 @@ private class LocalQArg extends AnnotationArg {
LocalQArg() { this.getValue() = "local?" }
}

private class DiscardEntityArg extends AnnotationArg {
DiscardEntityArg() { this.getValue() = "discard_entity" }
}

private class MonotonicAggregatesArg extends AnnotationArg {
MonotonicAggregatesArg() { this.getValue() = "monotonicAggregates" }
}
Expand Down Expand Up @@ -2641,6 +2645,15 @@ class OverlayLocalQ extends Annotation {
override string toString() { result = "overlay[local?]" }
}

/** An `overlay[discard_entity]` annotation. */
class OverlayDiscardEntity extends Annotation {
OverlayDiscardEntity() {
this.getName() = "overlay" and this.getArgs(0) instanceof DiscardEntityArg
}

override string toString() { result = "overlay[discard_entity]" }
}

/** A `language[monotonicAggregates]` annotation. */
class MonotonicAggregates extends Annotation {
MonotonicAggregates() { this.getArgs(0) instanceof MonotonicAggregatesArg }
Expand Down
12 changes: 10 additions & 2 deletions ql/ql/src/codeql_ql/style/DeadCodeQuery.qll
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ private AstNode queryPredicate() {
result = queryPredicate().getAChild()
}

private AstNode discardPredicate() {
result.(Predicate).getAnAnnotation() instanceof OverlayDiscardEntity
}

AstNode hackyShouldBeTreatedAsAlive() {
// Stages from the shared DataFlow impl are copy-pasted, so predicates that are dead in one stage are not dead in another.
result = any(Module mod | mod.getName().matches("Stage%")).getAMember().(ClasslessPredicate) and
Expand All @@ -58,7 +62,7 @@ AstNode hackyShouldBeTreatedAsAlive() {
*/
private AstNode alive() {
//
// The 4 base cases.
// The 6 base cases.
//
// 1) everything that can be imported.
result = publicApi()
Expand All @@ -73,7 +77,11 @@ private AstNode alive() {
// 4) Things that aren't really alive, but that this query treats as live.
result = hackyShouldBeTreatedAsAlive()
or
result instanceof TopLevel // toplevel is always alive.
// 5) discard predicates
result = discardPredicate()
or
// 6) toplevel is always alive.
result instanceof TopLevel
or
// recursive cases
result = aliveStep(alive())
Expand Down
3 changes: 3 additions & 0 deletions ql/ql/test/queries/style/DeadCode/Foo.qll
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,6 @@ private class CImpl1 extends AstNode { }
final class CPublic1 = CImpl1;

private class CImpl2 extends AstNode { }

overlay[discard_entity]
private predicate discard(@foo x) { any() }
Loading