@@ -209,7 +209,42 @@ private predicate hides_candidateStrict(UserVariable v1, UserVariable v2) {
209209 v2 = getPotentialScopeOfVariableStrict ( v1 ) and
210210 v1 .getName ( ) = v2 .getName ( ) and
211211 // 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 ( ) )
212+ not ( v1 .isMember ( ) or v2 .isMember ( ) ) and
213+ (
214+ // If v1 is a local variable, ensure that v1 is declared before v2
215+ (
216+ v1 instanceof LocalVariable and
217+ // Ignore variables declared in conditional expressions, as they apply to
218+ // the nested scope
219+ not v1 = any ( ConditionDeclExpr cde ) .getVariable ( ) and
220+ // Ignore variables declared in loops
221+ not exists ( Loop l | l .getADeclaration ( ) = v1 )
222+ )
223+ implies
224+ exists ( BlockStmt bs , DeclStmt v1Stmt , Stmt v2Stmt |
225+ v1 = v1Stmt .getADeclaration ( ) and
226+ getEnclosingStmt ( v2 ) .getParentStmt * ( ) = v2Stmt
227+ |
228+ bs .getIndexOfStmt ( v1Stmt ) <= bs .getIndexOfStmt ( v2Stmt )
229+ )
230+ )
231+ }
232+
233+ /**
234+ * Gets the enclosing statement of the given variable, if any.
235+ */
236+ private Stmt getEnclosingStmt ( LocalScopeVariable v ) {
237+ result .( DeclStmt ) .getADeclaration ( ) = v
238+ or
239+ exists ( ConditionDeclExpr cde |
240+ cde .getVariable ( ) = v and
241+ result = cde .getEnclosingStmt ( )
242+ )
243+ or
244+ exists ( CatchBlock cb |
245+ cb .getParameter ( ) = v and
246+ result = cb .getEnclosingStmt ( )
247+ )
213248}
214249
215250/** Holds if `v2` hides `v1`. */
0 commit comments