Skip to content

Commit 47b3fb2

Browse files
committed
Scope: refactor hides calculation to expose pairs of variables
Behaviour preserving refactor to allow future filtering of invalid pairs of variables during the traversal algorithm. For example, whether a variable declared within a lambda variable hides an outer scope variable depends on the type and nature of the variable. By exposing pairs of candidate variables, we can more easily filter on these conditions.
1 parent 61521e0 commit 47b3fb2

File tree

1 file changed

+33
-21
lines changed

1 file changed

+33
-21
lines changed

cpp/common/src/codingstandards/cpp/Scope.qll

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ class Scope extends Element {
7878

7979
UserVariable getAVariable() { Internal::getParentScope(result) = this }
8080

81+
/**
82+
* Gets the `Variable` with the given `name` that is declared in this scope.
83+
*/
84+
UserVariable getVariable(string name) {
85+
result = getAVariable() and
86+
result.getName() = name
87+
}
88+
8189
int getNumberOfVariables() { result = count(getAVariable()) }
8290

8391
Scope getAnAncestor() { result = this.getStrictParent+() }
@@ -152,9 +160,9 @@ class Scope extends Element {
152160
}
153161

154162
/**
155-
* Gets a variable with `name` which is hidden in at least one nested scope.
163+
* Gets a variable with `name` which is potentially hidden in at least one nested scope.
156164
*/
157-
UserVariable getAHiddenVariable(string name) {
165+
private UserVariable getAPotentiallyHiddenVariable(string name) {
158166
result = getAVariable() and
159167
result.getName() = name and
160168
isDeclaredNameHiddenByChild(name)
@@ -163,34 +171,43 @@ class Scope extends Element {
163171
/**
164172
* Holds if `name` is declared above this scope and hidden by this or a nested scope.
165173
*/
166-
private predicate isNameDeclaredAboveHiddenByThisOrNested(string name) {
167-
(
168-
this.getStrictParent().isDeclaredNameHiddenByChild(name) or
169-
this.getStrictParent().isNameDeclaredAboveHiddenByThisOrNested(name)
174+
UserVariable getAVariableHiddenByThisOrNestedScope(string name) {
175+
exists(Scope parent | parent = this.getStrictParent() |
176+
result = parent.getAPotentiallyHiddenVariable(name) or
177+
result = parent.getAVariableHiddenByThisOrNestedScope(name)
170178
) and
171179
isNameDeclaredInThisOrNestedScope(name)
172180
}
173181

174182
/**
175-
* Gets a variable with `name` which is declared in a scope above this one, and hidden by a variable in this or a
176-
* nested scope.
183+
* Holds if `hiddenVariable` and `hidingVariable` are a candidate hiding pair at this scope.
177184
*/
178-
UserVariable getAHidingVariable(string name) {
179-
isNameDeclaredAboveHiddenByThisOrNested(name) and
185+
private predicate hidesCandidate(
186+
UserVariable hiddenVariable, UserVariable hidingVariable, string name
187+
) {
180188
(
181189
// Declared in this scope
182-
getAVariable().getName() = name and
183-
result = getAVariable() and
184-
result.getName() = name
190+
hidingVariable = getVariable(name) and
191+
hiddenVariable = getAVariableHiddenByThisOrNestedScope(name)
185192
or
186193
// Declared in a child scope
187194
exists(Scope child |
188195
getAChildScope() = child and
189-
child.isNameDeclaredInThisOrNestedScope(name) and
190-
result = child.getAHidingVariable(name)
196+
child.hidesCandidate(hiddenVariable, hidingVariable, name)
191197
)
192198
)
193199
}
200+
201+
/**
202+
* Holds if `hiddenVariable` is declared in this scope and hidden by `hidingVariable`.
203+
*/
204+
predicate hides(UserVariable hiddenVariable, UserVariable hidingVariable, Scope childScope) {
205+
exists(string name |
206+
hiddenVariable = getAPotentiallyHiddenVariable(name) and
207+
childScope = getAChildScope() and
208+
childScope.hidesCandidate(hiddenVariable, hidingVariable, name)
209+
)
210+
}
194211
}
195212

196213
class GeneratedBlockStmt extends BlockStmt {
@@ -247,12 +264,7 @@ class TranslationUnit extends SourceFile {
247264

248265
/** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */
249266
predicate hides_candidateStrict(UserVariable v1, UserVariable v2) {
250-
exists(Scope parentScope, Scope childScope, string name |
251-
v1 = parentScope.getAHiddenVariable(name) and
252-
childScope = parentScope.getAChildScope() and
253-
v2 = childScope.getAHidingVariable(name) and
254-
not v1 = v2
255-
|
267+
exists(Scope parentScope, Scope childScope | parentScope.hides(v1, v2, childScope) |
256268
// If v1 is a local variable defined in a `DeclStmt` ensure that it is declared before `v2`,
257269
// otherwise it would not be hidden
258270
(

0 commit comments

Comments
 (0)