Skip to content

Commit 3d0b937

Browse files
committed
Fix FP for issue 214
exclude variable templates and fix case where same scope identifiers are considered
1 parent 466eae8 commit 3d0b937

File tree

5 files changed

+53
-1
lines changed

5 files changed

+53
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* `A12-10-1` and `RULE-5-3` - reduce false positives reported for identifiers in same scope, and (relevant for `A12-10-1` only) omitted false positives for template variables

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

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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`. */
134146
pragma[noinline]
135147
predicate 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 */
152173
class 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`. */
186216
predicate 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. */
196236
predicate hasNamespaceScope(Declaration decl) {
197237
// getNamespace always returns a namespace (e.g. the global namespace).

cpp/common/src/codingstandards/cpp/rules/identifierhidden/IdentifierHidden.qll

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,10 @@ Query getQuery() { result instanceof IdentifierHiddenSharedQuery }
1414
query predicate problems(UserVariable v2, string message, UserVariable v1, string varName) {
1515
not isExcluded(v1, getQuery()) and
1616
not isExcluded(v2, getQuery()) and
17-
hides(v1, v2) and
17+
//ignore template variables for this rule
18+
not v1 instanceof TemplateVariable and
19+
not v2 instanceof TemplateVariable and
20+
hidesStrict(v1, v2) and
1821
varName = v1.getName() and
1922
message = "Variable is hiding variable $@."
2023
}

cpp/common/test/rules/identifierhidden/test.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,10 @@ void f3() {
2727
for (int id1; id1 < 1; id1++) {
2828
} // NON_COMPLIANT
2929
}
30+
}
31+
32+
template <typename T> constexpr bool foo = false; // COMPLIANT
33+
34+
namespace {
35+
template <typename T> bool foo<T> = true; // COMPLIANT
3036
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
template <typename T> constexpr bool foo = false; // COMPLIANT
2+
template <typename T> constexpr bool foo<T> = true; // COMPLIANT

0 commit comments

Comments
 (0)