@@ -130,6 +130,18 @@ private UserVariable getPotentialScopeOfVariable_candidate(UserVariable v) {
130130 )
131131}
132132
133+ /** Gets a variable that is in the potential scope of variable `v`. */
134+ private UserVariable getOuterScopesOfVariable_candidate ( UserVariable v ) {
135+ exists ( Scope s |
136+ result = s .getAVariable ( ) and
137+ (
138+ // Variable in an ancestor scope, but only if there are less than 100 variables in this scope
139+ v = s .getAnAncestor ( ) .getAVariable ( ) and
140+ s .getNumberOfVariables ( ) < 100
141+ )
142+ )
143+ }
144+
133145/** Holds if there exists a translation unit that includes both `f1` and `f2`. */
134146pragma [ noinline]
135147predicate inSameTranslationUnit ( File f1 , File f2 ) {
@@ -148,6 +160,15 @@ UserVariable getPotentialScopeOfVariable(UserVariable v) {
148160 inSameTranslationUnit ( v .getFile ( ) , result .getFile ( ) )
149161}
150162
163+ /**
164+ * Gets a user variable which occurs in the "outer scope" of variable `v`.
165+ */
166+ cached
167+ UserVariable getPotentialScopeOfVariableStrict ( UserVariable v ) {
168+ result = getOuterScopesOfVariable_candidate ( v ) and
169+ inSameTranslationUnit ( v .getFile ( ) , result .getFile ( ) )
170+ }
171+
151172/** A file that is a C/C++ source file */
152173class SourceFile extends File {
153174 SourceFile ( ) {
@@ -182,6 +203,15 @@ private predicate hides_candidate(UserVariable v1, UserVariable v2) {
182203 not ( v1 .isMember ( ) or v2 .isMember ( ) )
183204}
184205
206+ /** Holds if `v2` may hide `v1`. */
207+ private predicate hides_candidateStrict ( UserVariable v1 , UserVariable v2 ) {
208+ not v1 = v2 and
209+ v2 = getPotentialScopeOfVariableStrict ( v1 ) and
210+ v1 .getName ( ) = v2 .getName ( ) and
211+ // Member variables cannot hide other variables nor be hidden because the can be referenced through their qualified name.
212+ not ( v1 .isMember ( ) or v2 .isMember ( ) )
213+ }
214+
185215/** Holds if `v2` hides `v1`. */
186216predicate hides ( UserVariable v1 , UserVariable v2 ) {
187217 hides_candidate ( v1 , v2 ) and
@@ -192,6 +222,16 @@ predicate hides(UserVariable v1, UserVariable v2) {
192222 )
193223}
194224
225+ /** Holds if `v2` strictly (`v2` is in an inner scope compared to `v1`) hides `v1`. */
226+ predicate hidesStrict ( UserVariable v1 , UserVariable v2 ) {
227+ hides_candidateStrict ( v1 , v2 ) and
228+ // Confirm that there's no closer candidate variable which `v2` hides
229+ not exists ( UserVariable mid |
230+ hides_candidateStrict ( v1 , mid ) and
231+ hides_candidateStrict ( mid , v2 )
232+ )
233+ }
234+
195235/** Holds if `decl` has namespace scope. */
196236predicate hasNamespaceScope ( Declaration decl ) {
197237 // getNamespace always returns a namespace (e.g. the global namespace).
0 commit comments